24#ifdef WITH_OPENGL_BACKEND
28#ifdef WITH_VULKAN_BACKEND
36#ifdef WITH_GHOST_WAYLAND_DYNLOAD
40#ifdef WITH_OPENGL_BACKEND
41# ifdef WITH_GHOST_WAYLAND_DYNLOAD
44# include <wayland-egl.h>
51#include <unordered_map>
52#include <unordered_set>
54#ifdef WITH_GHOST_WAYLAND_DYNLOAD
57#include <wayland-cursor.h>
59#include <xkbcommon/xkbcommon-compose.h>
60#include <xkbcommon/xkbcommon.h>
63#include <fractional-scale-v1-client-protocol.h>
64#include <pointer-constraints-unstable-v1-client-protocol.h>
65#include <pointer-gestures-unstable-v1-client-protocol.h>
66#include <primary-selection-unstable-v1-client-protocol.h>
67#include <relative-pointer-unstable-v1-client-protocol.h>
68#include <tablet-unstable-v2-client-protocol.h>
69#include <viewporter-client-protocol.h>
70#include <xdg-activation-v1-client-protocol.h>
71#include <xdg-output-unstable-v1-client-protocol.h>
73# include <text-input-unstable-v3-client-protocol.h>
77#include <xdg-decoration-unstable-v1-client-protocol.h>
78#include <xdg-shell-client-protocol.h>
98#ifdef USE_EVENT_BACKGROUND_THREAD
102#ifdef WITH_GHOST_WAYLAND_LIBDECOR
103static bool use_libdecor =
true;
104# ifdef WITH_GHOST_WAYLAND_DYNLOAD
105static bool has_libdecor =
false;
107static bool has_libdecor =
true;
135 int *r_interface_slot);
144 xkb_compose_state *compose_state,
146 const xkb_keycode_t key,
149#ifdef USE_EVENT_BACKGROUND_THREAD
161#define pushEvent DONT_USE
176#define USE_GNOME_CONFINE_HACK
183#ifdef USE_GNOME_CONFINE_HACK
192#define USE_KDE_TABLET_HIDDEN_CURSOR_HACK
217#ifdef USE_VERBOSE_OLD_IFACE_PRINT
218# define _VERBOSE_OLD_IFACE_PRINT(params_version, version_max) \
219 ((params_version > version_max) ? \
221 "%s: version_max=%u, is smaller than run-time version=%u\n", \
227# define _VERBOSE_OLD_IFACE_PRINT(params_version, version_max) \
228 ((void)(params_version), (version_max))
231#define GWL_IFACE_VERSION_CLAMP(params_version, version_min, version_max) \
232 ((void)_VERBOSE_OLD_IFACE_PRINT(params_version, version_max), \
233 std::clamp(params_version, version_min, version_max))
239#define USE_NON_LATIN_KB_WORKAROUND
241#define WL_NAME_UNSET uint32_t(-1)
247#define WL_FIXED_TO_INT_FOR_WINDOW_V2(win, xy) \
248 wl_fixed_to_int((win)->wl_fixed_to_window((xy)[0])), \
249 wl_fixed_to_int((win)->wl_fixed_to_window((xy)[1])),
275#define BTN_RANGE_MIN BTN_LEFT
276#define BTN_RANGE_MAX BTN_BACK
309#ifdef USE_NON_LATIN_KB_WORKAROUND
337#define MOD_INDEX_NUM (MOD_INDEX_OS + 1)
394 const char *data =
nullptr;
400 free(
const_cast<char *
>(buffer->
data));
401 buffer->
data =
nullptr;
407 free(
const_cast<char *
>(buffer->
data));
409 char *data =
static_cast<char *
>(malloc(buffer->
data_size));
424#define EVDEV_OFFSET 8
440 wl_cursor_image image = {0};
510#define GWL_TabletTool_FrameTypes_NUM (int(GWL_TabletTool_EventTypes::Stylus3_Up) + 1)
565 const int ty_mask = 1 <<
int(ty);
594 wl_data_offer *
id =
nullptr;
597 std::unordered_set<std::string>
types;
611 enum wl_data_device_manager_dnd_action
source_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
612 enum wl_data_device_manager_dnd_action
action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
614 wl_fixed_t
xy[2] = {0, 0};
698 wl_fixed_t
xy[2] = {0, 0};
701 std::unordered_set<const GWL_Output *>
outputs;
746#define GWL_SeatStatePointer_EventTypes_NUM (int(GWL_Pointer_EventTypes::Button6_Up) + 1)
785 GHOST_ASSERT(event_ms == 0,
"Scroll events must not have a time-stamp");
788 GHOST_ASSERT(event_ms != 0,
"Non-scroll events must have a time-stamp");
791 const int ty_mask = 1 <<
int(ty);
833 enum wl_pointer_axis_source
axis_source = WL_POINTER_AXIS_SOURCE_WHEEL;
857 wl_fixed_t value = 0;
858 wl_fixed_t factor = 1;
862 const wl_fixed_t add)
864 const int result_prev = wl_fixed_to_int(sf->
value * sf->
factor);
866 const int result_curr = wl_fixed_to_int(sf->
value * sf->
factor);
867 return result_curr - result_prev;
906#ifdef WITH_GHOST_WAYLAND_LIBDECOR
907struct GWL_LibDecor_System {
908 libdecor *context =
nullptr;
911static void gwl_libdecor_system_destroy(GWL_LibDecor_System *decor)
913 if (decor->context) {
915 decor->context =
nullptr;
925 zxdg_decoration_manager_v1 *
manager =
nullptr;
946 zwp_primary_selection_offer_v1 *
id =
nullptr;
949 std::unordered_set<std::string>
types;
956 zwp_primary_selection_source_v1 *
source =
nullptr;
974 if (primary->data_offer ==
nullptr) {
977 zwp_primary_selection_offer_v1_destroy(primary->data_offer->wp.id);
978 delete primary->data_offer;
979 primary->data_offer =
nullptr;
985 if (data_source ==
nullptr) {
990 zwp_primary_selection_source_v1_destroy(data_source->
wp.
source);
992 delete primary->data_source;
993 primary->data_source =
nullptr;
1021 bool has_preedit =
false;
1026 std::string composite;
1029 bool result_is_null =
false;
1031 bool composite_is_null =
false;
1034 bool has_preedit_string_callback =
false;
1036 bool has_commit_string_callback =
false;
1065#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
1066 zwp_pointer_gesture_hold_v1 *pointer_gesture_hold =
nullptr;
1068#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE
1071#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE
1072 zwp_pointer_gesture_swipe_v1 *pointer_gesture_swipe =
nullptr;
1084#ifdef WITH_INPUT_IME
1085 zwp_text_input_v3 *text_input =
nullptr;
1091 xkb_context *context =
nullptr;
1122#ifdef WITH_INPUT_IME
1144#ifdef USE_GNOME_CONFINE_HACK
1152#ifdef USE_NON_LATIN_KB_WORKAROUND
1230 GHOST_ASSERT(0,
"Surface found without pointer/tablet tag");
1248 xkb_state_update_mask(seat->
xkb.
state_empty, 0, 0, 0, 0, 0, group);
1252 "Invalid state for SHIFT");
1258 GHOST_ASSERT((mod_mod2 == XKB_MOD_INVALID || mod_numlock == XKB_MOD_INVALID) ==
1260 "Invalid state for NUMLOCK");
1262 xkb_state_update_mask(
1274 if (
UNLIKELY(wl_surface_focus ==
nullptr)) {
1291 xkb_state_key_get_utf8(seat->
xkb.
state, payload->
key_code, utf8_buf,
sizeof(utf8_buf));
1304 const bool use_delay)
1313#ifdef USE_EVENT_BACKGROUND_THREAD
1315 time_now + time_start, time_step, key_repeat_fn, payload);
1329#ifdef USE_EVENT_BACKGROUND_THREAD
1338#ifdef WITH_INPUT_IME
1340static void gwl_seat_ime_full_reset(
GWL_Seat *seat)
1342 const GWL_SeatIME ime_default{};
1345 wl_surface *surface_window = seat->ime.surface_window;
1346 const bool is_enabled = seat->ime.is_enabled;
1347 const bool has_preedit_string_callback = seat->ime.has_preedit_string_callback;
1348 const bool has_commit_string_callback = seat->ime.has_commit_string_callback;
1350 seat->ime = ime_default;
1352 seat->ime.surface_window = surface_window;
1354 seat->ime.has_preedit_string_callback = has_preedit_string_callback;
1355 seat->ime.has_commit_string_callback = has_commit_string_callback;
1358static void gwl_seat_ime_result_reset(
GWL_Seat *seat)
1360 seat->ime.result.clear();
1361 seat->ime.result_is_null =
false;
1365 event_ime_data.
result =
nullptr;
1368static void gwl_seat_ime_preedit_reset(
GWL_Seat *seat)
1370 seat->ime.composite.clear();
1371 seat->ime.composite_is_null =
false;
1382static void gwl_seat_ime_rect_reset(
GWL_Seat *seat)
1384 seat->ime.rect.x = -1;
1385 seat->ime.rect.y = -1;
1386 seat->ime.rect.w = -1;
1387 seat->ime.rect.h = -1;
1422 wl_compositor *compositor =
nullptr;
1439#ifdef WITH_INPUT_IME
1440 zwp_text_input_manager_v3 *text_input_manager =
nullptr;
1464#ifdef WITH_GHOST_WAYLAND_LIBDECOR
1465 GWL_LibDecor_System *libdecor =
nullptr;
1490#ifdef USE_EVENT_BACKGROUND_THREAD
1528#ifdef USE_EVENT_BACKGROUND_THREAD
1529 if (display->events_pthread) {
1531 display->events_pthread_is_active =
false;
1536 for (
GWL_Seat *seat : display->seats) {
1542 if (display->wl.registry) {
1543 wl_registry_destroy(display->wl.registry);
1544 display->wl.registry =
nullptr;
1550#ifdef WITH_GHOST_WAYLAND_LIBDECOR
1552 if (display->libdecor) {
1553 gwl_libdecor_system_destroy(display->libdecor);
1554 display->libdecor =
nullptr;
1560 if (display->xdg_decor) {
1562 display->xdg_decor =
nullptr;
1566#ifdef WITH_OPENGL_BACKEND
1567 if (display->wl.display) {
1568 if (eglGetDisplay) {
1569 ::eglTerminate(eglGetDisplay(EGLNativeDisplayType(display->wl.display)));
1574#ifdef USE_EVENT_BACKGROUND_THREAD
1575 if (display->events_pthread) {
1577 display->system->server_mutex->unlock();
1581 if (display->ghost_timer_manager) {
1582 delete display->ghost_timer_manager;
1583 display->ghost_timer_manager =
nullptr;
1586 for (
const GHOST_IEvent *event : display->events_pending) {
1592 if (display->wl.display) {
1601 std::vector<GWL_Seat *>::iterator iter = std::find(
1602 display->seats.begin(), display->seats.end(), seat);
1603 const int index = (iter != display->seats.cend()) ? std::distance(display->seats.begin(), iter) :
1618 if (
UNLIKELY(display->seats.empty())) {
1621 return display->seats[display->seats_active_index];
1626 if (
UNLIKELY(display->seats.empty())) {
1630 if (index == display->seats_active_index) {
1633 display->seats_active_index = index;
1748 reg->
next = display->registry_entry;
1749 display->registry_entry = reg;
1754 int *r_interface_slot)
1760 if (r_interface_slot) {
1761 *r_interface_slot = -1;
1765 if (reg->
name == name) {
1770 if (r_interface_slot) {
1774 *reg_link_p = reg_next;
1778 reg_link_p = ®->
next;
1799 *reg_link_p = reg_next;
1804 reg_link_p = ®->
next;
1815 const bool on_exit =
true;
1829 while (interface_slot--) {
1833 GHOST_ASSERT(display->registry_entry ==
nullptr,
"Failed to remove all entries!");
1834 display->registry_entry =
nullptr;
1855 GHOST_ASSERT(interface_slot_exclude == -1 || (
uint(interface_slot_exclude) <
1857 "Invalid exclude slot");
1860 if (reg->interface_slot == interface_slot_exclude) {
1864 reg->interface_slot);
1871 params.interface_slot = reg->interface_slot;
1872 params.version = reg->version;
1873 params.user_data = reg->user_data;
1885#ifdef WITH_GHOST_WAYLAND_LIBDECOR
1886static const char *strchr_or_end(
const char *
str,
const char ch)
1888 const char *p =
str;
1889 while (!
ELEM(*p, ch,
'\0')) {
1895static bool string_elem_split_by_delim(
const char *haystack,
const char delim,
const char *needle)
1900 const size_t needle_len = strlen(needle);
1901 const char *p = haystack, *p_next;
1903 p_next = strchr_or_end(p, delim);
1904 if ((
size_t(p_next - p) == needle_len) && (memcmp(p, needle, needle_len) == 0)) {
1907 if (*p_next ==
'\0') {
1918 return a >
b ? a -
b :
b - a;
1934 const char *locale = getenv(
"LC_ALL");
1935 if (!locale || !*locale) {
1936 locale = getenv(
"LC_CTYPE");
1937 if (!locale || !*locale) {
1938 locale = getenv(
"LANG");
1939 if (!locale || !*locale) {
1950 if (
ELEM(ecode, EPIPE, ECONNRESET)) {
1951 fprintf(stderr,
"The Wayland connection broke. Did the Wayland compositor die?\n");
1955 if (ecode == EPROTO) {
1956 const wl_interface *
interface = nullptr;
1959 "The Wayland connection experienced a protocol error %d in interface: %s\n",
1961 interface ? interface->name :
"<nil>");
1962 const char *env_debug =
"WAYLAND_DEBUG";
1963 if (getenv(env_debug) ==
nullptr) {
1964 fprintf(stderr,
"Run with the environment variable \"%s=1\" for details.\n", env_debug);
1969 fprintf(stderr,
"The Wayland connection experienced a fatal error: %s\n", strerror(ecode));
2020 (strstr(msg,
"error: XDG_RUNTIME_DIR not set in the environment") ||
2021 strstr(msg,
"error: XDG_RUNTIME_DIR is invalid or not set in the environment")))
2026 fprintf(stderr,
"GHOST/Wayland: ");
2027 vfprintf(stderr, msg, arg);
2031 backtrace_fn(stderr);
2035#if defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND_LIBDECOR)
2041static bool ghost_wayland_is_x11_available()
2043 const char *x11_display = getenv(
"DISPLAY");
2044 if (x11_display && x11_display[0]) {
2055 if (sym >= XKB_KEY_0 && sym <= XKB_KEY_9) {
2058 else if (sym >= XKB_KEY_KP_0 && sym <= XKB_KEY_KP_9) {
2061 else if (sym >= XKB_KEY_A && sym <= XKB_KEY_Z) {
2064 else if (sym >= XKB_KEY_a && sym <= XKB_KEY_z) {
2065 gkey =
GHOST_TKey(sym - XKB_KEY_a + XKB_KEY_A);
2067 else if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F24) {
2072#define GXMAP(k, x, y) \
2183 "unhandled key: " << std::hex << std::showbase << sym <<
2184 std::dec <<
" (" << sym <<
"), " <<
2186 "scan-code: " << std::hex << std::showbase << key <<
2187 std::dec <<
" (" << key <<
")" <<
2200 case WL_POINTER_AXIS_HORIZONTAL_SCROLL: {
2203 case WL_POINTER_AXIS_VERTICAL_SCROLL: {
2214 switch (wp_tablet_tool_type) {
2215 case ZWP_TABLET_TOOL_V2_TYPE_ERASER: {
2218 case ZWP_TABLET_TOOL_V2_TYPE_PEN:
2219 case ZWP_TABLET_TOOL_V2_TYPE_BRUSH:
2220 case ZWP_TABLET_TOOL_V2_TYPE_PENCIL:
2221 case ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH:
2222 case ZWP_TABLET_TOOL_V2_TYPE_FINGER:
2223 case ZWP_TABLET_TOOL_V2_TYPE_MOUSE:
2224 case ZWP_TABLET_TOOL_V2_TYPE_LENS: {
2229 GHOST_PRINT(
"unknown tablet tool: " << wp_tablet_tool_type << std::endl);
2242#define CASE_CURSOR(shape_id, shape_name_in_theme) \
2244 info.names[int(shape_id)] = shape_name_in_theme;
2320 "text/plain;charset=utf-8",
2324#ifdef USE_EVENT_BACKGROUND_THREAD
2328 sched_param sch_params;
2329 if (pthread_getschedparam(handle, &policy, &sch_params) == 0) {
2330 sch_params.sched_priority = sched_get_priority_min(policy);
2331 pthread_setschedparam(handle, policy, &sch_params);
2337 constexpr bool is_pthread = std::is_same<std::thread::native_handle_type, pthread_t>();
2349#ifdef HAVE_MEMFD_CREATE
2350 const int fd = memfd_create(name, MFD_CLOEXEC | MFD_ALLOW_SEALING);
2352 fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
2356 char *path = getenv(
"XDG_RUNTIME_DIR");
2362 asprintf(&tmpname,
"%s/%s-XXXXXX", path, name);
2363 const int fd = mkostemp(tmpname, O_CLOEXEC);
2372#if defined(WITH_GHOST_WAYLAND_LIBDECOR) && defined(WITH_VULKAN_BACKEND)
2373int memfd_create_sealed_for_vulkan_hack(
const char *name)
2399 info.events |= POLLIN | POLLPRI;
2402 info.events |= POLLOUT;
2404 result = poll(&info, 1, timeout_ms);
2406 fd_set rfdset, *rfdp =
nullptr;
2407 fd_set wfdset, *wfdp =
nullptr;
2408 struct timeval tv, *tvp =
nullptr;
2415 FD_SET(fd, &rfdset);
2420 FD_SET(fd, &wfdset);
2424 if (timeout_ms >= 0) {
2425 tv.tv_sec = timeout_ms / 1000;
2426 tv.tv_usec = (timeout_ms % 1000) * 1000;
2430 result =
select(fd + 1, rfdp, wfdp,
nullptr, tvp);
2463#ifdef USE_EVENT_BACKGROUND_THREAD
2473 server_mutex->lock();
2479 }
while (
state == 0);
2484 std::mutex *server_mutex)
2487 server_mutex->lock();
2490 bool wait_on_fd =
false;
2501 server_mutex->unlock();
2509 server_mutex->unlock();
2515 server_mutex->lock();
2520 server_mutex->unlock();
2531 case WL_SHM_FORMAT_ARGB8888: {
2551 enum wl_shm_format
format,
2552 void **r_buffer_data,
2553 size_t *r_buffer_data_size)
2556 wl_buffer *buffer =
nullptr;
2559 const int32_t buffer_size = buffer_stride * size_xy[1];
2560 if (posix_fallocate(fd, 0, buffer_size) == 0) {
2561 void *buffer_data = mmap(
nullptr, buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
2562 if (buffer_data != MAP_FAILED) {
2563 wl_shm_pool *pool = wl_shm_create_pool(shm, fd, buffer_size);
2564 buffer = wl_shm_pool_create_buffer(pool, 0,
UNPACK2(size_xy), buffer_stride,
format);
2565 wl_shm_pool_destroy(pool);
2567 *r_buffer_data = buffer_data;
2568 *r_buffer_data_size = size_t(buffer_size);
2572 munmap(buffer_data, buffer_size);
2587 ssize_t nbytes_read = read(fd, data, nbytes);
2588 if (nbytes_read > 0) {
2589 while (nbytes_read < nbytes) {
2590 const ssize_t nbytes_extra = read(
2591 fd,
static_cast<char *
>(data) + nbytes_read, nbytes - nbytes_read);
2592 if (nbytes_extra > 0) {
2593 nbytes_read += nbytes_extra;
2597 nbytes_read = nbytes_extra;
2617 char data[4096 -
sizeof(ByteChunk *)];
2622 ByteChunk *chunk_first =
static_cast<ByteChunk *
>(malloc(
sizeof(ByteChunk)));
2624 ByteChunk **chunk_link_p = &chunk_first;
2625 ByteChunk *chunk = chunk_first;
2632 chunk->next =
nullptr;
2634 const ssize_t len_chunk =
read_exhaustive(fd, chunk->data,
sizeof(ByteChunk::data));
2635 if (len_chunk <= 0) {
2639 if (chunk == chunk_first) {
2640 chunk_first =
nullptr;
2645 *chunk_link_p = chunk;
2646 chunk_link_p = &chunk->next;
2649 if (len_chunk !=
sizeof(ByteChunk::data)) {
2652 chunk =
static_cast<ByteChunk *
>(malloc(
sizeof(ByteChunk)));
2656 char *buf =
nullptr;
2658 buf =
static_cast<char *
>(malloc(
len + (nil_terminate ? 1 : 0)));
2667 if (nil_terminate) {
2675 char *buf_stride = buf;
2676 while (chunk_first) {
2678 const size_t len_chunk = std::min(
len,
sizeof(chunk_first->data));
2679 memcpy(buf_stride, chunk_first->data, len_chunk);
2680 buf_stride += len_chunk;
2683 ByteChunk *chunk = chunk_first->next;
2685 chunk_first = chunk;
2704 GHOST_ASSERT((image_size_x % scale) == 0 && (image_size_y % scale) == 0,
2705 "The size must be a multiple of the scale!");
2707 wl_surface_set_buffer_scale(
wl_surface, scale);
2709 wl_surface_damage(
wl_surface, 0, 0, image_size_x, image_size_y);
2721 if ((image_size_x % scale) == 0 && (image_size_y % scale) == 0) {
2731 const char **r_cursor_name)
2735 wl_cursor *wl_cursor =
nullptr;
2738 if (cursor_name[0] !=
'\0') {
2739 if (!cursor->wl.theme) {
2742 (cursor->theme_name.empty() ?
nullptr : cursor->theme_name.c_str()),
2747 if (cursor->wl.theme) {
2750 GHOST_PRINT(
"cursor '" << cursor_name <<
"' does not exist" << std::endl);
2755 if (r_cursor_name && wl_cursor) {
2756 *r_cursor_name = cursor_name;
2772 const int scale = cursor->
is_custom ? cursor->custom_scale : seat->
pointer.theme_scale;
2773 const int32_t hotspot_x =
int32_t(cursor->wl.image.hotspot_x) / scale;
2774 const int32_t hotspot_y =
int32_t(cursor->wl.image.hotspot_y) / scale;
2775 wl_pointer_set_cursor(
2776 seat->
wl.
pointer, seat->
pointer.serial, cursor->wl.surface_cursor, hotspot_x, hotspot_y);
2780 const int scale = cursor->is_custom ? cursor->custom_scale : seat->
tablet.
theme_scale;
2781 const int32_t hotspot_x =
int32_t(cursor->wl.image.hotspot_x) / scale;
2782 const int32_t hotspot_y =
int32_t(cursor->wl.image.hotspot_y) / scale;
2783 for (zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->
wp.
tablet_tools) {
2785 zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
2786 zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2,
2791#ifdef USE_KDE_TABLET_HIDDEN_CURSOR_HACK
2810 wl_pointer_set_cursor(seat->
wl.
pointer, seat->
pointer.serial,
nullptr, 0, 0);
2811 for (zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->
wp.
tablet_tools) {
2812 zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2, seat->
tablet.
serial,
nullptr, 0, 0);
2817 const wl_cursor_image *wl_image,
2821 const bool visible = (cursor->visible && cursor->is_hardware);
2827 wl_image, cursor->is_custom ? cursor->custom_scale : seat->
pointer.theme_scale);
2833 visible ? cursor->wl.surface_cursor :
nullptr,
2844 for (zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->
wp.
tablet_tools) {
2846 zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
2848 zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2,
2873 const bool is_hardware,
2877 const bool was_visible = cursor->
is_hardware && cursor->visible;
2878 const bool use_visible = is_hardware && visible;
2904 cursor->visible = visible;
2905 cursor->is_hardware = is_hardware;
2914#ifdef USE_EVENT_BACKGROUND_THREAD
2926 return wl_cursor->image_count > 1;
2935 auto cursor_anim_frame_step_fn =
2941 while (!anim_handle->exit_pending.load()) {
2942 std::this_thread::sleep_for(std::chrono::milliseconds(delay));
2943 if (!anim_handle->exit_pending.load()) {
2944 std::lock_guard lock_server_guard{*server_mutex};
2945 if (!anim_handle->exit_pending.load()) {
2947 frame = (frame + 1) % wl_cursor->image_count;
2948 wl_cursor_image *image = wl_cursor->images[frame];
2951 delay = wl_cursor->images[frame]->delay;
2965 std::thread cursor_anim_thread(cursor_anim_frame_step_fn, seat, anim_handle, delay);
2968 cursor_anim_thread.detach();
2981 if (cursor->anim_handle) {
2983 cursor->anim_handle =
nullptr;
3019#define LOG (&LOG_WL_KEYBOARD_DEPRESSED_STATE)
3038 CLOG_WARN(
LOG,
"modifier (%d) has negative keys held (%d)!", index, value);
3090#define LOG (&LOG_WL_RELATIVE_POINTER)
3097 const wl_fixed_t
xy[2],
3103#ifdef USE_GNOME_CONFINE_HACK
3124 zwp_relative_pointer_v1 * ,
3127 const wl_fixed_t dx,
3128 const wl_fixed_t dy,
3139 const wl_fixed_t xy_next[2] = {
3163#define LOG (&LOG_WL_DATA_SOURCE)
3182 const char *mime_receive,
3184 const bool nil_terminate,
3188 const bool pipefd_ok = pipe(pipefd) == 0;
3190 wl_data_offer_receive(data_offer->
wl.
id, mime_receive, pipefd[1]);
3194 CLOG_WARN(
LOG,
"error creating pipe: %s", std::strerror(errno));
3204 char *buf =
nullptr;
3207 if (buf ==
nullptr) {
3208 CLOG_WARN(
LOG,
"unable to pipe into buffer: %s", std::strerror(errno));
3219 const char *mime_receive,
3221 const bool nil_terminate,
3225 const bool pipefd_ok = pipe(pipefd) == 0;
3227 zwp_primary_selection_offer_v1_receive(data_offer->
wp.
id, mime_receive, pipefd[1]);
3231 CLOG_WARN(
LOG,
"error creating pipe: %s", std::strerror(errno));
3238 char *buf =
nullptr;
3241 if (buf ==
nullptr) {
3242 CLOG_WARN(
LOG,
"unable to pipe into buffer: %s", std::strerror(errno));
3271 auto write_file_fn = [](
GWL_Seat *seat,
const int fd) {
3276 CLOG_WARN(
LOG,
"error writing to clipboard: %s", std::strerror(errno));
3283 std::thread write_thread(write_file_fn, seat, fd);
3284 write_thread.detach();
3296 wl_data_source_destroy(wl_data_source);
3335 CLOG_INFO(
LOG, 2,
"handle_action (dnd_action=%u)", dnd_action);
3356#define LOG (&LOG_WL_DATA_OFFER)
3360 const char *mime_type)
3364 data_offer->
types.insert(mime_type);
3371 CLOG_INFO(
LOG, 2,
"source_actions (%u)", source_actions);
3373 data_offer->
dnd.
source_actions = (
enum wl_data_device_manager_dnd_action)source_actions;
3382 data_offer->
dnd.
action = (
enum wl_data_device_manager_dnd_action)dnd_action;
3400#define LOG (&LOG_WL_DATA_DEVICE)
3420 data_offer->
wl.
id = id;
3448 wl_data_offer_destroy(data_offer->
wl.
id);
3458 data_offer->
dnd.
xy[0] =
x;
3459 data_offer->
dnd.
xy[1] =
y;
3461 wl_data_offer_set_actions(
id,
3462 WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
3463 WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE,
3464 WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
3468 wl_data_offer_accept(
id, serial, type);
3541 const char *mime_receive =
"";
3544 if (data_offer->
types.count(type)) {
3545 mime_receive = type;
3550 CLOG_INFO(
LOG, 2,
"drop mime_recieve=%s", mime_receive);
3552 auto read_drop_data_fn = [](
GWL_Seat *
const seat,
3555 const char *mime_receive) {
3560 size_t data_buf_len = 0;
3562 data_offer, mime_receive,
nullptr, nil_terminate, &data_buf_len);
3564 CLOG_INFO(
LOG, 2,
"read_drop_data mime_receive=%s, data_len=%zu", mime_receive, data_buf_len);
3566 wl_data_offer_finish(data_offer->
wl.
id);
3567 wl_data_offer_destroy(data_offer->
wl.
id);
3570 data_offer =
nullptr;
3574 if (data_buf !=
nullptr) {
3576 void *ghost_dnd_data =
nullptr;
3580 const char file_proto[] =
"file://";
3583 const char lf =
'\n';
3585 const std::string_view data = std::string_view(data_buf, data_buf_len);
3586 std::vector<std::string_view> uris;
3589 while (
pos != std::string::npos) {
3590 pos = data.find(file_proto,
pos);
3591 if (
pos == std::string::npos) {
3594 const size_t start =
pos +
sizeof(file_proto) - 1;
3595 pos = data.find(lf,
pos);
3598 if (
UNLIKELY(end == std::string::npos)) {
3604 if (data[end - 1] ==
'\r') {
3608 std::string_view data_substr = data.substr(start, end - start);
3609 uris.push_back(data_substr);
3612 "read_drop_data pos=%zu, text_uri=\"%.*s\"",
3614 int(data_substr.size()),
3615 data_substr.data());
3622 for (
size_t i = 0; i < uris.size(); i++) {
3629 ghost_dnd_data = flist;
3633 ghost_dnd_data = (
void *)data_buf;
3655 free(
const_cast<char *
>(data_buf));
3661 std::thread read_thread(
3663 read_thread.detach();
3681 if (
id ==
nullptr) {
3710#define LOG (&LOG_WL_CURSOR_BUFFER)
3717 wl_buffer_destroy(wl_buffer);
3719 if (wl_buffer == cursor->wl.buffer) {
3721 cursor->wl.buffer =
nullptr;
3738#define LOG (&LOG_WL_CURSOR_SURFACE)
3747 int output_scale_floor = output->scale;
3759 if (output_scale_floor > 1 && output->has_scale_fractional) {
3763 if (output_scale_floor > scale) {
3764 scale = output_scale_floor;
3768 if (scale > 0 && seat_state_pointer->
theme_scale != scale) {
3770 if (!cursor.is_custom) {
3771 if (wl_surface_cursor) {
3772 wl_surface_set_buffer_scale(wl_surface_cursor, scale);
3777 (cursor.theme_name.empty() ?
nullptr : cursor.theme_name.c_str()),
3778 scale * cursor.theme_size,
3780 if (cursor.wl.theme_cursor) {
3782 cursor.wl.theme_cursor_name);
3802 seat_state_pointer->
outputs.insert(reg_output);
3818 seat_state_pointer->
outputs.erase(reg_output);
3827 CLOG_INFO(
LOG, 2,
"handle_preferred_buffer_scale (factor=%d)", factor);
3830#if defined(WL_SURFACE_PREFERRED_BUFFER_SCALE_SINCE_VERSION) && \
3831 defined(WL_SURFACE_PREFERRED_BUFFER_TRANSFORM_SINCE_VERSION)
3832static void cursor_surface_handle_preferred_buffer_transform(
void * ,
3837 CLOG_INFO(
LOG, 2,
"handle_preferred_buffer_transform (transform=%u)", transform);
3845#if defined(WL_SURFACE_PREFERRED_BUFFER_SCALE_SINCE_VERSION) && \
3846 defined(WL_SURFACE_PREFERRED_BUFFER_TRANSFORM_SINCE_VERSION)
3848 cursor_surface_handle_preferred_buffer_transform,
3861#define LOG (&LOG_WL_POINTER)
3867 const wl_fixed_t surface_x,
3868 const wl_fixed_t surface_y)
3883 seat->
pointer.serial = serial;
3884 seat->
pointer.xy[0] = surface_x;
3885 seat->
pointer.xy[1] = surface_y;
3907 static_cast<GWL_Seat *
>(
data)->pointer.
wl.surface_window =
nullptr;
3918 const wl_fixed_t surface_x,
3919 const wl_fixed_t surface_y)
3924 seat->
pointer.xy[0] = surface_x;
3925 seat->
pointer.xy[1] = surface_y;
3949 case WL_POINTER_BUTTON_STATE_RELEASED:
3952 case WL_POINTER_BUTTON_STATE_PRESSED:
3976 const wl_fixed_t value)
3984 CLOG_INFO(
LOG, 2,
"axis (axis=%u, value=%d)", axis, value);
4025 GHOST_ASSERT(event_ms == 0,
"Scroll events are not expected to have a time!");
4028 for (
int i = 0; i < 2; i++) {
4039 if (ps.
axis_source == WL_POINTER_AXIS_SOURCE_WHEEL) {
4047 else if (ps.
axis_source == WL_POINTER_AXIS_SOURCE_FINGER) {
4054 for (
int i = 0; i < 2; i++) {
4073 if (ps.
axis_source == WL_POINTER_AXIS_SOURCE_WHEEL) {
4154 const int button_index = button_enum_offset / 2;
4155 const bool button_down = (button_index * 2) == button_enum_offset;
4159 seat->
pointer.buttons.set(ebutton, button_down);
4174 CLOG_INFO(
LOG, 2,
"axis_source (axis_source=%u)", axis_source);
4206 CLOG_INFO(
LOG, 2,
"axis_discrete (axis=%u, discrete=%d)", axis, discrete);
4222 CLOG_INFO(
LOG, 2,
"axis_value120 (axis=%u, value120=%d)", axis, value120);
4232#ifdef WL_POINTER_AXIS_RELATIVE_DIRECTION_ENUM
4233static void pointer_handle_axis_relative_direction(
void *data,
4239 CLOG_INFO(
LOG, 2,
"axis_relative_direction (axis=%u, direction=%u)", axis, direction);
4246 WL_POINTER_AXIS_RELATIVE_DIRECTION_INVERTED);
4261#ifdef WL_POINTER_AXIS_RELATIVE_DIRECTION_ENUM
4262 pointer_handle_axis_relative_direction,
4274#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
4275static CLG_LogRef LOG_WL_POINTER_GESTURE_HOLD = {
"ghost.wl.handle.pointer_gesture.hold"};
4276# define LOG (&LOG_WL_POINTER_GESTURE_HOLD)
4278static void gesture_hold_handle_begin(
4280 zwp_pointer_gesture_hold_v1 * ,
4289static void gesture_hold_handle_end(
void * ,
4290 zwp_pointer_gesture_hold_v1 * ,
4298static const zwp_pointer_gesture_hold_v1_listener gesture_hold_listener = {
4299 gesture_hold_handle_begin,
4300 gesture_hold_handle_end,
4312#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE
4313static CLG_LogRef LOG_WL_POINTER_GESTURE_PINCH = {
"ghost.wl.handle.pointer_gesture.pinch"};
4314# define LOG (&LOG_WL_POINTER_GESTURE_PINCH)
4316static void gesture_pinch_handle_begin(
void *data,
4317 zwp_pointer_gesture_pinch_v1 * ,
4373static void gesture_pinch_handle_update(
void *data,
4374 zwp_pointer_gesture_pinch_v1 * ,
4379 wl_fixed_t rotation)
4386 "update (dx=%.3f, dy=%.3f, scale=%.3f, rotation=%.3f)",
4387 wl_fixed_to_double(dx),
4388 wl_fixed_to_double(dy),
4389 wl_fixed_to_double(scale),
4390 wl_fixed_to_double(rotation));
4410 if (scale_as_delta_px) {
4421 if (rotation_as_delta_px) {
4427 rotation_as_delta_px,
4434static void gesture_pinch_handle_end(
void *data,
4435 zwp_pointer_gesture_pinch_v1 * ,
4446static const zwp_pointer_gesture_pinch_v1_listener gesture_pinch_listener = {
4447 gesture_pinch_handle_begin,
4448 gesture_pinch_handle_update,
4449 gesture_pinch_handle_end,
4466#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE
4467static CLG_LogRef LOG_WL_POINTER_GESTURE_SWIPE = {
"ghost.wl.handle.pointer_gesture.swipe"};
4468# define LOG (&LOG_WL_POINTER_GESTURE_SWIPE)
4470static void gesture_swipe_handle_begin(
4472 zwp_pointer_gesture_swipe_v1 * ,
4481static void gesture_swipe_handle_update(
4483 zwp_pointer_gesture_swipe_v1 * ,
4488 CLOG_INFO(
LOG, 2,
"update (dx=%.3f, dy=%.3f)", wl_fixed_to_double(dx), wl_fixed_to_double(dy));
4491static void gesture_swipe_handle_end(
4493 zwp_pointer_gesture_swipe_v1 * ,
4501static const zwp_pointer_gesture_swipe_v1_listener gesture_swipe_listener = {
4502 gesture_swipe_handle_begin,
4503 gesture_swipe_handle_update,
4504 gesture_swipe_handle_end,
4521#define LOG (&LOG_WL_TOUCH)
4601#define LOG (&LOG_WL_TABLET_TOOL)
4604 zwp_tablet_tool_v2 * ,
4615 zwp_tablet_tool_v2 * ,
4623 zwp_tablet_tool_v2 * ,
4631 zwp_tablet_tool_v2 * ,
4636 "capability (tilt=%d, distance=%d, rotation=%d, slider=%d, wheel=%d)",
4637 (capability & ZWP_TABLET_TOOL_V2_CAPABILITY_TILT) != 0,
4638 (capability & ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE) != 0,
4639 (capability & ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION) != 0,
4640 (capability & ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER) != 0,
4641 (capability & ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL) != 0);
4663 zwp_tablet_tool_v2 * ,
4698 zwp_tablet_tool_v2 * )
4708 zwp_tablet_tool_v2 * ,
4731 zwp_tablet_tool_v2 * ,
4739 tablet_tool->
xy[0] =
x;
4740 tablet_tool->
xy[1] =
y;
4741 tablet_tool->
has_xy =
true;
4747 zwp_tablet_tool_v2 * ,
4750 const float pressure_unit =
float(pressure) / 65535;
4761 zwp_tablet_tool_v2 * ,
4768 zwp_tablet_tool_v2 * ,
4769 const wl_fixed_t tilt_x,
4770 const wl_fixed_t tilt_y)
4773 const float tilt_unit[2] = {
4774 float(wl_fixed_to_double(tilt_x) / 90.0),
4775 float(wl_fixed_to_double(tilt_y) / 90.0),
4780 td.
Xtilt = std::clamp(tilt_unit[0], -1.0f, 1.0f);
4781 td.
Ytilt = std::clamp(tilt_unit[1], -1.0f, 1.0f);
4787 zwp_tablet_tool_v2 * ,
4788 const wl_fixed_t degrees)
4790 CLOG_INFO(
LOG, 2,
"rotation (degrees=%.4f)", wl_fixed_to_double(degrees));
4794 zwp_tablet_tool_v2 * ,
4800 zwp_tablet_tool_v2 * ,
4818 zwp_tablet_tool_v2 * ,
4828 bool is_press =
false;
4830 case WL_POINTER_BUTTON_STATE_RELEASED:
4833 case WL_POINTER_BUTTON_STATE_PRESSED:
4864 zwp_tablet_tool_v2 * ,
4876 bool has_motion =
false;
4890 if (tablet_tool->
has_xy ==
false) {
4917 const int button_index = button_enum_offset / 2;
4918 const bool button_down = (button_index * 2) == button_enum_offset;
4978#define LOG (&LOG_WL_TABLET_SEAT)
4981 zwp_tablet_seat_v2 * ,
4988 zwp_tablet_seat_v2 * ,
4989 zwp_tablet_tool_v2 *
id)
4995 tablet_tool->
seat = seat;
5001 wl_surface_add_listener(
5010 zwp_tablet_seat_v2 * ,
5011 zwp_tablet_pad_v2 *
id)
5031#define LOG (&LOG_WL_KEYBOARD)
5041 if ((!data) || (
format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)) {
5042 CLOG_INFO(
LOG, 2,
"keymap (no data or wrong version)");
5047 char *map_str =
static_cast<char *
>(mmap(
nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0));
5048 if (map_str == MAP_FAILED) {
5050 CLOG_INFO(
LOG, 2,
"keymap mmap failed: %s", std::strerror(errno));
5054 xkb_keymap *keymap = xkb_keymap_new_from_string(
5055 seat->
xkb.
context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
5056 munmap(map_str, size);
5078 XKB_COMPOSE_STATE_NO_FLAGS);
5083 seat->
xkb.
state = xkb_state_new(keymap);
5111#ifdef USE_NON_LATIN_KB_WORKAROUND
5120 if (!(sym_test >= XKB_KEY_0 && sym_test <= XKB_KEY_9)) {
5130 xkb_keymap_unref(keymap);
5167 uint32_t key = std::numeric_limits<uint32_t>::max();
5168 xkb_keysym_t sym = 0;
5174 CLOG_INFO(
LOG, 2,
"enter (key_held=%d)",
int(key_code));
5175 const xkb_keysym_t sym = xkb_state_key_get_one_sym(seat->
xkb.
state, key_code);
5181 if (xkb_keymap_key_repeats(xkb_state_get_keymap(seat->
xkb.
state), key_code)) {
5191 if ((repeat.key != std::numeric_limits<uint32_t>::max()) && (seat->
key_repeat.
rate > 0)) {
5194#ifdef USE_EVENT_BACKGROUND_THREAD
5202 const xkb_keycode_t key_code = repeat.key +
EVDEV_OFFSET;
5206 key_repeat_payload->
seat = seat;
5207 key_repeat_payload->
key_code = key_code;
5234 seat->
keyboard.wl.surface_window =
nullptr;
5237#ifdef USE_EVENT_BACKGROUND_THREAD
5252 xkb_state *xkb_state_empty,
5253 xkb_state *xkb_state_empty_with_numlock,
5254 xkb_state *xkb_state_empty_with_shift,
5255 const bool xkb_use_non_latin_workaround,
5256 const xkb_keycode_t key)
5259 xkb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state_empty, key);
5269 if (sym >= XKB_KEY_KP_Home && sym <= XKB_KEY_KP_Delete) {
5270 if (xkb_state_empty_with_numlock) {
5271 const xkb_keysym_t sym_test = xkb_state_key_get_one_sym(xkb_state_empty_with_numlock, key);
5272 if (sym_test != XKB_KEY_NoSymbol) {
5278#ifdef USE_NON_LATIN_KB_WORKAROUND
5280 if (xkb_state_empty_with_shift && xkb_use_non_latin_workaround) {
5281 const xkb_keysym_t sym_test = xkb_state_key_get_one_sym(xkb_state_empty_with_shift, key);
5282 if (sym_test != XKB_KEY_NoSymbol) {
5284 GHOST_ASSERT(sym_test >= XKB_KEY_0 && sym_test <= XKB_KEY_9,
"Unexpected key");
5290 (void)xkb_state_empty_with_shift;
5291 (void)xkb_use_non_latin_workaround;
5299 xkb_compose_state *compose_state,
5301 const xkb_keycode_t key,
5304 const xkb_keysym_t sym = xkb_state_key_get_one_sym(
state, key);
5305 const xkb_compose_feed_result result = xkb_compose_state_feed(compose_state, sym);
5306 bool handled =
false;
5308 if (result == XKB_COMPOSE_FEED_ACCEPTED) {
5309 switch (xkb_compose_state_get_status(compose_state)) {
5310 case XKB_COMPOSE_NOTHING: {
5313 case XKB_COMPOSE_COMPOSING: {
5314 r_utf8_buf[0] =
'\0';
5318 case XKB_COMPOSE_COMPOSED: {
5320 const int utf8_buf_compose_len = xkb_compose_state_get_utf8(
5321 compose_state, utf8_buf_compose,
sizeof(utf8_buf_compose));
5322 if (utf8_buf_compose_len > 0) {
5323 memcpy(r_utf8_buf, utf8_buf_compose, utf8_buf_compose_len);
5328 case XKB_COMPOSE_CANCELLED: {
5334 r_utf8_buf[0] =
'\0';
5393 if (sym == XKB_KEY_NoSymbol) {
5394 CLOG_INFO(
LOG, 2,
"key (code=%d, state=%u, no symbol, skipped)",
int(key_code),
state);
5401 case WL_KEYBOARD_KEY_STATE_RELEASED:
5404 case WL_KEYBOARD_KEY_STATE_PRESSED:
5409#ifdef USE_EVENT_BACKGROUND_THREAD
5418 enum { NOP = 1, RESET, CANCEL } timer_action = NOP;
5424 timer_action = CANCEL;
5426 else if (key_code == key_repeat_payload->
key_code) {
5428 timer_action = CANCEL;
5430 else if (xkb_keymap_key_repeats(xkb_state_get_keymap(seat->
xkb.
state), key_code)) {
5433 timer_action = CANCEL;
5441 timer_action = RESET;
5445 switch (timer_action) {
5448 key_repeat_payload =
nullptr;
5457 delete key_repeat_payload;
5458 key_repeat_payload =
nullptr;
5477 xkb_state_key_get_utf8(seat->
xkb.
state, key_code, utf8_buf,
sizeof(utf8_buf));
5488 new GHOST_EventKey(event_ms, etype, win, gkey,
false, utf8_buf));
5492 if (key_repeat_payload ==
nullptr) {
5495 xkb_keymap_key_repeats(xkb_state_get_keymap(seat->
xkb.
state), key_code))
5498 key_repeat_payload->
seat = seat;
5499 key_repeat_payload->
key_code = key_code;
5504 if (key_repeat_payload) {
5519 "modifiers (depressed=%u, latched=%u, locked=%u, group=%u)",
5526 xkb_state_update_mask(seat->
xkb.
state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
5538#ifdef USE_EVENT_BACKGROUND_THREAD
5554 CLOG_INFO(
LOG, 2,
"info (rate=%d, delay=%d)", rate, delay);
5561#ifdef USE_EVENT_BACKGROUND_THREAD
5589#define LOG (&LOG_WL_PRIMARY_SELECTION_OFFER)
5592 zwp_primary_selection_offer_v1 *
id,
5596 if (data_offer->
wp.
id !=
id) {
5597 CLOG_INFO(
LOG, 2,
"offer: %p: offer for unknown selection %p of %s (skipped)", data,
id, type);
5601 data_offer->
types.insert(std::string(type));
5617#define LOG (&LOG_WL_PRIMARY_SELECTION_DEVICE)
5621 zwp_primary_selection_device_v1 * ,
5622 zwp_primary_selection_offer_v1 *
id)
5627 data_offer->
wp.
id = id;
5633 zwp_primary_selection_device_v1 * ,
5634 zwp_primary_selection_offer_v1 *
id)
5641 if (primary->data_offer !=
nullptr) {
5645 if (
id ==
nullptr) {
5652 zwp_primary_selection_offer_v1_get_user_data(
id));
5653 primary->data_offer = data_offer;
5670#define LOG (&LOG_WL_PRIMARY_SELECTION_SOURCE)
5673 zwp_primary_selection_source_v1 * ,
5683 primary->data_source->buffer_out.data,
5684 primary->data_source->buffer_out.data_size) < 0))
5686 CLOG_WARN(
LOG,
"error writing to primary clipboard: %s", std::strerror(errno));
5689 primary->data_source_mutex.unlock();
5692 primary->data_source_mutex.lock();
5693 std::thread write_thread(write_file_fn, primary, fd);
5694 write_thread.detach();
5703 if (source == primary->data_source->wp.source) {
5721#ifdef WITH_INPUT_IME
5734 this->
m_data = customdata;
5738static CLG_LogRef LOG_WL_TEXT_INPUT = {
"ghost.wl.handle.text_input"};
5739# define LOG (&LOG_WL_TEXT_INPUT)
5741static void text_input_handle_enter(
void *data,
5742 zwp_text_input_v3 * ,
5750 seat->ime.surface_window = surface;
5753static void text_input_handle_leave(
void *data,
5754 zwp_text_input_v3 * ,
5763 if (seat->ime.surface_window == surface) {
5764 seat->ime.surface_window =
nullptr;
5768static void text_input_handle_preedit_string(
void *data,
5769 zwp_text_input_v3 * ,
5776 "preedit_string (text=\"%s\", cursor_begin=%d, cursor_end=%d)",
5777 text ? text :
"<null>",
5782 if (seat->ime.has_preedit ==
false) {
5784 gwl_seat_ime_full_reset(seat);
5787 seat->ime.composite_is_null = (text ==
nullptr);
5788 if (!seat->ime.composite_is_null) {
5789 seat->ime.composite = text;
5790 seat->ime.event_ime_data.composite = (
void *)seat->ime.composite.c_str();
5791 seat->ime.event_ime_data.composite_len = (
void *)seat->ime.composite.size();
5793 seat->ime.event_ime_data.cursor_position = cursor_begin;
5794 seat->ime.event_ime_data.target_start = cursor_begin;
5795 seat->ime.event_ime_data.target_end = cursor_end;
5798 seat->ime.has_preedit_string_callback =
true;
5801static void text_input_handle_commit_string(
void *data,
5802 zwp_text_input_v3 * ,
5805 CLOG_INFO(
LOG, 2,
"commit_string (text=\"%s\")", text ? text :
"<null>");
5808 seat->ime.result_is_null = (text ==
nullptr);
5809 if (seat->ime.result_is_null) {
5810 seat->ime.result =
"";
5813 seat->ime.result = text;
5816 seat->ime.result_is_null = (text ==
nullptr);
5817 seat->ime.event_ime_data.result = (
void *)seat->ime.result.c_str();
5818 seat->ime.event_ime_data.result_len = (
void *)seat->ime.result.size();
5819 seat->ime.event_ime_data.cursor_position = seat->ime.result.size();
5821 seat->ime.has_commit_string_callback =
true;
5824static void text_input_handle_delete_surrounding_text(
void * ,
5825 zwp_text_input_v3 * ,
5831 "delete_surrounding_text (before_length=%u, after_length=%u)",
5839static void text_input_handle_done(
void *data,
5840 zwp_text_input_v3 * ,
5852 if (seat->ime.has_commit_string_callback) {
5853 if (seat->ime.has_preedit) {
5854 const bool is_end = seat->ime.composite_is_null;
5856 seat->ime.has_preedit =
false;
5879 if (seat->ime.has_preedit ==
false) {
5880 gwl_seat_ime_preedit_reset(seat);
5883 else if (seat->ime.has_preedit_string_callback) {
5884 const bool is_end = seat->ime.composite_is_null;
5887 seat->ime.has_preedit =
false;
5892 const bool is_start = seat->ime.has_preedit ==
false;
5894 seat->ime.has_preedit =
true;
5899 &seat->ime.event_ime_data));
5903 seat->ime.has_preedit_string_callback =
false;
5904 seat->ime.has_commit_string_callback =
false;
5907static zwp_text_input_v3_listener text_input_listener = {
5908 text_input_handle_enter,
5909 text_input_handle_leave,
5910 text_input_handle_preedit_string,
5911 text_input_handle_commit_string,
5912 text_input_handle_delete_surrounding_text,
5913 text_input_handle_done,
5927#define LOG (&LOG_WL_SEAT)
5932 if (pointer_gestures ==
nullptr) {
5937#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
5938 if (seat->
wp.pointer_gesture_hold) {
5943#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE
5949#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE
5950 if (seat->
wp.pointer_gesture_swipe) {
5959 if (found ==
false) {
5972 if (pointer_gestures ==
nullptr) {
5976 const uint pointer_gestures_version = zwp_pointer_gestures_v1_get_version(pointer_gestures);
5977#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
5978 if (pointer_gestures_version >= ZWP_POINTER_GESTURES_V1_GET_HOLD_GESTURE_SINCE_VERSION)
5980 zwp_pointer_gesture_hold_v1 *gesture = zwp_pointer_gestures_v1_get_hold_gesture(
5982 zwp_pointer_gesture_hold_v1_set_user_data(gesture, seat);
5983 zwp_pointer_gesture_hold_v1_add_listener(gesture, &gesture_hold_listener, seat);
5984 seat->
wp.pointer_gesture_hold = gesture;
5987#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE
5989 zwp_pointer_gesture_pinch_v1 *gesture = zwp_pointer_gestures_v1_get_pinch_gesture(
5991 zwp_pointer_gesture_pinch_v1_set_user_data(gesture, seat);
5992 zwp_pointer_gesture_pinch_v1_add_listener(gesture, &gesture_pinch_listener, seat);
5996#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE
5998 zwp_pointer_gesture_swipe_v1 *gesture = zwp_pointer_gestures_v1_get_swipe_gesture(
6000 zwp_pointer_gesture_swipe_v1_set_user_data(gesture, seat);
6001 zwp_pointer_gesture_swipe_v1_add_listener(gesture, &gesture_swipe_listener, seat);
6002 seat->
wp.pointer_gesture_swipe = gesture;
6016 if (pointer_gestures ==
nullptr) {
6019#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
6021 zwp_pointer_gesture_hold_v1 **gesture_p = &seat->
wp.pointer_gesture_hold;
6023 zwp_pointer_gesture_hold_v1_destroy(*gesture_p);
6024 *gesture_p =
nullptr;
6028#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE
6032 zwp_pointer_gesture_pinch_v1_destroy(*gesture_p);
6033 *gesture_p =
nullptr;
6037#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE
6039 zwp_pointer_gesture_swipe_v1 **gesture_p = &seat->
wp.pointer_gesture_swipe;
6041 zwp_pointer_gesture_swipe_v1_destroy(*gesture_p);
6042 *gesture_p =
nullptr;
6063 env = getenv(
"XCURSOR_THEME");
6066 env = getenv(
"XCURSOR_SIZE");
6069 if (env && (*env !=
'\0')) {
6070 char *env_end =
nullptr;
6073 const long value = strtol(env, &env_end, 10);
6074 if ((*env_end ==
'\0') && (value > 0)) {
6124#ifdef USE_EVENT_BACKGROUND_THREAD
6141 wl_touch_set_user_data(seat->
wl.
touch, seat);
6150 wl_touch_destroy(seat->
wl.
touch);
6156 [[maybe_unused]] wl_seat *wl_seat,
6161 "capabilities (pointer=%d, keyboard=%d, touch=%d)",
6162 (capabilities & WL_SEAT_CAPABILITY_POINTER) != 0,
6163 (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) != 0,
6164 (capabilities & WL_SEAT_CAPABILITY_TOUCH) != 0);
6169 if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
6176 if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
6183 if (capabilities & WL_SEAT_CAPABILITY_TOUCH) {
6194 static_cast<GWL_Seat *
>(
data)->name = std::string(name);
6211#define LOG (&LOG_WL_XDG_OUTPUT)
6222 output->position_logical[1] =
y;
6223 output->has_position_logical =
true;
6231 CLOG_INFO(
LOG, 2,
"logical_size [%d, %d]", width, height);
6234 if (output->size_logical[0] != 0 && output->size_logical[1] != 0) {
6242 if ((output->size_logical[0] == width) &&
6245 GHOST_PRINT(
"xdg_output scale did not match, overriding with wl_output scale\n");
6247#ifdef USE_GNOME_CONFINE_HACK
6257 output->size_logical[0] = width;
6258 output->size_logical[1] = height;
6259 output->has_size_logical =
true;
6268 if (zxdg_output_v1_get_version(output->xdg.output) < 3) {
6282 const char *description)
6284 CLOG_INFO(
LOG, 2,
"description (description=\"%s\")", description);
6304#define LOG (&LOG_WL_OUTPUT)
6311 const int32_t physical_height,
6319 "geometry (make=\"%s\", model=\"%s\", transform=%d, size=[%d, %d])",
6328 output->make = std::string(make);
6329 output->model = std::string(model);
6330 output->size_mm[0] = physical_width;
6331 output->size_mm[1] = physical_height;
6341 if ((flags & WL_OUTPUT_MODE_CURRENT) == 0) {
6345 CLOG_INFO(
LOG, 2,
"mode (size=[%d, %d], flags=%u)", width, height, flags);
6349 output->size_native[1] = height;
6353 if (!output->has_size_logical) {
6354 output->size_logical[0] = width;
6355 output->size_logical[1] = height;
6373 if (
ELEM(output->transform, WL_OUTPUT_TRANSFORM_90, WL_OUTPUT_TRANSFORM_270)) {
6374 std::swap(size_native[0], size_native[1]);
6378 if (output->has_size_logical) {
6383 GHOST_ASSERT(size_native[0] && output->size_logical[0],
6384 "Screen size values were not set when they were expected to be.");
6387 output->has_scale_fractional =
true;
6395 output->
scale = factor;
6396 output->system->output_scale_update(output);
6406 const char *description)
6430#define LOG (&LOG_WL_XDG_WM_BASE)
6435 xdg_wm_base_pong(xdg_wm_base, serial);
6450#ifdef WITH_GHOST_WAYLAND_LIBDECOR
6452static CLG_LogRef LOG_WL_LIBDECOR = {
"ghost.wl.handle.libdecor"};
6453# define LOG (&LOG_WL_LIBDECOR)
6455static void decor_handle_error(libdecor * ,
6456 enum libdecor_error
error,
6457 const char *message)
6463 GHOST_PRINT(
"decoration error (" <<
error <<
"): " << message << std::endl);
6467static libdecor_interface libdecor_interface = {
6482#define LOG (&LOG_WL_REGISTRY)
6491 display->wl.compositor =
static_cast<wl_compositor *
>(
6492 wl_registry_bind(display->wl.registry,
params.name, &wl_compositor_interface, version));
6499 wl_compositor **value_p = &display->wl.compositor;
6500 wl_compositor_destroy(*value_p);
6512 decor.
shell =
static_cast<xdg_wm_base *
>(
6513 wl_registry_bind(display->wl.registry,
params.name, &xdg_wm_base_interface, version));
6523 xdg_wm_base **value_p = &decor.
shell;
6525 xdg_wm_base_destroy(*value_p);
6538 decor.
manager =
static_cast<zxdg_decoration_manager_v1 *
>(wl_registry_bind(
6539 display->wl.registry,
params.name, &zxdg_decoration_manager_v1_interface, version));
6548 zxdg_decoration_manager_v1 **value_p = &decor.
manager;
6550 zxdg_decoration_manager_v1_destroy(*value_p);
6562 display->xdg.output_manager =
static_cast<zxdg_output_manager_v1 *
>(wl_registry_bind(
6563 display->wl.registry,
params.name, &zxdg_output_manager_v1_interface, version));
6570 zxdg_output_manager_v1 **value_p = &display->xdg.output_manager;
6571 zxdg_output_manager_v1_destroy(*value_p);
6582 output->
system = display->system;
6583 output->wl.output =
static_cast<wl_output *
>(
6584 wl_registry_bind(display->wl.registry,
params.name, &wl_output_interface, version));
6586 wl_output_set_user_data(output->wl.output, output);
6588 display->outputs.push_back(output);
6596 if (display->xdg.output_manager) {
6597 if (output->xdg.output ==
nullptr) {
6598 output->
xdg.
output = zxdg_output_manager_v1_get_xdg_output(display->xdg.output_manager,
6604 output->xdg.output =
nullptr;
6621 if (output->system->output_unref(output->wl.output)) {
6623 "mis-behaving compositor failed to call \"surface_listener.leave\" "
6624 "window scale may be invalid!");
6628 if (output->xdg.output) {
6629 zxdg_output_v1_destroy(output->xdg.output);
6631 wl_output_destroy(output->wl.output);
6632 std::vector<GWL_Output *>::iterator iter = std::find(
6633 display->outputs.begin(), display->outputs.end(), output);
6634 const int index = (iter != display->outputs.cend()) ?
6635 std::distance(display->outputs.begin(), iter) :
6639 display->outputs.erase(display->outputs.begin() + index);
6650 seat->
system = display->system;
6651 seat->
xkb.
context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
6658 seat->
wl.
seat =
static_cast<wl_seat *
>(
6659 wl_registry_bind(display->wl.registry,
params.name, &wl_seat_interface, version));
6660 display->seats.push_back(seat);
6672 if (display->wl.data_device_manager) {
6674 seat->
wl.
data_device = wl_data_device_manager_get_data_device(
6675 display->wl.data_device_manager, seat->
wl.
seat);
6683 if (display->wp.tablet_manager) {
6685 seat->
wp.
tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(display->wp.tablet_manager,
6694 if (display->wp.primary_selection_device_manager) {
6697 display->wp.primary_selection_device_manager, seat->
wl.
seat);
6708#ifdef WITH_INPUT_IME
6709 if (display->wp.text_input_manager) {
6710 if (seat->
wp.text_input ==
nullptr) {
6711 seat->
wp.text_input = zwp_text_input_manager_v3_get_text_input(
6712 display->wp.text_input_manager, seat->
wl.
seat);
6713 zwp_text_input_v3_set_user_data(seat->
wp.text_input, seat);
6714 zwp_text_input_v3_add_listener(seat->
wp.text_input, &text_input_listener, seat);
6718 seat->
wp.text_input =
nullptr;
6804 wl_seat_destroy(seat->
wl.
seat);
6806 std::vector<GWL_Seat *>::iterator iter = std::find(
6807 display->seats.begin(), display->seats.end(), seat);
6808 const int index = (iter != display->seats.cend()) ? std::distance(display->seats.begin(), iter) :
6813 if (display->seats_active_index >= index) {
6814 display->seats_active_index -= 1;
6816 display->seats.erase(display->seats.begin() + index);
6827 display->wl.shm =
static_cast<wl_shm *
>(
6828 wl_registry_bind(display->wl.registry,
params.name, &wl_shm_interface, version));
6835 wl_shm **value_p = &display->wl.shm;
6836 wl_shm_destroy(*value_p);
6847 display->wl.data_device_manager =
static_cast<wl_data_device_manager *
>(wl_registry_bind(
6848 display->wl.registry,
params.name, &wl_data_device_manager_interface, version));
6855 wl_data_device_manager **value_p = &display->wl.data_device_manager;
6856 wl_data_device_manager_destroy(*value_p);
6867 display->wp.tablet_manager =
static_cast<zwp_tablet_manager_v2 *
>(wl_registry_bind(
6868 display->wl.registry,
params.name, &zwp_tablet_manager_v2_interface, version));
6875 zwp_tablet_manager_v2 **value_p = &display->wp.tablet_manager;
6876 zwp_tablet_manager_v2_destroy(*value_p);
6887 display->wp.relative_pointer_manager =
static_cast<zwp_relative_pointer_manager_v1 *
>(
6889 display->wl.registry,
params.name, &zwp_relative_pointer_manager_v1_interface, version));
6896 zwp_relative_pointer_manager_v1 **value_p = &display->wp.relative_pointer_manager;
6897 zwp_relative_pointer_manager_v1_destroy(*value_p);
6908 display->wp.pointer_constraints =
static_cast<zwp_pointer_constraints_v1 *
>(wl_registry_bind(
6909 display->wl.registry,
params.name, &zwp_pointer_constraints_v1_interface, version));
6916 zwp_pointer_constraints_v1 **value_p = &display->wp.pointer_constraints;
6917 zwp_pointer_constraints_v1_destroy(*value_p);
6928 display->wp.pointer_gestures =
static_cast<zwp_pointer_gestures_v1 *
>(
6929 wl_registry_bind(display->wl.registry,
6931 &zwp_pointer_gestures_v1_interface,
6932 std::min(
params.version, version)));
6939 zwp_pointer_gestures_v1 **value_p = &display->wp.pointer_gestures;
6940 zwp_pointer_gestures_v1_destroy(*value_p);
6951 display->xdg.activation_manager =
static_cast<xdg_activation_v1 *
>(
6952 wl_registry_bind(display->wl.registry,
params.name, &xdg_activation_v1_interface, version));
6959 xdg_activation_v1 **value_p = &display->xdg.activation_manager;
6960 xdg_activation_v1_destroy(*value_p);
6971 display->wp.fractional_scale_manager =
static_cast<wp_fractional_scale_manager_v1 *
>(
6973 display->wl.registry,
params.name, &wp_fractional_scale_manager_v1_interface, version));
6980 wp_fractional_scale_manager_v1 **value_p = &display->wp.fractional_scale_manager;
6981 wp_fractional_scale_manager_v1_destroy(*value_p);
6992 display->wp.viewporter =
static_cast<wp_viewporter *
>(
6993 wl_registry_bind(display->wl.registry,
params.name, &wp_viewporter_interface, version));
7000 wp_viewporter **value_p = &display->wp.viewporter;
7001 wp_viewporter_destroy(*value_p);
7012 display->wp.primary_selection_device_manager =
7013 static_cast<zwp_primary_selection_device_manager_v1 *
>(
7014 wl_registry_bind(display->wl.registry,
7016 &zwp_primary_selection_device_manager_v1_interface,
7024 zwp_primary_selection_device_manager_v1 **value_p =
7025 &display->wp.primary_selection_device_manager;
7026 zwp_primary_selection_device_manager_v1_destroy(*value_p);
7030#ifdef WITH_INPUT_IME
7034static void gwl_registry_wp_text_input_manager_add(
GWL_Display *display,
7039 display->wp.text_input_manager =
static_cast<zwp_text_input_manager_v3 *
>(wl_registry_bind(
7040 display->wl.registry,
params.name, &zwp_text_input_manager_v3_interface, version));
7043static void gwl_registry_wp_text_input_manager_remove(
GWL_Display *display,
7047 zwp_text_input_manager_v3 **value_p = &display->wp.text_input_manager;
7048 zwp_text_input_manager_v3_destroy(*value_p);
7067 &wl_compositor_interface.name,
7073 &wl_shm_interface.name,
7079 &xdg_wm_base_interface.name,
7086 &zxdg_decoration_manager_v1_interface.name,
7092 &zxdg_output_manager_v1_interface.name,
7098 &wl_data_device_manager_interface.name,
7104 &zwp_primary_selection_device_manager_v1_interface.name,
7110 &zwp_tablet_manager_v2_interface.name,
7116 &zwp_relative_pointer_manager_v1_interface.name,
7121#ifdef WITH_INPUT_IME
7123 &zwp_text_input_manager_v3_interface.name,
7124 gwl_registry_wp_text_input_manager_add,
7126 gwl_registry_wp_text_input_manager_remove,
7131 &zwp_pointer_constraints_v1_interface.name,
7137 &zwp_pointer_gestures_v1_interface.name,
7143 &xdg_activation_v1_interface.name,
7149 &wp_fractional_scale_manager_v1_interface.name,
7155 &wp_viewporter_interface.name,
7162 &wl_output_interface.name,
7171 &wl_seat_interface.name,
7194 if (
STREQ(interface, *handler->interface_p)) {
7204 "Index out of range");
7209 [[maybe_unused]] wl_registry *wl_registry,
7211 const char *interface,
7216 GHOST_ASSERT(display->wl.registry == wl_registry,
"Registry argument must match!");
7221 if (interface_slot != -1) {
7228 params.interface_slot = interface_slot;
7229 params.version = version;
7233 added = display->registry_entry != registry_entry_prev;
7238 "add %s(interface=%s, version=%u, name=%u)",
7239 (interface_slot != -1) ? (added ?
"" :
"(found but not added)") :
"(skipped), ",
7246 if (display->registry_skip_update_all ==
false) {
7263 [[maybe_unused]] wl_registry *wl_registry,
7267 GHOST_ASSERT(display->wl.registry == wl_registry,
"Registry argument must match!");
7269 int interface_slot = 0;
7274 "remove (name=%u, interface=%s)",
7279 if (display->registry_skip_update_all ==
false) {
7299#ifdef USE_EVENT_BACKGROUND_THREAD
7305 while (display->events_pthread_is_active) {
7308 display->wl.display, fd, display->system->server_mutex) == -1)
7326 GHOST_ASSERT(display->events_pthread == 0,
"Only call once");
7328 display->events_pthread_is_active =
true;
7333 pthread_detach(display->events_pthread);
7338 pthread_cancel(display->events_pthread);
7354 server_mutex(new std::
mutex),
7355 timer_mutex(new std::
mutex),
7356 main_thread_id(std::this_thread::get_id()),
7367 display_destroy_and_free_all();
7368 throw std::runtime_error(
"unable to connect to display!");
7377 wl_registry *registry = wl_display_get_registry(display_->
wl.
display);
7391#ifdef WITH_GHOST_WAYLAND_LIBDECOR
7392 bool libdecor_required =
false;
7393 if (
const char *xdg_current_desktop = getenv(
"XDG_CURRENT_DESKTOP")) {
7396 if (string_elem_split_by_delim(xdg_current_desktop,
':',
"GNOME")) {
7397 libdecor_required =
true;
7401 if (libdecor_required) {
7407 libdecor_required =
false;
7409# ifdef WITH_GHOST_X11
7410 else if (!has_libdecor && !ghost_wayland_is_x11_available()) {
7413 libdecor_required =
false;
7418 if (libdecor_required) {
7422 if (!has_libdecor) {
7423# ifdef WITH_GHOST_X11
7426 "WAYLAND found but libdecor was not, install libdecor for Wayland support, "
7427 "falling back to X11\n");
7429 display_destroy_and_free_all();
7430 throw std::runtime_error(
"unable to find libdecor!");
7434 use_libdecor =
false;
7438#ifdef WITH_GHOST_WAYLAND_LIBDECOR
7440 display_->libdecor =
new GWL_LibDecor_System;
7441 GWL_LibDecor_System &decor = *display_->libdecor;
7443 if (!decor.context) {
7444 display_destroy_and_free_all();
7445 throw std::runtime_error(
"unable to create window decorations!");
7455 display_destroy_and_free_all();
7456 throw std::runtime_error(
"unable to access xdg_shell!");
7466#ifdef USE_EVENT_BACKGROUND_THREAD
7473void GHOST_SystemWayland::display_destroy_and_free_all()
7477#ifdef USE_EVENT_BACKGROUND_THREAD
7485 display_destroy_and_free_all();
7493#ifdef WITH_INPUT_NDOF
7506 bool any_processed =
false;
7508#ifdef USE_EVENT_BACKGROUND_THREAD
7522 switch (event->getType()) {
7551#ifdef USE_EVENT_BACKGROUND_THREAD
7555 any_processed =
true;
7560 any_processed =
true;
7564#ifdef WITH_INPUT_NDOF
7568 waitForEvent =
false;
7569 any_processed =
true;
7574#ifdef USE_EVENT_BACKGROUND_THREAD
7582#ifdef USE_EVENT_BACKGROUND_THREAD
7599 any_processed =
true;
7602 return any_processed;
7612#ifdef USE_EVENT_BACKGROUND_THREAD
7637 const bool is_keyboard_active = seat->
keyboard.wl.surface_window !=
nullptr;
7638 const xkb_mod_mask_t
state = is_keyboard_active ?
7639 xkb_state_serialize_mods(seat->
xkb.
state,
7640 XKB_STATE_MODS_DEPRESSED) :
7659 bool val_l = depressed_l > 0;
7660 bool val_r = depressed_r > 0;
7662 if (is_keyboard_active) {
7669 "modifier (%s) state is inconsistent (GHOST held keys do not match XKB)",
7680 "modifier (%s) state is inconsistent (GHOST released keys do not match XKB)",
7699#ifdef USE_EVENT_BACKGROUND_THREAD
7708 if (!seat_state_pointer) {
7712 buttons = seat_state_pointer->
buttons;
7721 const std::unordered_set<std::string> &data_offer_types)
7724 for (
size_t i = 0; i <
ARRAY_SIZE(ghost_supported_types); i++) {
7725 if (data_offer_types.count(ghost_supported_types[i])) {
7726 return ghost_supported_types[i];
7742 bool mutex_locked =
true;
7743 char *data =
nullptr;
7746 if (data_offer !=
nullptr) {
7751 struct ThreadResult {
7752 char *data =
nullptr;
7753 std::atomic<bool> done =
false;
7756 const char *mime_receive,
7758 ThreadResult *thread_result) {
7759 size_t data_len = 0;
7761 data_offer, mime_receive,
mutex,
true, &data_len);
7762 thread_result->done =
true;
7764 std::thread read_thread(read_clipboard_fn, data_offer, mime_receive, &
mutex, &thread_result);
7765 read_thread.detach();
7767 while (!thread_result.done) {
7770 data = thread_result.data;
7773 mutex_locked =
false;
7791 bool mutex_locked =
true;
7792 char *data =
nullptr;
7795 if (data_offer !=
nullptr) {
7800 struct ThreadResult {
7801 char *data =
nullptr;
7802 std::atomic<bool> done =
false;
7805 const char *mime_receive,
7807 ThreadResult *thread_result) {
7808 size_t data_len = 0;
7810 data_offer, mime_receive,
mutex,
true, &data_len);
7811 thread_result->done =
true;
7813 std::thread read_thread(read_clipboard_fn, data_offer, mime_receive, &
mutex, &thread_result);
7814 read_thread.detach();
7816 while (!thread_result.done) {
7819 data = thread_result.data;
7822 mutex_locked =
false;
7833#ifdef USE_EVENT_BACKGROUND_THREAD
7837 char *data =
nullptr;
7849 if (!display->wp.primary_selection_device_manager) {
7863 primary->data_source = data_source;
7868 data_source->
wp.
source = zwp_primary_selection_device_manager_v1_create_source(
7869 display->wp.primary_selection_device_manager);
7871 zwp_primary_selection_source_v1_add_listener(
7879 zwp_primary_selection_device_v1_set_selection(
7886 if (!display->wl.data_device_manager) {
7900 data_source->
wl.
source = wl_data_device_manager_create_data_source(
7901 display->wl.data_device_manager);
7910 wl_data_device_set_selection(
7917#ifdef USE_EVENT_BACKGROUND_THREAD
7933#ifdef USE_EVENT_BACKGROUND_THREAD
7954#ifdef USE_EVENT_BACKGROUND_THREAD
7965 bool mutex_locked =
true;
7967 uint *rgba =
nullptr;
7977 struct ThreadResult {
7978 char *data =
nullptr;
7979 size_t data_len = 0;
7980 std::atomic<bool> done =
false;
7984 const char *mime_receive,
7986 ThreadResult *thread_result) {
7988 data_offer, mime_receive,
mutex,
false, &thread_result->data_len);
7989 thread_result->done =
true;
7991 std::thread read_thread(
7993 read_thread.detach();
7995 while (!thread_result.done) {
7999 if (thread_result.data) {
8002 thread_result.data_len,
8006 free(thread_result.data);
8010 *r_height = ibuf->
y;
8011 const size_t byte_count = size_t(ibuf->
x) * size_t(ibuf->
y) * 4;
8012 rgba = (
uint *)malloc(byte_count);
8019 mutex_locked =
false;
8031#ifdef USE_EVENT_BACKGROUND_THREAD
8057 char *data =
static_cast<char *
>(malloc(imgbuffer->
data_size));
8061 data_source->
wl.
source = wl_data_device_manager_create_data_source(
8069 wl_data_device_set_selection(
8079#ifdef USE_EVENT_BACKGROUND_THREAD
8089 timespec ts = {0, 0};
8090 clock_gettime(CLOCK_MONOTONIC, &ts);
8109 seat_state_pointer->
xy[0],
8110 seat_state_pointer->
xy[1],
8143 const wl_fixed_t xy_next[2]{
8159#ifdef USE_EVENT_BACKGROUND_THREAD
8179#ifdef USE_EVENT_BACKGROUND_THREAD
8193#ifdef USE_EVENT_BACKGROUND_THREAD
8202 if (!seat_state_pointer) {
8215#ifdef USE_EVENT_BACKGROUND_THREAD
8235#ifdef USE_EVENT_BACKGROUND_THREAD
8239 if (!display_->
outputs.empty()) {
8243 if (
ELEM(output->transform, WL_OUTPUT_TRANSFORM_90, WL_OUTPUT_TRANSFORM_270)) {
8244 std::swap(size_native[0], size_native[1]);
8253#ifdef USE_EVENT_BACKGROUND_THREAD
8256 if (!display_->
outputs.empty()) {
8263 if (output->has_position_logical) {
8264 xy[0] = output->position_logical[0];
8265 xy[1] = output->position_logical[1];
8267 if (
ELEM(output->transform, WL_OUTPUT_TRANSFORM_90, WL_OUTPUT_TRANSFORM_270)) {
8268 std::swap(size_native[0], size_native[1]);
8270 xy_min[0] = std::min(xy_min[0],
xy[0]);
8271 xy_min[1] = std::min(xy_min[1],
xy[1]);
8272 xy_max[0] = std::max(xy_max[0],
xy[0] + size_native[0]);
8273 xy_max[1] = std::max(xy_max[1],
xy[1] + size_native[1]);
8276 width = xy_max[0] - xy_min[0];
8277 height = xy_max[1] - xy_min[1];
8283#ifdef USE_EVENT_BACKGROUND_THREAD
8291#ifdef WITH_VULKAN_BACKEND
8292 case GHOST_kDrawingContextTypeVulkan: {
8297 GHOST_kVulkanPlatformWayland,
8308 if (context->initializeDrawingContext()) {
8321#ifdef WITH_OPENGL_BACKEND
8322 case GHOST_kDrawingContextTypeOpenGL: {
8327 for (
int minor = 6; minor >= 3; --minor) {
8332 EGLNativeWindowType(egl_window),
8333 EGLNativeDisplayType(display_->
wl.
display),
8334 EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
8338 (debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
8342 if (context->initializeDrawingContext()) {
8343 wl_surface_set_user_data(
wl_surface, egl_window);
8350 GHOST_PRINT(
"Cannot create off-screen EGL context" << std::endl);
8369#ifdef USE_EVENT_BACKGROUND_THREAD
8374#ifdef WITH_OPENGL_BACKEND
8376 type = GHOST_kDrawingContextTypeOpenGL;
8379#ifdef WITH_VULKAN_BACKEND
8381 type = GHOST_kDrawingContextTypeVulkan;
8392#ifdef WITH_OPENGL_BACKEND
8393 if (type == GHOST_kDrawingContextTypeOpenGL) {
8394 wl_egl_window *egl_window =
static_cast<wl_egl_window *
>(wl_surface_get_user_data(
wl_surface));
8395 if (egl_window !=
nullptr) {
8415 const bool exclusive,
8416 const bool is_dialog,
8457#ifdef USE_GNOME_CONFINE_HACK
8459 if (use_software_confine) {
8464 (void)use_software_confine;
8478 const char *cursor_name =
nullptr;
8480 if (wl_cursor ==
nullptr) {
8485 wl_cursor_image *image = wl_cursor->images[0];
8491 cursor->visible =
true;
8492 cursor->is_custom =
false;
8493 cursor->wl.buffer = buffer;
8494 cursor->wl.image = *
image;
8495 cursor->wl.theme_cursor = wl_cursor;
8496 cursor->wl.theme_cursor_name = cursor_name;
8512 if (wl_cursor ==
nullptr) {
8533 if (cursor->custom_data) {
8534 munmap(cursor->custom_data, cursor->custom_data_size);
8535 cursor->custom_data =
nullptr;
8536 cursor->custom_data_size = 0;
8539 const int32_t size_xy[2] = {sizex, sizey};
8542 WL_SHM_FORMAT_ARGB8888,
8543 &cursor->custom_data,
8544 &cursor->custom_data_size);
8545 if (buffer ==
nullptr) {
8551 static constexpr uint32_t black = 0xFF000000;
8552 static constexpr uint32_t white = 0xFFFFFFFF;
8553 static constexpr uint32_t transparent = 0x00000000;
8557 for (
int y = 0; y < sizey; ++
y) {
8558 uint32_t *pixel = &
static_cast<uint32_t *
>(cursor->custom_data)[y * sizex];
8559 for (
int x = 0; x < sizex; ++
x) {
8565 datab =
uint8_t((datab * 0x0202020202ULL & 0x010884422010ULL) % 1023);
8566 maskb =
uint8_t((maskb * 0x0202020202ULL & 0x010884422010ULL) % 1023);
8570 *pixel++ = (datab & 0x80) ? white : black;
8573 *pixel++ = (datab & 0x80) ? white : transparent;
8580 cursor->visible =
true;
8581 cursor->is_custom =
true;
8582 cursor->custom_scale = 1;
8583 cursor->wl.buffer = buffer;
8584 cursor->wl.image.width =
uint32_t(sizex);
8585 cursor->wl.image.height =
uint32_t(sizey);
8586 cursor->wl.image.hotspot_x =
uint32_t(hotX);
8587 cursor->wl.image.hotspot_y =
uint32_t(hotY);
8588 cursor->wl.theme_cursor =
nullptr;
8589 cursor->wl.theme_cursor_name =
nullptr;
8605 if (cursor->custom_data ==
nullptr) {
8608 if (!cursor->is_custom) {
8612 bitmap->
data_size[0] = cursor->wl.image.width;
8613 bitmap->
data_size[1] = cursor->wl.image.height;
8615 bitmap->
hot_spot[0] = cursor->wl.image.hotspot_x;
8616 bitmap->
hot_spot[1] = cursor->wl.image.hotspot_y;
8618 bitmap->
data =
static_cast<uint8_t *
>(cursor->custom_data);
8640 "The trackpad direction was expected to be initialized");
8678#ifdef USE_GNOME_CONFINE_HACK
8681 const bool use_software_confine =
false;
8687#ifdef USE_GNOME_CONFINE_HACK
8691# ifndef USE_GNOME_CONFINE_HACK_ALWAYS_ON
8704# ifndef USE_GNOME_CONFINE_HACK_ALWAYS_ON
8714 const bool use_software_confine)
8731#ifdef USE_EVENT_BACKGROUND_THREAD
8761 const wl_proxy *proxy =
reinterpret_cast<const wl_proxy *
>(wl_output);
8767 const wl_proxy *proxy =
reinterpret_cast<const wl_proxy *
>(
wl_surface);
8778 const wl_proxy *proxy =
reinterpret_cast<const wl_proxy *
>(
wl_surface);
8785 const wl_proxy *proxy =
reinterpret_cast<const wl_proxy *
>(
wl_surface);
8791 wl_proxy *proxy =
reinterpret_cast<wl_proxy *
>(wl_output);
8797 wl_proxy *proxy =
reinterpret_cast<wl_proxy *
>(
wl_surface);
8803 wl_proxy *proxy =
reinterpret_cast<wl_proxy *
>(
wl_surface);
8809 wl_proxy *proxy =
reinterpret_cast<wl_proxy *
>(
wl_surface);
8863#ifdef WITH_GHOST_WAYLAND_APP_ID
8875#ifdef WITH_GHOST_WAYLAND_LIBDECOR
8877libdecor *GHOST_SystemWayland::libdecor_context_get()
8879 return display_->libdecor->context;
8903 return display_->
wl.
shm;
8906#ifdef USE_EVENT_BACKGROUND_THREAD
8921#ifdef WITH_INPUT_IME
8928 bool completed)
const
8934 if (seat->
wp.text_input ==
nullptr) {
8941 gwl_seat_ime_result_reset(seat);
8944 if (seat->ime.is_enabled && completed) {
8948 bool force_rect_update =
false;
8949 if (seat->ime.is_enabled ==
false) {
8950 seat->ime.has_preedit =
false;
8951 seat->ime.is_enabled =
true;
8955 zwp_text_input_v3_enable(seat->
wp.text_input);
8956 zwp_text_input_v3_commit(seat->
wp.text_input);
8957 zwp_text_input_v3_enable(seat->
wp.text_input);
8958 zwp_text_input_v3_commit(seat->
wp.text_input);
8961 zwp_text_input_v3_set_content_type(seat->
wp.text_input,
8962 ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE,
8963 ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL);
8965 gwl_seat_ime_rect_reset(seat);
8966 force_rect_update =
true;
8969 if ((force_rect_update ==
false) &&
8970 (seat->ime.rect.x == x) &&
8971 (seat->ime.rect.y == y) &&
8972 (seat->ime.rect.w ==
w) &&
8973 (seat->ime.rect.h == h))
8983 zwp_text_input_v3_set_cursor_rectangle(seat->
wp.text_input, rect_x, rect_y, rect_w, rect_h);
8985 zwp_text_input_v3_commit(seat->
wp.text_input);
8987 seat->ime.rect.x =
x;
8988 seat->ime.rect.y =
y;
8989 seat->ime.rect.w =
w;
8990 seat->ime.rect.h = h;
9001 seat->ime.is_enabled =
false;
9003 gwl_seat_ime_rect_reset(seat);
9005 if (seat->
wp.text_input ==
nullptr) {
9009 zwp_text_input_v3_disable(seat->
wp.text_input);
9010 zwp_text_input_v3_commit(seat->
wp.text_input);
9056 if (
UNLIKELY(timestamp_as_uint < input_timestamp.
last)) {
9064 if (input_timestamp.
last - timestamp_as_uint > std::numeric_limits<uint32_t>::max() / 2) {
9068 uint64_t(std::numeric_limits<uint32_t>::max()) + 1;
9074 input_timestamp.
offset = offset_test;
9078 input_timestamp.
last = timestamp_as_uint;
9081 timestamp += input_timestamp.
offset;
9086 if (now_as_uint32 == timestamp_as_uint) {
9094 if (!input_timestamp.
offset) {
9095 input_timestamp.
offset = (now - timestamp);
9097 timestamp += input_timestamp.
offset;
9099 if (timestamp > now) {
9100 input_timestamp.
offset -= (timestamp - now);
9111#ifdef USE_EVENT_BACKGROUND_THREAD
9139 bool changed =
false;
9140#define SURFACE_CLEAR_PTR(surface_test) \
9141 if (surface_test == wl_surface) { \
9142 surface_test = nullptr; \
9153#ifdef WITH_INPUT_IME
9157#undef SURFACE_CLEAR_PTR
9164 bool changed =
false;
9172 if (window_manager) {
9182 if (seat->
pointer.outputs.erase(output)) {
9196 if (window_manager) {
9199 const std::vector<GWL_Output *> &outputs = win->
outputs_get();
9200 if (!(std::find(outputs.begin(), outputs.end(), output) == outputs.cend())) {
9207 if (seat->
pointer.outputs.count(output)) {
9215 for (zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->
wp.
tablet_tools) {
9217 zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
9247 if (mode == mode_current) {
9251#ifdef USE_GNOME_CONFINE_HACK
9255 const bool was_software_confine =
false;
9256 const bool use_software_confine =
false;
9260 was_software_confine);
9281 int32_t xy_motion[2] = {0, 0};
9282 bool xy_motion_create_event =
false;
9293 wl_fixed_from_int(wrap_bounds->
m_l));
9295 wl_fixed_from_int(wrap_bounds->
m_t));
9297 wl_fixed_from_int(wrap_bounds->
m_r));
9299 wl_fixed_from_int(wrap_bounds->
m_b));
9304 if ((xy_next[0] != seat->
pointer.xy[0]) || (xy_next[1] != seat->
pointer.xy[1])) {
9305 xy_motion[0] = xy_next[0];
9306 xy_motion[1] = xy_next[1];
9307 xy_motion_create_event =
true;
9309 seat->
pointer.xy[0] = xy_next[0];
9310 seat->
pointer.xy[1] = xy_next[1];
9319 const wl_fixed_t xy_next[2] = {
9330 xy_motion[0] = xy_next[0];
9331 xy_motion[1] = xy_next[1];
9332 xy_motion_create_event =
true;
9335#ifdef USE_GNOME_CONFINE_HACK
9337 if (was_software_confine) {
9345 if (xy_motion_create_event) {
9379 zwp_relative_pointer_v1_add_listener(
9386 ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
9391 init_grab_xy[0] = wl_fixed_to_int(
9393 init_grab_xy[1] = wl_fixed_to_int(
9406 ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
9414#ifdef USE_GNOME_CONFINE_HACK
9421#ifdef WITH_GHOST_WAYLAND_LIBDECOR
9422bool GHOST_SystemWayland::use_libdecor_runtime()
9424 return use_libdecor;
9428#ifdef WITH_GHOST_WAYLAND_DYNLOAD
9429bool ghost_wl_dynload_libraries_init()
9431# ifdef WITH_GHOST_X11
9435 bool verbose = getenv(
"WAYLAND_DISPLAY") !=
nullptr;
9442# ifdef WITH_OPENGL_BACKEND
9449# ifdef WITH_GHOST_WAYLAND_LIBDECOR
9457# ifdef WITH_OPENGL_BACKEND
9464void ghost_wl_dynload_libraries_exit()
9468# ifdef WITH_OPENGL_BACKEND
9471# ifdef WITH_GHOST_WAYLAND_LIBDECOR
void BLI_kdtree_nd_ free(KDTree *tree)
#define CLOG_WARN(clg_ref,...)
#define CLOG_INFO(clg_ref, level,...)
#define GHOST_OPENGL_EGL_CONTEXT_FLAGS
#define GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY
#define GHOST_ASSERT(x, info)
char * GHOST_URL_decode_alloc(const char *buf_src, const int buf_src_len)
static void keyboard_handle_repeat_info(void *data, wl_keyboard *, const int32_t rate, const int32_t delay)
void(*)(GWL_Display *display, void *user_data, bool on_exit) GWL_RegistryEntry_RemoveFn
static constexpr int smooth_as_discrete_steps
static void ghost_wl_display_lock_without_input(wl_display *wl_display, std::mutex *server_mutex)
static void gwl_registry_wp_viewporter_remove(GWL_Display *display, void *, const bool)
static void tablet_tool_handle_button(void *data, zwp_tablet_tool_v2 *, const uint32_t serial, const uint32_t button, const uint32_t state)
static CLG_LogRef LOG_WL_PRIMARY_SELECTION_SOURCE
#define USE_NON_LATIN_KB_WORKAROUND
#define WL_FIXED_TO_INT_FOR_WINDOW_V2(win, xy)
static const char * ghost_wl_mime_send[]
static void cursor_surface_handle_enter(void *data, wl_surface *wl_surface, wl_output *wl_output)
static void tablet_tool_handle_distance(void *, zwp_tablet_tool_v2 *, const uint32_t distance)
static void data_source_handle_target(void *, wl_data_source *, const char *)
static void primary_selection_device_handle_selection(void *data, zwp_primary_selection_device_v1 *, zwp_primary_selection_offer_v1 *id)
static void global_handle_add(void *data, wl_registry *wl_registry, const uint32_t name, const char *interface, const uint32_t version)
static void gwl_registry_wp_relative_pointer_manager_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
static int gwl_registry_handler_interface_slot_from_string(const char *interface)
static const wl_keyboard_listener keyboard_listener
static CLG_LogRef LOG_WL_TABLET_TOOL
static void gwl_registry_xdg_wm_base_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
static void touch_seat_handle_cancel(void *, wl_touch *)
static void keyboard_depressed_state_push_events_from_change(GWL_Seat *seat, GHOST_IWindow *win, const uint64_t event_ms, const GWL_KeyboardDepressedState &key_depressed_prev)
static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wp_tablet_tool_type)
static void keyboard_handle_modifiers(void *data, wl_keyboard *, const uint32_t serial, const uint32_t mods_depressed, const uint32_t mods_latched, const uint32_t mods_locked, const uint32_t group)
static const GWL_Cursor_ShapeInfo ghost_wl_cursors
static void seat_handle_capabilities(void *data, wl_seat *wl_seat, const uint32_t capabilities)
static void cursor_surface_handle_leave(void *data, wl_surface *wl_surface, wl_output *wl_output)
static const char * ghost_wl_surface_cursor_tablet_tag_id
static const xdg_wm_base_listener shell_listener
static CLG_LogRef LOG_WL_KEYBOARD_DEPRESSED_STATE
static void keyboard_handle_keymap(void *data, wl_keyboard *, const uint32_t format, const int32_t fd, const uint32_t size)
static void data_source_handle_cancelled(void *data, wl_data_source *wl_data_source)
bool ghost_wl_surface_own(const wl_surface *wl_surface)
static void tablet_seat_handle_tool_added(void *data, zwp_tablet_seat_v2 *, zwp_tablet_tool_v2 *id)
static void pointer_handle_frame(void *data, wl_pointer *)
static void pointer_handle_axis(void *data, wl_pointer *, const uint32_t time, const uint32_t axis, const wl_fixed_t value)
static const char * ghost_wl_app_id
static void xdg_output_handle_name(void *, zxdg_output_v1 *, const char *name)
static GHOST_TSuccess getCursorPositionClientRelative_impl(const GWL_SeatStatePointer *seat_state_pointer, const GHOST_WindowWayland *win, int32_t &x, int32_t &y)
static void gwl_primary_selection_discard_offer(GWL_PrimarySelection *primary)
static void pthread_set_min_priority(pthread_t handle)
static void gwl_registry_wl_data_device_manager_remove(GWL_Display *display, void *, const bool)
static char * read_buffer_from_primary_selection_offer(GWL_PrimarySelection_DataOffer *data_offer, const char *mime_receive, std::mutex *mutex, const bool nil_terminate, size_t *r_len)
static void gwl_seat_capability_keyboard_disable(GWL_Seat *seat)
static void gwl_seat_cursor_anim_end(GWL_Seat *seat)
static void tablet_tool_handle_type(void *data, zwp_tablet_tool_v2 *, const uint32_t tool_type)
static void gwl_registry_wp_relative_pointer_manager_remove(GWL_Display *display, void *, const bool)
static CLG_LogRef LOG_WL_TABLET_SEAT
static void data_device_handle_drop(void *data, wl_data_device *)
static void data_source_handle_send(void *data, wl_data_source *, const char *, const int32_t fd)
static bool gwl_display_seat_active_set(GWL_Display *display, const GWL_Seat *seat)
static const zwp_relative_pointer_v1_listener relative_pointer_listener
static const wl_cursor * gwl_seat_cursor_find_from_shape(GWL_Seat *seat, const GHOST_TStandardCursor shape, const char **r_cursor_name)
static void tablet_tool_handle_proximity_out(void *data, zwp_tablet_tool_v2 *)
void ghost_wl_output_tag(wl_output *wl_output)
static void gwl_registry_xdg_decoration_manager_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
static void output_handle_geometry(void *data, wl_output *, const int32_t, const int32_t, const int32_t physical_width, const int32_t physical_height, const int32_t, const char *make, const char *model, const int32_t transform)
static void gwl_registry_xdg_decoration_manager_remove(GWL_Display *display, void *, const bool)
static CLG_LogRef LOG_WL_PRIMARY_SELECTION_OFFER
static void data_device_handle_selection(void *data, wl_data_device *, wl_data_offer *id)
static int memfd_create_sealed(const char *name)
static uint64_t ghost_wl_ms_from_utime_pair(uint32_t utime_hi, uint32_t utime_lo)
#define GWL_TabletTool_FrameTypes_NUM
static void keyboard_handle_key_repeat_cancel(GWL_Seat *seat)
GHOST_WindowWayland * ghost_wl_surface_user_data(wl_surface *wl_surface)
static void gwl_seat_key_repeat_timer_remove(GWL_Seat *seat)
static const GHOST_TButton gwl_pointer_events_ebutton[]
static CLG_LogRef LOG_WL_TOUCH
static void gwl_registry_wp_primary_selection_device_manager_remove(GWL_Display *display, void *, const bool)
static GHOST_TSuccess setCursorPositionClientRelative_impl(GWL_Seat *seat, GHOST_WindowWayland *win, const int32_t x, const int32_t y)
static const zxdg_output_v1_listener xdg_output_listener
static void keyboard_handle_key_repeat_reset(GWL_Seat *seat, const bool use_delay)
static void global_handle_remove(void *data, wl_registry *wl_registry, const uint32_t name)
static void primary_selection_source_send(void *data, zwp_primary_selection_source_v1 *, const char *, int32_t fd)
static const wl_buffer_listener cursor_buffer_listener
static void gwl_registry_wp_pointer_constraints_remove(GWL_Display *display, void *, const bool)
static void tablet_tool_handle_done(void *, zwp_tablet_tool_v2 *)
static void output_handle_done(void *data, wl_output *wl_output)
static void gwl_registry_wl_seat_update(GWL_Display *display, const GWL_RegisteryUpdate_Params ¶ms)
static void gwl_seat_capability_keyboard_enable(GWL_Seat *seat)
static ssize_t read_exhaustive(const int fd, void *data, size_t nbytes)
static CLG_LogRef LOG_WL_RELATIVE_POINTER
static void thread_set_min_priority(std::thread &thread)
static void relative_pointer_handle_relative_motion_impl(GWL_Seat *seat, GHOST_WindowWayland *win, const wl_fixed_t xy[2], const uint64_t event_ms)
static uint64_t sub_abs_u64(const uint64_t a, const uint64_t b)
static bool gwl_registry_entry_remove_by_name(GWL_Display *display, uint32_t name, int *r_interface_slot)
static void gwl_registry_compositor_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
void ghost_wl_surface_tag_cursor_tablet(wl_surface *wl_surface)
static void gwl_registry_entry_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms, void *user_data)
static void xdg_output_handle_description(void *, zxdg_output_v1 *, const char *description)
bool ghost_wl_surface_own_cursor_tablet(const wl_surface *wl_surface)
static CLG_LogRef LOG_WL_XDG_OUTPUT
static void gwl_seat_cursor_anim_begin(GWL_Seat *seat)
static void gwl_seat_cursor_buffer_set(const GWL_Seat *seat, const wl_cursor_image *wl_image, wl_buffer *buffer)
static void gwl_registry_entry_update_all(GWL_Display *display, const int interface_slot_exclude)
static CLG_LogRef LOG_WL_PRIMARY_SELECTION_DEVICE
GWL_Output * ghost_wl_output_user_data(wl_output *wl_output)
static void touch_seat_handle_orientation(void *, wl_touch *, int32_t, wl_fixed_t)
static char * read_buffer_from_data_offer(GWL_DataOffer *data_offer, const char *mime_receive, std::mutex *mutex, const bool nil_terminate, size_t *r_len)
static bool gwl_seat_capability_pointer_multitouch_check(const GWL_Seat *seat, const bool fallback)
static const wl_registry_listener registry_listener
static void keyboard_depressed_state_reset(GWL_Seat *seat)
static const zwp_tablet_seat_v2_listener tablet_seat_listener
static void gwl_tablet_tool_frame_event_reset(GWL_TabletTool *tablet_tool)
static GWL_SeatStatePointer * gwl_seat_state_pointer_active(GWL_Seat *seat)
static constexpr const char * ghost_wl_mime_text_plain
static void tablet_seat_handle_tablet_added(void *, zwp_tablet_seat_v2 *, zwp_tablet_v2 *id)
static void tablet_tool_handle_frame(void *data, zwp_tablet_tool_v2 *, const uint32_t time)
static const zwp_primary_selection_offer_v1_listener primary_selection_offer_listener
static int pointer_axis_as_index(const uint32_t axis)
static GHOST_TKey xkb_map_gkey(const xkb_keysym_t sym)
static const wl_pointer_listener pointer_listener
static void system_clipboard_put_primary_selection(GWL_Display *display, const char *buffer)
static void touch_seat_handle_up(void *, wl_touch *, uint32_t, uint32_t, int32_t)
static void data_source_handle_dnd_finished(void *, wl_data_source *)
static void gwl_registry_xdg_output_manager_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
static void gwl_registry_wp_tablet_manager_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
static void tablet_tool_handle_hardware_id_wacom(void *, zwp_tablet_tool_v2 *, const uint32_t, const uint32_t)
static void gwl_seat_capability_pointer_disable(GWL_Seat *seat)
static void gwl_registry_wp_pointer_gestures_remove(GWL_Display *display, void *, const bool)
static const wl_data_offer_listener data_offer_listener
static bool update_cursor_scale(GWL_Cursor &cursor, wl_shm *shm, GWL_SeatStatePointer *seat_state_pointer, wl_surface *wl_surface_cursor)
static void ghost_wl_display_report_error_from_code(wl_display *display, const int ecode)
static void gwl_pointer_handle_frame_event_reset(GWL_SeatStatePointer_Events *pointer_events)
static void tablet_tool_handle_motion(void *data, zwp_tablet_tool_v2 *, const wl_fixed_t x, const wl_fixed_t y)
static const GWL_RegistryHandler * gwl_registry_handler_from_interface_slot(int interface_slot)
static CLG_LogRef LOG_WL_OUTPUT
static const wl_data_source_listener data_source_listener
static void gwl_registry_wl_seat_remove(GWL_Display *display, void *user_data, const bool on_exit)
void(*)(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms) GWL_RegistryHandler_AddFn
static void keyboard_depressed_state_key_event(GWL_Seat *seat, const GHOST_TKey gkey, const GHOST_TEventType etype)
static const zwp_tablet_tool_v2_listener tablet_tool_listner
static void tablet_seat_handle_pad_added(void *, zwp_tablet_seat_v2 *, zwp_tablet_pad_v2 *id)
static void tablet_tool_handle_hardware_serial(void *, zwp_tablet_tool_v2 *, const uint32_t, const uint32_t)
static bool gwl_registry_entry_remove_by_interface_slot(GWL_Display *display, int interface_slot, bool on_exit)
void ghost_wl_surface_tag(wl_surface *wl_surface)
static wl_buffer * ghost_wl_buffer_create_for_image(wl_shm *shm, const int32_t size_xy[2], enum wl_shm_format format, void **r_buffer_data, size_t *r_buffer_data_size)
static bool cursor_is_software(const GHOST_TGrabCursorMode mode, const bool use_software_confine)
static void gwl_registry_xdg_activation_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
static const wl_data_device_listener data_device_listener
static void pointer_handle_axis_value120(void *data, wl_pointer *, uint32_t axis, int32_t value120)
static void touch_seat_handle_shape(void *, wl_touch *, int32_t, wl_fixed_t, wl_fixed_t)
static void pointer_handle_axis_stop(void *data, wl_pointer *, uint32_t time, uint32_t axis)
static void gwl_seat_capability_touch_disable(GWL_Seat *seat)
static bool gwl_seat_cursor_anim_check(GWL_Seat *seat)
static void ghost_wl_display_report_error(wl_display *display)
static void tablet_tool_handle_tilt(void *data, zwp_tablet_tool_v2 *, const wl_fixed_t tilt_x, const wl_fixed_t tilt_y)
bool ghost_wl_display_report_error_if_set(wl_display *display)
static void tablet_tool_handle_removed(void *data, zwp_tablet_tool_v2 *zwp_tablet_tool_v2)
static const wl_touch_listener touch_seat_listener
static void gwl_registry_wl_seat_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
static void pointer_handle_button(void *data, wl_pointer *, const uint32_t serial, const uint32_t time, const uint32_t button, const uint32_t state)
static void gwl_seat_key_layout_active_state_update_mask(GWL_Seat *seat)
static void gwl_display_event_thread_destroy(GWL_Display *display)
static constexpr const char * ghost_wl_mime_text_uri
static CLG_LogRef LOG_WL_KEYBOARD
static bool ghost_wayland_log_handler_is_background
static GHOST_TKey xkb_map_gkey_or_scan_code(const xkb_keysym_t sym, const uint32_t key)
static void keyboard_handle_key(void *data, wl_keyboard *, const uint32_t serial, const uint32_t time, const uint32_t key, const uint32_t state)
void ghost_wl_surface_tag_cursor_pointer(wl_surface *wl_surface)
static void ghost_wayland_log_handler(const char *msg, va_list arg)
static void gwl_seat_cursor_buffer_show(GWL_Seat *seat)
static CLG_LogRef LOG_WL_REGISTRY
static const wl_surface_listener cursor_surface_listener
static void primary_selection_source_cancelled(void *data, zwp_primary_selection_source_v1 *source)
@ CURSOR_VISIBLE_ONLY_HIDE
@ CURSOR_VISIBLE_ALWAYS_SET
@ CURSOR_VISIBLE_ONLY_SHOW
static CLG_LogRef LOG_WL_POINTER
static void gwl_seat_cursor_buffer_hide(GWL_Seat *seat)
static void pointer_handle_axis_discrete(void *data, wl_pointer *, uint32_t axis, int32_t discrete)
static void keyboard_handle_leave(void *data, wl_keyboard *, const uint32_t, wl_surface *wl_surface)
static constexpr const char * ghost_wl_mime_img_png
static void data_source_handle_action(void *, wl_data_source *, const uint32_t dnd_action)
static xkb_keysym_t xkb_state_key_get_one_sym_without_modifiers(xkb_state *xkb_state_empty, xkb_state *xkb_state_empty_with_numlock, xkb_state *xkb_state_empty_with_shift, const bool xkb_use_non_latin_workaround, const xkb_keycode_t key)
static void gwl_registry_wp_tablet_manager_remove(GWL_Display *display, void *, const bool)
static void xdg_output_handle_logical_position(void *data, zxdg_output_v1 *, const int32_t x, const int32_t y)
static const zwp_primary_selection_source_v1_listener primary_selection_source_listener
static void data_device_handle_data_offer(void *, wl_data_device *, wl_data_offer *id)
static void pointer_handle_enter(void *data, wl_pointer *, const uint32_t serial, wl_surface *wl_surface, const wl_fixed_t surface_x, const wl_fixed_t surface_y)
static void cursor_surface_handle_preferred_buffer_scale(void *, wl_surface *, int32_t factor)
static void tablet_tool_handle_capability(void *, zwp_tablet_tool_v2 *, const uint32_t capability)
static void cursor_buffer_set_surface_impl(const wl_cursor_image *wl_image, wl_buffer *buffer, wl_surface *wl_surface, const int scale)
static void gwl_registry_wl_output_remove(GWL_Display *display, void *user_data, const bool on_exit)
static void pointer_handle_axis_source(void *data, wl_pointer *, uint32_t axis_source)
static void pointer_handle_motion(void *data, wl_pointer *, const uint32_t time, const wl_fixed_t surface_x, const wl_fixed_t surface_y)
static void touch_seat_handle_motion(void *, wl_touch *, uint32_t, int32_t, wl_fixed_t, wl_fixed_t)
static void primary_selection_device_handle_data_offer(void *, zwp_primary_selection_device_v1 *, zwp_primary_selection_offer_v1 *id)
static const zwp_primary_selection_device_v1_listener primary_selection_device_listener
static void cursor_buffer_handle_release(void *data, wl_buffer *wl_buffer)
static const char * system_clipboard_text_mime_type(const std::unordered_set< std::string > &data_offer_types)
static void gwl_registry_wl_shm_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
bool ghost_wl_output_own(const wl_output *wl_output)
static void * gwl_display_event_thread_fn(void *display_voidp)
static const char * ghost_wl_locale_from_env_with_default()
static void gwl_registry_wp_viewporter_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
static void pointer_handle_leave(void *data, wl_pointer *, const uint32_t, wl_surface *wl_surface)
static void gwl_registry_wl_data_device_manager_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
static CLG_LogRef LOG_WL_DATA_OFFER
static void data_offer_handle_source_actions(void *data, wl_data_offer *, const uint32_t source_actions)
static void tablet_tool_handle_rotation(void *, zwp_tablet_tool_v2 *, const wl_fixed_t degrees)
static void gwl_seat_capability_pointer_enable(GWL_Seat *seat)
static CLG_LogRef LOG_WL_SEAT
static void data_offer_handle_action(void *data, wl_data_offer *, const uint32_t dnd_action)
static void gwl_seat_cursor_buffer_set_current(GWL_Seat *seat)
static void tablet_tool_handle_proximity_in(void *data, zwp_tablet_tool_v2 *, const uint32_t serial, zwp_tablet_v2 *, wl_surface *wl_surface)
static void gwl_display_event_thread_create(GWL_Display *display)
#define SURFACE_CLEAR_PTR(surface_test)
static void seat_handle_name(void *data, wl_seat *, const char *name)
static void gwl_tablet_tool_frame_event_add(GWL_TabletTool *tablet_tool, const GWL_TabletTool_EventTypes ty)
static void tablet_tool_handle_wheel(void *data, zwp_tablet_tool_v2 *, const wl_fixed_t, const int32_t clicks)
static void gwl_primary_selection_discard_source(GWL_PrimarySelection *primary)
static void tablet_tool_handle_down(void *data, zwp_tablet_tool_v2 *, const uint32_t serial)
static void gwl_seat_cursor_visible_set(GWL_Seat *seat, const bool visible, const bool is_hardware, const enum eCursorSetMode set_mode)
static CLG_LogRef LOG_WL_CURSOR_SURFACE
static void output_handle_scale(void *data, wl_output *, const int32_t factor)
static void data_device_handle_leave(void *data, wl_data_device *)
static const char * ghost_wl_surface_cursor_pointer_tag_id
static void gwl_display_destroy(GWL_Display *display)
static void touch_seat_handle_down(void *, wl_touch *, uint32_t, uint32_t, wl_surface *, int32_t, wl_fixed_t, wl_fixed_t)
static void gwl_seat_capability_touch_enable(GWL_Seat *seat)
static void gwl_seat_cursor_anim_begin_if_needed(GWL_Seat *seat)
static bool xkb_compose_state_feed_and_get_utf8(xkb_compose_state *compose_state, xkb_state *state, const xkb_keycode_t key, char r_utf8_buf[sizeof(GHOST_TEventKeyData::utf8_buf)])
static void primary_selection_offer_offer(void *data, zwp_primary_selection_offer_v1 *id, const char *type)
static const wl_output_listener output_listener
static void gwl_registry_entry_remove_all(GWL_Display *display)
static void keyboard_handle_enter(void *data, wl_keyboard *, const uint32_t serial, wl_surface *wl_surface, wl_array *keys)
static int ghost_wl_display_event_pump(wl_display *wl_display)
static CLG_LogRef LOG_WL_XDG_WM_BASE
static void output_handle_mode(void *data, wl_output *, const uint32_t flags, const int32_t width, const int32_t height, const int32_t)
static void gwl_seat_key_repeat_timer_fn(GHOST_ITimerTask *task, uint64_t time_ms)
static void relative_pointer_handle_relative_motion(void *data, zwp_relative_pointer_v1 *, const uint32_t utime_hi, const uint32_t utime_lo, const wl_fixed_t dx, const wl_fixed_t dy, const wl_fixed_t, const wl_fixed_t)
static GWL_Seat * gwl_display_seat_active_get(const GWL_Display *display)
void(*)(GWL_Display *display, const GWL_RegisteryUpdate_Params ¶ms) GWL_RegistryHandler_UpdateFn
static const char * ghost_wl_surface_tag_id
static void xdg_output_handle_logical_size(void *data, zxdg_output_v1 *, const int32_t width, const int32_t height)
static signed char has_wl_trackpad_physical_direction
constexpr size_t events_pending_default_size
static void gwl_registry_xdg_wm_base_remove(GWL_Display *display, void *, const bool)
static bool setCursorGrab_use_software_confine(const GHOST_TGrabCursorMode mode, wl_surface *wl_surface)
static void data_offer_handle_offer(void *data, wl_data_offer *, const char *mime_type)
static const GHOST_TDragnDropTypes ghost_wl_mime_preference_order_type[]
static char * read_file_as_buffer(const int fd, const bool nil_terminate, size_t *r_len)
static void data_device_handle_motion(void *data, wl_data_device *, const uint32_t time, const wl_fixed_t x, const wl_fixed_t y)
static void gwl_registry_wl_output_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
static void gwl_registry_wp_fractional_scale_manager_remove(GWL_Display *display, void *, const bool)
static void gwl_registry_wp_fractional_scale_manager_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
GWL_TabletTool_EventTypes
static void gwl_seat_capability_pointer_multitouch_disable(GWL_Seat *seat)
#define CASE_CURSOR(shape_id, shape_name_in_theme)
static void output_handle_description(void *, wl_output *, const char *description)
static void gwl_registry_wp_pointer_gestures_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
static CLG_LogRef LOG_WL_DATA_SOURCE
bool ghost_wl_surface_own_cursor_pointer(const wl_surface *wl_surface)
static void gwl_simple_buffer_free_data(GWL_SimpleBuffer *buffer)
static CLG_LogRef LOG_WL_CURSOR_BUFFER
static void touch_seat_handle_frame(void *, wl_touch *)
static CLG_LogRef LOG_WL_DATA_DEVICE
static void gwl_seat_cursor_anim_reset(GWL_Seat *seat)
static void gwl_seat_capability_pointer_multitouch_enable(GWL_Seat *seat)
static const GHOST_TButton gwl_tablet_tool_ebutton[]
static void gwl_registry_xdg_output_manager_remove(GWL_Display *display, void *, const bool)
static GWL_SeatStateGrab seat_grab_state_from_mode(const GHOST_TGrabCursorMode mode, const bool use_software_confine)
static const int default_cursor_size
static const wl_seat_listener seat_listener
static const GWL_ModifierInfo g_modifier_info_table[MOD_INDEX_NUM]
static constexpr const char * ghost_wl_mime_text_utf8
static void gwl_seat_key_repeat_timer_add(GWL_Seat *seat, GHOST_TimerProcPtr key_repeat_fn, GHOST_TUserDataPtr payload, const bool use_delay)
static void data_source_handle_dnd_drop_performed(void *, wl_data_source *)
static void tablet_tool_handle_up(void *data, zwp_tablet_tool_v2 *)
static void gwl_xdg_decor_system_destroy(GWL_Display *display, GWL_XDG_Decor_System *decor)
static char * system_clipboard_get(GWL_Display *display)
static void gwl_simple_buffer_set_from_string(GWL_SimpleBuffer *buffer, const char *str)
static GWL_SeatStatePointer * gwl_seat_state_pointer_from_cursor_surface(GWL_Seat *seat, const wl_surface *wl_surface)
static void gwl_registry_xdg_activation_remove(GWL_Display *display, void *, const bool)
static int gwl_scaled_fixed_t_add_and_calc_rounded_delta(GWL_ScaledFixedT *sf, const wl_fixed_t add)
static const GWL_RegistryHandler gwl_registry_handlers[]
static void gwl_registry_wl_shm_remove(GWL_Display *display, void *, const bool)
static bool use_gnome_confine_hack
static void tablet_tool_handle_slider(void *, zwp_tablet_tool_v2 *, const int32_t position)
bool ghost_wl_surface_own_with_null_check(const wl_surface *wl_surface)
static int ghost_wl_display_event_pump_from_thread(wl_display *wl_display, const int fd, std::mutex *server_mutex)
static void output_handle_name(void *, wl_output *, const char *name)
static void data_device_handle_enter(void *data, wl_data_device *, const uint32_t serial, wl_surface *wl_surface, const wl_fixed_t x, const wl_fixed_t y, wl_data_offer *id)
static void system_clipboard_put(GWL_Display *display, const char *buffer)
static int gwl_display_seat_index(GWL_Display *display, const GWL_Seat *seat)
static const char * ghost_wl_output_tag_id
static const char * ghost_wl_mime_preference_order[]
static void shell_handle_ping(void *, xdg_wm_base *xdg_wm_base, const uint32_t serial)
static int file_descriptor_is_io_ready(int fd, const int flags, const int timeout_ms)
static void gwl_pointer_handle_frame_event_add(GWL_SeatStatePointer_Events *pointer_events, const GWL_Pointer_EventTypes ty, const uint64_t event_ms)
static void dnd_events(const GWL_Seat *const seat, const GHOST_TEventType event, const uint64_t event_ms)
static void tablet_tool_handle_pressure(void *data, zwp_tablet_tool_v2 *, const uint32_t pressure)
static int cursor_buffer_compatible_scale_from_image(const wl_cursor_image *wl_image, int scale)
static void gwl_registry_wp_pointer_constraints_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
#define GWL_IFACE_VERSION_CLAMP(params_version, version_min, version_max)
static char * system_clipboard_get_primary_selection(GWL_Display *display)
static int gwl_registry_handler_interface_slot_max()
static void gwl_registry_wl_output_update(GWL_Display *display, const GWL_RegisteryUpdate_Params ¶ms)
static void xdg_output_handle_done(void *data, zxdg_output_v1 *)
static void gwl_registry_wp_primary_selection_device_manager_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
static size_t ghost_wl_shm_format_as_size(enum wl_shm_format format)
static void gwl_registry_compositor_remove(GWL_Display *display, void *, const bool)
wl_fixed_t gwl_window_scale_wl_fixed_to(const GWL_WindowScaleParams &scale_params, wl_fixed_t value)
wl_fixed_t gwl_window_scale_wl_fixed_from(const GWL_WindowScaleParams &scale_params, wl_fixed_t value)
int gwl_window_scale_int_to(const GWL_WindowScaleParams &scale_params, int value)
#define FRACTIONAL_DENOMINATOR
bool ghost_wl_output_own(const struct wl_output *wl_output)
struct GWL_Output * ghost_wl_output_user_data(struct wl_output *wl_output)
GHOST_WindowWayland * ghost_wl_surface_user_data(struct wl_surface *wl_surface)
@ GHOST_kTrackpadEventMagnify
@ GHOST_kTrackpadEventRotate
@ GHOST_kTrackpadEventScroll
void * GHOST_TUserDataPtr
@ GHOST_kStandardCursorLeftHandle
@ GHOST_kStandardCursorHandClosed
@ GHOST_kStandardCursorHandOpen
@ GHOST_kStandardCursorBottomLeftCorner
@ GHOST_kStandardCursorZoomIn
@ GHOST_kStandardCursorVerticalSplit
@ GHOST_kStandardCursorHelp
@ GHOST_kStandardCursorCopy
@ GHOST_kStandardCursorWait
@ GHOST_kStandardCursorRightHandle
@ GHOST_kStandardCursorHorizontalSplit
@ GHOST_kStandardCursorTopSide
@ GHOST_kStandardCursorStop
@ GHOST_kStandardCursorCrosshair
@ GHOST_kStandardCursorCustom
@ GHOST_kStandardCursorNSEWScroll
@ GHOST_kStandardCursorLeftRight
@ GHOST_kStandardCursorPencil
@ GHOST_kStandardCursorNSScroll
@ GHOST_kStandardCursorCrosshairA
@ GHOST_kStandardCursorUpDown
@ GHOST_kStandardCursorUpArrow
@ GHOST_kStandardCursorHandPoint
@ GHOST_kStandardCursorBottomSide
@ GHOST_kStandardCursorBothHandles
@ GHOST_kStandardCursorInfo
@ GHOST_kStandardCursorTopLeftCorner
@ GHOST_kStandardCursorEyedropper
@ GHOST_kStandardCursorKnife
@ GHOST_kStandardCursorMove
@ GHOST_kStandardCursorCrosshairB
@ GHOST_kStandardCursorBottomRightCorner
@ GHOST_kStandardCursorDownArrow
@ GHOST_kStandardCursorEraser
@ GHOST_kStandardCursorDefault
@ GHOST_kStandardCursorEWScroll
@ GHOST_kStandardCursorRightSide
@ GHOST_kStandardCursorRightArrow
@ GHOST_kStandardCursorTopRightCorner
@ GHOST_kStandardCursorDestroy
@ GHOST_kStandardCursorCrosshairC
@ GHOST_kStandardCursorZoomOut
@ GHOST_kStandardCursorLeftSide
@ GHOST_kStandardCursorText
@ GHOST_kStandardCursorLeftArrow
#define GHOST_KEY_MODIFIER_TO_INDEX(key)
#define GHOST_kStandardCursorNumCursors
@ GHOST_kEventDraggingDropDone
@ GHOST_kEventDraggingExited
@ GHOST_kEventImeComposition
@ GHOST_kEventDraggingUpdated
@ GHOST_kEventDraggingEntered
@ GHOST_kEventWindowActivate
@ GHOST_kEventWindowDeactivate
@ GHOST_kEventImeCompositionStart
@ GHOST_kEventImeCompositionEnd
static const GHOST_TabletData GHOST_TABLET_DATA_NONE
#define GHOST_KEY_MODIFIER_CHECK(key)
#define GHOST_KEY_MODIFIER_NUM
@ GHOST_kTabletModeEraser
@ GHOST_kTabletModeStylus
@ GHOST_kCapabilityWindowPosition
@ GHOST_kCapabilityGPUReadFrontBuffer
@ GHOST_kCapabilityCursorWarp
@ GHOST_kCapabilityTrackpadPhysicalDirection
@ GHOST_kCapabilityDesktopSample
#define GHOST_CAPABILITY_FLAG_ALL
#define GHOST_KEY_MODIFIER_FROM_INDEX(key)
void(* GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__ *task, uint64_t time)
@ GHOST_kKeyNumpadAsterisk
GHOST_TDrawingContextType
@ GHOST_kDrawingContextTypeNone
@ GHOST_kModifierKeyRightControl
@ GHOST_kModifierKeyLeftControl
@ GHOST_kModifierKeyRightAlt
@ GHOST_kModifierKeyRightShift
@ GHOST_kModifierKeyLeftAlt
@ GHOST_kModifierKeyLeftShift
@ GHOST_kModifierKeyLeftOS
@ GHOST_kModifierKeyRightOS
void(* GHOST_TBacktraceFn)(void *file_handle)
@ GHOST_kDragnDropTypeUnknown
@ GHOST_kDragnDropTypeFilenames
@ GHOST_kDragnDropTypeString
@ GHOST_kButtonMaskButton4
@ GHOST_kButtonMaskButton7
@ GHOST_kButtonMaskButton6
@ GHOST_kButtonMaskButton5
@ GHOST_kButtonMaskMiddle
GHOST_TConsoleWindowState
#define WL_ARRAY_FOR_EACH(pos, array)
static const wl_surface_listener wl_surface_listener
#define USE_EVENT_BACKGROUND_THREAD
Contains defines and structs used throughout the imbuf module.
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
btAlignedObjectArray< btScalar > m_data
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
static GHOST_TBacktraceFn getBacktraceFn()
virtual GHOST_TUserDataPtr getUserData() const =0
virtual GHOST_TimerProcPtr getTimerProc() const =0
virtual void wrapPoint(int32_t &x, int32_t &y, int32_t ofs, GHOST_TAxisFlag axis)
struct zwp_primary_selection_device_manager_v1 * wp_primary_selection_manager_get()
static const char * xdg_app_id_get()
GHOST_TSuccess init() override
GHOST_TSuccess pushEvent_maybe_pending(const GHOST_IEvent *event)
bool window_surface_unref(const wl_surface *wl_surface)
uint64_t getMilliSeconds() const override
GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const override
bool window_cursor_grab_set(const GHOST_TGrabCursorMode mode, const GHOST_TGrabCursorMode mode_current, int32_t init_grab_xy[2], const GHOST_Rect *wrap_bounds, GHOST_TAxisFlag wrap_axis, wl_surface *wl_surface, const struct GWL_WindowScaleParams &scale_params)
GHOST_TSuccess cursor_visibility_set(bool visible)
std::thread::id main_thread_id
struct wl_display * wl_display_get()
char * getClipboard(bool selection) const override
GHOST_TSuccess setCursorPosition(int32_t x, int32_t y) override
GHOST_TSuccess cursor_shape_check(GHOST_TStandardCursor cursorShape)
bool cursor_grab_use_software_display_get(const GHOST_TGrabCursorMode mode)
uint64_t ms_from_input_time(const uint32_t timestamp_as_uint)
GHOST_TimerManager * ghost_timer_manager()
uint * getClipboardImage(int *r_width, int *r_height) const override
struct xdg_wm_base * xdg_decor_shell_get()
struct wl_compositor * wl_compositor_get()
struct wp_fractional_scale_manager_v1 * wp_fractional_scale_manager_get()
void setMultitouchGestures(const bool use) override
struct wl_shm * wl_shm_get() const
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const override
GHOST_TSuccess cursor_shape_set(GHOST_TStandardCursor shape)
const std::vector< GWL_Output * > & outputs_get() const
GHOST_TSuccess disposeContext(GHOST_IContext *context) override
GHOST_IWindow * createWindow(const char *title, int32_t left, int32_t top, uint32_t width, uint32_t height, GHOST_TWindowState state, GHOST_GPUSettings gpuSettings, const bool exclusive, const bool is_dialog, const GHOST_IWindow *parentWindow) override
struct wp_viewporter * wp_viewporter_get()
struct zxdg_decoration_manager_v1 * xdg_decor_manager_get()
struct wl_seat * wl_seat_active_get_with_input_serial(uint32_t &serial)
GHOST_TSuccess cursor_bitmap_get(GHOST_CursorBitmapRef *bitmap)
GHOST_TSuccess cursor_shape_custom_set(const uint8_t *bitmap, const uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor)
GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const override
void ime_begin(const GHOST_WindowWayland *win, int32_t x, int32_t y, int32_t w, int32_t h, bool completed) const
uint8_t getNumDisplays() const override
bool output_unref(struct wl_output *wl_output)
~GHOST_SystemWayland() override
void putClipboard(const char *buffer, bool selection) const override
void output_scale_update(GWL_Output *output)
GHOST_TCapabilityFlag getCapabilities() const override
std::atomic< bool > has_pending_actions_for_window
bool processEvents(bool waitForEvent) override
void seat_active_set(const struct GWL_Seat *seat)
GHOST_TSuccess getCursorPositionClientRelative(const GHOST_IWindow *window, int32_t &x, int32_t &y) const override
GHOST_TSuccess setCursorPositionClientRelative(GHOST_IWindow *window, int32_t x, int32_t y) override
GHOST_TSuccess hasClipboardImage() const override
bool setConsoleWindowState(GHOST_TConsoleWindowState action) override
std::mutex * server_mutex
void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const override
struct xdg_activation_v1 * xdg_activation_manager_get()
struct zwp_pointer_gestures_v1 * wp_pointer_gestures_get()
void ime_end(const GHOST_WindowWayland *win) const
GHOST_IContext * createOffscreenContext(GHOST_GPUSettings gpuSettings) override
void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const override
GHOST_TSuccess putClipboardImage(uint *rgba, int width, int height) const override
GHOST_EventManager * getEventManager() const
GHOST_WindowManager * getWindowManager() const
GHOST_TSuccess removeTimer(GHOST_ITimerTask *timerTask)
bool m_multitouchGestures
virtual GHOST_TSuccess init()
GHOST_TimerManager * getTimerManager() const
GHOST_WindowManager * m_windowManager
GHOST_ITimerTask * installTimer(uint64_t delay, uint64_t interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData=nullptr)
GHOST_TSuccess removeTimer(GHOST_TimerTask *timer)
GHOST_TSuccess addTimer(GHOST_TimerTask *timer)
GHOST_TSuccess addWindow(GHOST_IWindow *window)
const std::vector< GHOST_IWindow * > & getWindows() const
GHOST_TSuccess setActiveWindow(GHOST_IWindow *window)
void setWindowInactive(const GHOST_IWindow *window)
const struct GWL_WindowScaleParams & scale_params_get() const
bool outputs_leave(GWL_Output *output)
wl_fixed_t wl_fixed_to_window(wl_fixed_t value) const
void outputs_changed_update_scale_tag()
bool getValid() const override
wl_fixed_t wl_fixed_from_window(wl_fixed_t value) const
void getClientBounds(GHOST_Rect &bounds) const override
GHOST_TSuccess cursor_shape_refresh()
const void pending_actions_handle()
const std::vector< GWL_Output * > & outputs_get()
GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds) const override
GHOST_TAxisFlag getCursorGrabAxis() const
bool getCursorGrabModeIsWarp() const
input_tx image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img") .compute_source("compositor_compute_preview.glsl") .do_static_compilation(true)
local_group_size(16, 16) .push_constant(Type b
static __attribute__((constructor)) void cpu_check()
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
struct ImBuf * IMB_ibImageFromMemory(const unsigned char *, size_t, int, char[IM_MAX_SPACE], const char *)
bool IMB_saveiff(struct ImBuf *, const char *, int)
struct ImBuf * IMB_allocFromBuffer(const uint8_t *, const float *, unsigned int, unsigned int, unsigned int)
void IMB_freeImBuf(ImBuf *)
ccl_device_inline float4 select(const int4 mask, const float4 a, const float4 b)
static void error(const char *str)
static void add(blender::Map< std::string, std::string > &messages, Message &msg)
bool is_enabled(const Sculpt &sd, const Object &object, const Brush *br)
unsigned __int64 uint64_t
GHOST_TDrawingContextType context_type
GHOST_GPUDevice preferred_device
void set(GHOST_TModifierKey mask, bool down)
GHOST_TUserDataPtr composite_len
GHOST_TUserDataPtr result_len
GHOST_TUserDataPtr result
GHOST_TUserDataPtr composite
std::atomic< bool > exit_pending
const char * names[GHOST_kStandardCursorNumCursors]
struct GWL_Cursor::@1482 wl
GWL_Cursor_AnimHandle * anim_handle
const wl_cursor * theme_cursor
wl_surface * surface_cursor
const char * theme_cursor_name
std::unordered_set< std::string > types
struct GWL_DataOffer::@1487 dnd
enum wl_data_device_manager_dnd_action source_actions
struct GWL_DataOffer::@1486 wl
enum wl_data_device_manager_dnd_action action
GWL_SimpleBuffer buffer_out
struct GWL_DataSource::@1488 wl
wp_viewporter * viewporter
zwp_primary_selection_device_manager_v1 * primary_selection_device_manager
std::vector< GWL_Seat * > seats
bool events_pthread_is_active
GHOST_TimerManager * ghost_timer_manager
std::vector< const GHOST_IEvent * > events_pending
std::vector< GWL_Output * > outputs
zwp_pointer_gestures_v1 * pointer_gestures
struct GWL_Display::@1501 xdg
GWL_DisplayTimeStamp input_timestamp
GWL_XDG_Decor_System * xdg_decor
bool registry_skip_update_all
GWL_RegistryEntry * registry_entry
struct GWL_Display::@1500 wp
zwp_pointer_constraints_v1 * pointer_constraints
zwp_relative_pointer_manager_v1 * relative_pointer_manager
wl_compositor * compositor
zxdg_output_manager_v1 * output_manager
xdg_activation_v1 * activation_manager
wl_data_device_manager * data_device_manager
zwp_tablet_manager_v2 * tablet_manager
struct GWL_Display::@1499 wl
GHOST_SystemWayland * system
std::mutex events_pending_mutex
wp_fractional_scale_manager_v1 * fractional_scale_manager
struct GWL_KeyRepeatPlayload::@1489 key_data
int16_t mods[GHOST_KEY_MODIFIER_NUM]
const char * display_name
int32_t position_logical[2]
struct GWL_Output::@1503 xdg
GHOST_SystemWayland * system
zwp_primary_selection_offer_v1 * id
struct GWL_PrimarySelection_DataOffer::@1493 wp
std::unordered_set< std::string > types
GWL_SimpleBuffer buffer_out
zwp_primary_selection_source_v1 * source
struct GWL_PrimarySelection_DataSource::@1494 wp
GWL_PrimarySelection_DataSource * data_source
std::mutex data_offer_mutex
GWL_PrimarySelection_DataOffer * data_offer
std::mutex data_source_mutex
GWL_RegistryHandler_AddFn add_fn
const char *const * interface_p
GWL_RegistryEntry_RemoveFn remove_fn
GWL_RegistryHandler_UpdateFn update_fn
wl_surface * surface_window
struct GWL_SeatStateKeyboard::@1492 wl
GWL_ScaledFixedT rotation
GWL_Pointer_EventTypes frame_types[GWL_TabletTool_FrameTypes_NUM]
uint64_t frame_event_ms[GWL_TabletTool_FrameTypes_NUM]
struct GWL_SeatStatePointer_Events::@1491 frame_pending
struct GWL_SeatStatePointer::@1490 wl
wl_surface * surface_window
std::unordered_set< const GWL_Output * > outputs
GHOST_SystemWayland * system
GWL_SeatStatePointerScroll pointer_scroll
struct GWL_Seat::@1497 xkb
GWL_KeyboardDepressedState key_depressed
GWL_SeatStatePointer_Events pointer_events
GWL_DataSource * data_source
uint32_t data_source_serial
struct GWL_Seat::@1498 key_repeat
std::unordered_set< zwp_tablet_tool_v2 * > tablet_tools
GWL_DataOffer * data_offer_copy_paste
zwp_primary_selection_device_v1 * primary_selection_device
GWL_SeatStatePointer pointer
struct GWL_Seat::@1495 wl
std::mutex data_source_mutex
xkb_mod_index_t xkb_keymap_mod_index[MOD_INDEX_NUM]
zwp_relative_pointer_v1 * relative_pointer
xkb_compose_state * compose_state
xkb_state * state_empty_with_shift
std::mutex data_offer_dnd_mutex
xkb_state * state_empty_with_numlock
GWL_PrimarySelection primary_selection
std::mutex data_offer_copy_paste_mutex
uint32_t cursor_source_serial
GWL_SeatStatePointer tablet
bool use_pointer_scroll_smooth_as_discrete
zwp_tablet_seat_v2 * tablet_seat
wl_surface * surface_window_focus_dnd
xkb_layout_index_t layout_active
zwp_confined_pointer_v1 * confined_pointer
xkb_compose_table * compose_table
wl_data_device * data_device
xkb_mod_index_t xkb_keymap_mod_index_numlock
bool xkb_use_non_latin_workaround
wl_fixed_t grab_lock_xy[2]
GWL_DataOffer * data_offer_dnd
xkb_mod_index_t xkb_keymap_mod_index_mod2
zwp_locked_pointer_v1 * locked_pointer
GWL_SeatStatePointerGesture_Pinch pointer_gesture_pinch
GWL_SeatStateKeyboard keyboard
bool use_pointer_software_confine
struct GWL_Seat::@1496 wp
zxdg_decoration_manager_v1 * manager
ImbFormatOptions foptions
ImBufByteBuffer byte_buffer
unsigned int encoded_buffer_size
ImBufByteBuffer encoded_buffer
void wayland_dynload_client_exit(void)
void wayland_dynload_cursor_exit(void)
bool wayland_dynload_cursor_init(bool verbose)
bool wayland_dynload_client_init(bool verbose)
#define wl_proxy_get_tag(...)
#define wl_display_connect(...)
#define wl_log_set_handler_client(...)
#define wl_display_dispatch_pending(...)
#define wl_proxy_set_tag(...)
#define wl_display_get_error(...)
#define wl_display_cancel_read(...)
#define wl_display_dispatch(...)
#define wl_display_get_fd(...)
#define wl_display_prepare_read(...)
#define wl_display_flush(...)
#define wl_display_get_protocol_error(...)
#define wl_display_disconnect(...)
#define wl_display_read_events(...)
#define wl_display_roundtrip(...)
#define wl_cursor_theme_get_cursor(...)
#define wl_cursor_theme_load(...)
#define wl_cursor_image_get_buffer(...)
#define wl_cursor_theme_destroy(...)
bool wayland_dynload_egl_init(const bool verbose)
void wayland_dynload_egl_exit(void)
#define wl_egl_window_create(...)
#define wl_egl_window_destroy(...)
bool wayland_dynload_libdecor_init(const bool verbose)
void wayland_dynload_libdecor_exit(void)
#define libdecor_unref(...)
#define libdecor_new(...)