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_set>
53#ifdef WITH_GHOST_WAYLAND_DYNLOAD
56#include <wayland-cursor.h>
58#include <xkbcommon/xkbcommon-compose.h>
59#include <xkbcommon/xkbcommon.h>
62#include <cursor-shape-v1-client-protocol.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-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;
130 int *r_interface_slot);
139 xkb_compose_state *compose_state,
141 const xkb_keycode_t key,
144#ifdef USE_EVENT_BACKGROUND_THREAD
156#define pushEvent DONT_USE
171#define USE_GNOME_CONFINE_HACK
178#ifdef USE_GNOME_CONFINE_HACK
187#define USE_KDE_TABLET_HIDDEN_CURSOR_HACK
212#ifdef USE_VERBOSE_OLD_IFACE_PRINT
213# define _VERBOSE_OLD_IFACE_PRINT(params_version, version_max) \
214 ((params_version > version_max) ? \
216 "%s: version_max=%u, is smaller than run-time version=%u\n", \
222# define _VERBOSE_OLD_IFACE_PRINT(params_version, version_max) \
223 ((void)(params_version), (version_max))
226#define GWL_IFACE_VERSION_CLAMP(params_version, version_min, version_max) \
227 ((void)_VERBOSE_OLD_IFACE_PRINT(params_version, version_max), \
228 std::clamp(params_version, version_min, version_max))
234#define USE_NON_LATIN_KB_WORKAROUND
236#define WL_NAME_UNSET uint32_t(-1)
242#define WL_FIXED_TO_INT_FOR_WINDOW_V2(win, xy) \
243 wl_fixed_to_int((win)->wl_fixed_to_window((xy)[0])), \
244 wl_fixed_to_int((win)->wl_fixed_to_window((xy)[1])),
270#define BTN_RANGE_MIN BTN_LEFT
271#define BTN_RANGE_MAX BTN_BACK
304#ifdef USE_NON_LATIN_KB_WORKAROUND
319#ifndef XKB_VMOD_NAME_HYPER
320# define XKB_VMOD_NAME_HYPER "Hyper"
338#define MOD_INDEX_NUM (MOD_INDEX_HYPER + 1)
410 free(
const_cast<char *
>(buffer->
data));
411 buffer->
data =
nullptr;
417 free(
const_cast<char *
>(buffer->
data));
434#define EVDEV_OFFSET 8
445 wp_cursor_shape_device_v1_shape
enum_id = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT;
446 wp_cursor_shape_device_v1 *
device =
nullptr;
521#define GWL_TabletTool_FrameTypes_NUM (int(GWL_TabletTool_EventTypes::Stylus3_Up) + 1)
582 const int ty_mask = 1 << int(ty);
611 wl_data_offer *
id =
nullptr;
614 std::unordered_set<std::string>
types;
623 enum wl_data_device_manager_dnd_action
source_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
624 enum wl_data_device_manager_dnd_action
action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
626 wl_fixed_t
xy[2] = {0, 0};
710 wl_fixed_t
xy[2] = {0, 0};
713 std::unordered_set<const GWL_Output *>
outputs;
762#define GWL_SeatStatePointer_EventTypes_NUM (int(GWL_Pointer_EventTypes::Button6_Up) + 1)
801 GHOST_ASSERT(event_ms == 0,
"Scroll events must not have a time-stamp");
804 GHOST_ASSERT(event_ms != 0,
"Non-scroll events must have a time-stamp");
807 const int ty_mask = 1 << int(ty);
849 enum wl_pointer_axis_source
axis_source = WL_POINTER_AXIS_SOURCE_WHEEL;
878 const wl_fixed_t
add)
880 const int result_prev = wl_fixed_to_int(sf->
value * sf->
factor);
882 const int result_curr = wl_fixed_to_int(sf->
value * sf->
factor);
883 return result_curr - result_prev;
922#ifdef WITH_GHOST_WAYLAND_LIBDECOR
923struct GWL_LibDecor_System {
927static void gwl_libdecor_system_destroy(GWL_LibDecor_System *decor)
929 if (decor->context) {
931 decor->context =
nullptr;
941 zxdg_decoration_manager_v1 *
manager =
nullptr;
962 zwp_primary_selection_offer_v1 *
id =
nullptr;
965 std::unordered_set<std::string>
types;
972 zwp_primary_selection_source_v1 *
source =
nullptr;
993 zwp_primary_selection_offer_v1_destroy(primary->
data_offer->
wp.
id);
1001 if (data_source ==
nullptr) {
1006 zwp_primary_selection_source_v1_destroy(data_source->
wp.
source);
1012#ifdef WITH_INPUT_IME
1022 GHOST_TEventImeData event_ime_data = {
1038 bool has_preedit =
false;
1041 bool result_is_null =
false;
1043 bool composite_is_null =
false;
1046 bool has_preedit_string_callback =
false;
1048 bool has_commit_string_callback =
false;
1077#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
1078 zwp_pointer_gesture_hold_v1 *pointer_gesture_hold =
nullptr;
1080#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE
1083#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE
1084 zwp_pointer_gesture_swipe_v1 *pointer_gesture_swipe =
nullptr;
1096#ifdef WITH_INPUT_IME
1097 zwp_text_input_v3 *text_input =
nullptr;
1134#ifdef WITH_INPUT_IME
1184#ifdef USE_GNOME_CONFINE_HACK
1192#ifdef USE_NON_LATIN_KB_WORKAROUND
1266 return &seat->
touch;
1280 GHOST_ASSERT(0,
"Surface found without pointer/tablet tag");
1298 xkb_state_update_mask(seat->
xkb.
state_empty, 0, 0, 0, 0, 0, group);
1302 "Invalid state for SHIFT");
1308 GHOST_ASSERT((mod_mod2 == XKB_MOD_INVALID || mod_numlock == XKB_MOD_INVALID) ==
1310 "Invalid state for NUMLOCK");
1312 xkb_state_update_mask(
1324 if (
UNLIKELY(wl_surface_focus ==
nullptr)) {
1341 xkb_state_key_get_utf8(seat->
xkb.
state, payload->
key_code, utf8_buf,
sizeof(utf8_buf));
1358 const bool use_delay)
1369#ifdef USE_EVENT_BACKGROUND_THREAD
1371 time_now + time_start, time_step, key_repeat_fn, payload);
1385#ifdef USE_EVENT_BACKGROUND_THREAD
1394#ifdef WITH_INPUT_IME
1396static void gwl_seat_ime_full_reset(
GWL_Seat *seat)
1398 const GWL_SeatIME ime_default{};
1401 wl_surface *surface_window = seat->ime.surface_window;
1402 const bool is_enabled = seat->ime.is_enabled;
1403 const bool has_preedit_string_callback = seat->ime.has_preedit_string_callback;
1404 const bool has_commit_string_callback = seat->ime.has_commit_string_callback;
1406 seat->ime = ime_default;
1408 seat->ime.surface_window = surface_window;
1410 seat->ime.has_preedit_string_callback = has_preedit_string_callback;
1411 seat->ime.has_commit_string_callback = has_commit_string_callback;
1414static void gwl_seat_ime_result_reset(
GWL_Seat *seat)
1417 event_ime_data.
result.clear();
1418 seat->ime.result_is_null =
false;
1421static void gwl_seat_ime_preedit_reset(
GWL_Seat *seat)
1426 seat->ime.composite_is_null =
false;
1433static void gwl_seat_ime_rect_reset(
GWL_Seat *seat)
1435 seat->ime.rect.x = -1;
1436 seat->ime.rect.y = -1;
1437 seat->ime.rect.w = -1;
1438 seat->ime.rect.h = -1;
1490#ifdef WITH_INPUT_IME
1491 zwp_text_input_manager_v3 *text_input_manager =
nullptr;
1516#ifdef WITH_GHOST_WAYLAND_LIBDECOR
1517 GWL_LibDecor_System *libdecor =
nullptr;
1557#ifdef USE_EVENT_BACKGROUND_THREAD
1601#ifdef USE_EVENT_BACKGROUND_THREAD
1620#ifdef WITH_GHOST_WAYLAND_LIBDECOR
1622 if (display->libdecor) {
1623 gwl_libdecor_system_destroy(display->libdecor);
1624 display->libdecor =
nullptr;
1636#ifdef WITH_OPENGL_BACKEND
1638 if (eglGetDisplay) {
1639 ::eglTerminate(eglGetDisplay(EGLNativeDisplayType(display->
wl.
display)));
1644#ifdef USE_EVENT_BACKGROUND_THREAD
1673 std::vector<GWL_Seat *>::iterator iter = std::find(
1674 display->
seats.begin(), display->
seats.end(), seat);
1675 const int index = (iter != display->
seats.cend()) ? std::distance(display->
seats.begin(), iter) :
1826 int *r_interface_slot)
1832 if (r_interface_slot) {
1833 *r_interface_slot = -1;
1842 if (r_interface_slot) {
1846 *reg_link_p = reg_next;
1850 reg_link_p = ®->
next;
1857 const int interface_slot,
1871 *reg_link_p = reg_next;
1876 reg_link_p = ®->
next;
1887 const bool on_exit =
true;
1901 while (interface_slot--) {
1927 GHOST_ASSERT(interface_slot_exclude == -1 || (
uint(interface_slot_exclude) <
1929 "Invalid exclude slot");
1932 if (reg->interface_slot == interface_slot_exclude) {
1936 reg->interface_slot);
1943 params.interface_slot = reg->interface_slot;
1944 params.version = reg->version;
1945 params.user_data = reg->user_data;
1959 return ((
x + multiple - 1) / multiple) * multiple;
1964 uint8_t *rgba =
reinterpret_cast<uint8_t *
>(&rgba_uint);
1965 const uint32_t alpha = uint32_t(rgba[3]);
1966 rgba[0] = uint8_t(((alpha * rgba[0]) + (0xff / 2)) / 0xff);
1967 rgba[1] = uint8_t(((alpha * rgba[1]) + (0xff / 2)) / 0xff);
1968 rgba[2] = uint8_t(((alpha * rgba[2]) + (0xff / 2)) / 0xff);
1974 uint8_t *rgba =
reinterpret_cast<uint8_t *
>(&rgba_uint);
1975 const uint32_t alpha = uint32_t(rgba[3]);
1976 rgba[0] = uint8_t(((alpha * (0xff - rgba[0])) + (0xff / 2)) / 0xff);
1977 rgba[1] = uint8_t(((alpha * (0xff - rgba[1])) + (0xff / 2)) / 0xff);
1978 rgba[2] = uint8_t(((alpha * (0xff - rgba[2])) + (0xff / 2)) / 0xff);
1982#ifdef WITH_GHOST_WAYLAND_LIBDECOR
1983static const char *strchr_or_end(
const char *
str,
const char ch)
1985 const char *p =
str;
1986 while (!
ELEM(*p, ch,
'\0')) {
1992static bool string_elem_split_by_delim(
const char *haystack,
const char delim,
const char *needle)
1997 const size_t needle_len = strlen(needle);
1998 const char *p = haystack, *p_next;
2000 p_next = strchr_or_end(p, delim);
2001 if ((
size_t(p_next - p) == needle_len) && (memcmp(p, needle, needle_len) == 0)) {
2004 if (*p_next ==
'\0') {
2015 return a >
b ? a -
b :
b - a;
2031 const char *locale = getenv(
"LC_ALL");
2032 if (!locale || !*locale) {
2033 locale = getenv(
"LC_CTYPE");
2034 if (!locale || !*locale) {
2035 locale = getenv(
"LANG");
2036 if (!locale || !*locale) {
2047 if (
ELEM(ecode, EPIPE, ECONNRESET)) {
2048 fprintf(stderr,
"The Wayland connection broke. Did the Wayland compositor die?\n");
2052 if (ecode == EPROTO) {
2053 const wl_interface *
interface =
nullptr;
2056 "The Wayland connection experienced a protocol error %d in interface: %s\n",
2059 const char *env_debug =
"WAYLAND_DEBUG";
2060 if (getenv(env_debug) ==
nullptr) {
2061 fprintf(stderr,
"Run with the environment variable \"%s=1\" for details.\n", env_debug);
2066 fprintf(stderr,
"The Wayland connection experienced a fatal error: %s\n", strerror(ecode));
2115 fprintf(stderr,
"GHOST/Wayland: ");
2116 vfprintf(stderr, msg, arg);
2120 backtrace_fn(stderr);
2129 if (strstr(msg,
"error: XDG_RUNTIME_DIR not set in the environment") ||
2130 strstr(msg,
"error: XDG_RUNTIME_DIR is invalid or not set in the environment"))
2137#if defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND_LIBDECOR)
2143static bool ghost_wayland_is_x11_available()
2145 const char *x11_display = getenv(
"DISPLAY");
2146 if (x11_display && x11_display[0]) {
2157 if (sym >= XKB_KEY_0 && sym <= XKB_KEY_9) {
2160 else if (sym >= XKB_KEY_KP_0 && sym <= XKB_KEY_KP_9) {
2163 else if (sym >= XKB_KEY_A && sym <= XKB_KEY_Z) {
2166 else if (sym >= XKB_KEY_a && sym <= XKB_KEY_z) {
2167 gkey =
GHOST_TKey(sym - XKB_KEY_a + XKB_KEY_A);
2169 else if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F24) {
2174#define GXMAP(k, x, y) \
2288 "unhandled key: " << std::hex << std::showbase << sym <<
2289 std::dec <<
" (" << sym <<
"), " <<
2291 "scan-code: " << std::hex << std::showbase << key <<
2292 std::dec <<
" (" << key <<
")" <<
2305 case WL_POINTER_AXIS_HORIZONTAL_SCROLL: {
2308 case WL_POINTER_AXIS_VERTICAL_SCROLL: {
2319 switch (wp_tablet_tool_type) {
2320 case ZWP_TABLET_TOOL_V2_TYPE_ERASER: {
2323 case ZWP_TABLET_TOOL_V2_TYPE_PEN:
2324 case ZWP_TABLET_TOOL_V2_TYPE_BRUSH:
2325 case ZWP_TABLET_TOOL_V2_TYPE_PENCIL:
2326 case ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH:
2327 case ZWP_TABLET_TOOL_V2_TYPE_FINGER:
2328 case ZWP_TABLET_TOOL_V2_TYPE_MOUSE:
2329 case ZWP_TABLET_TOOL_V2_TYPE_LENS: {
2334 GHOST_PRINT(
"unknown tablet tool: " << wp_tablet_tool_type << std::endl);
2361 "text/plain;charset=utf-8",
2370 size_t data_buf_len)
2372 std::vector<std::string_view> uris;
2373 const char file_proto[] =
"file://";
2376 const char lf =
'\n';
2378 const std::string_view
data = std::string_view(data_buf, data_buf_len);
2381 while (
pos != std::string::npos) {
2383 if (
pos == std::string::npos) {
2386 const size_t start =
pos +
sizeof(file_proto) - 1;
2390 if (
UNLIKELY(end == std::string::npos)) {
2396 if (
data[end - 1] ==
'\r') {
2400 std::string_view data_substr =
data.substr(start, end - start);
2401 uris.push_back(data_substr);
2406#ifdef USE_EVENT_BACKGROUND_THREAD
2410 sched_param sch_params;
2411 if (pthread_getschedparam(handle, &policy, &sch_params) == 0) {
2412 sch_params.sched_priority = sched_get_priority_min(policy);
2413 pthread_setschedparam(handle, policy, &sch_params);
2421#ifdef HAVE_MEMFD_CREATE
2422 const int fd = memfd_create(
name, MFD_CLOEXEC | MFD_ALLOW_SEALING);
2424 fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
2428 char *path = getenv(
"XDG_RUNTIME_DIR");
2434 asprintf(&tmpname,
"%s/%s-XXXXXX", path,
name);
2435 const int fd = mkostemp(tmpname, O_CLOEXEC);
2464 info.events |= POLLIN | POLLPRI;
2467 info.events |= POLLOUT;
2469 result = poll(&info, 1, timeout_ms);
2471 fd_set rfdset, *rfdp =
nullptr;
2472 fd_set wfdset, *wfdp =
nullptr;
2473 struct timeval tv, *tvp =
nullptr;
2480 FD_SET(fd, &rfdset);
2485 FD_SET(fd, &wfdset);
2489 if (timeout_ms >= 0) {
2490 tv.tv_sec = timeout_ms / 1000;
2491 tv.tv_usec = (timeout_ms % 1000) * 1000;
2528#ifdef USE_EVENT_BACKGROUND_THREAD
2538 server_mutex->lock();
2544 }
while (
state == 0);
2549 std::mutex *server_mutex)
2552 server_mutex->lock();
2555 bool wait_on_fd =
false;
2566 server_mutex->unlock();
2574 server_mutex->unlock();
2580 server_mutex->lock();
2585 server_mutex->unlock();
2596 case WL_SHM_FORMAT_ARGB8888: {
2616 enum wl_shm_format
format,
2617 void **r_buffer_data,
2618 size_t *r_buffer_data_size)
2621 wl_buffer *buffer =
nullptr;
2624 const int32_t buffer_size = buffer_stride * size_xy[1];
2625 if (posix_fallocate(fd, 0, buffer_size) == 0) {
2626 void *buffer_data = mmap(
nullptr, buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
2627 if (buffer_data != MAP_FAILED) {
2628 wl_shm_pool *pool = wl_shm_create_pool(shm, fd, buffer_size);
2629 buffer = wl_shm_pool_create_buffer(pool, 0,
UNPACK2(size_xy), buffer_stride,
format);
2630 wl_shm_pool_destroy(pool);
2632 *r_buffer_data = buffer_data;
2633 *r_buffer_data_size = size_t(buffer_size);
2637 munmap(buffer_data, buffer_size);
2652 ssize_t nbytes_read =
read(fd,
data, nbytes);
2653 if (nbytes_read > 0) {
2654 while (nbytes_read < nbytes) {
2655 const ssize_t nbytes_extra =
read(
2656 fd,
static_cast<char *
>(
data) + nbytes_read, nbytes - nbytes_read);
2657 if (nbytes_extra > 0) {
2658 nbytes_read += nbytes_extra;
2662 nbytes_read = nbytes_extra;
2682 char data[4096 -
sizeof(ByteChunk *)];
2687 ByteChunk *chunk_first =
static_cast<ByteChunk *
>(malloc(
sizeof(ByteChunk)));
2689 ByteChunk **chunk_link_p = &chunk_first;
2690 ByteChunk *chunk = chunk_first;
2697 chunk->next =
nullptr;
2699 const ssize_t len_chunk =
read_exhaustive(fd, chunk->data,
sizeof(ByteChunk::data));
2700 if (len_chunk <= 0) {
2704 if (chunk == chunk_first) {
2705 chunk_first =
nullptr;
2710 *chunk_link_p = chunk;
2711 chunk_link_p = &chunk->next;
2714 if (len_chunk !=
sizeof(ByteChunk::data)) {
2717 chunk =
static_cast<ByteChunk *
>(malloc(
sizeof(ByteChunk)));
2721 char *buf =
nullptr;
2723 buf =
static_cast<char *
>(malloc(
len + (nil_terminate ? 1 : 0)));
2732 if (nil_terminate) {
2740 char *buf_stride = buf;
2741 while (chunk_first) {
2743 const size_t len_chunk = std::min(
len,
sizeof(chunk_first->data));
2744 memcpy(buf_stride, chunk_first->data, len_chunk);
2745 buf_stride += len_chunk;
2748 ByteChunk *chunk = chunk_first->next;
2750 chunk_first = chunk;
2769 GHOST_ASSERT((image_size_x % scale) == 0 && (image_size_y % scale) == 0,
2770 "The size must be a multiple of the scale!");
2774 wl_surface_set_buffer_scale(
wl_surface, scale);
2776 if (wl_surface_get_version(
wl_surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION) {
2780 std::numeric_limits<int32_t>::max(),
2781 std::numeric_limits<int32_t>::max());
2788 std::numeric_limits<int32_t>::max(),
2789 std::numeric_limits<int32_t>::max());
2812 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT;
2814 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_E_RESIZE;
2816 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_W_RESIZE;
2818 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CONTEXT_MENU;
2820 return std::nullopt;
2822 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_HELP;
2824 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_WAIT;
2826 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT;
2828 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CROSSHAIR;
2830 return std::nullopt;
2832 return std::nullopt;
2834 return std::nullopt;
2836 return std::nullopt;
2838 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_N_RESIZE;
2840 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_S_RESIZE;
2842 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COL_RESIZE;
2844 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ROW_RESIZE;
2846 return std::nullopt;
2848 return std::nullopt;
2850 return std::nullopt;
2852 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_IN;
2854 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_OUT;
2856 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE;
2858 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRAB;
2860 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRABBING;
2862 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER;
2864 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_SCROLL;
2866 return std::nullopt;
2868 return std::nullopt;
2870 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NOT_ALLOWED;
2872 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NS_RESIZE;
2874 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_EW_RESIZE;
2876 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_N_RESIZE;
2878 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_S_RESIZE;
2880 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_W_RESIZE;
2882 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_E_RESIZE;
2884 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NW_RESIZE;
2886 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NE_RESIZE;
2888 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SE_RESIZE;
2890 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_SW_RESIZE;
2892 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COPY;
2894 return std::nullopt;
2896 return std::nullopt;
2898 return std::nullopt;
2900 return std::nullopt;
2902 return std::nullopt;
2904 return std::nullopt;
2908 return std::nullopt;
2921 scale = std::max(scale, seat->
pointer.buffer_scale);
2941 wp_cursor_shape_device_v1_set_shape(
2950 wl_pointer_set_cursor(
2960 for (zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->
wp.
tablet_tools) {
2962 zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
2964 wp_cursor_shape_device_v1_set_shape(
2968 zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2,
2973#ifdef USE_KDE_TABLET_HIDDEN_CURSOR_HACK
2989 wl_pointer_set_cursor(seat->
wl.
pointer, seat->
pointer.serial,
nullptr, 0, 0);
2990 for (zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->
wp.
tablet_tools) {
2992 zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
2993 zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2, tablet_tool->
serial,
nullptr, 0, 0);
2998 const wl_cursor_image *wl_image,
3023 for (zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->
wp.
tablet_tools) {
3025 zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
3027 zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2,
3050 const bool is_hardware,
3055 const bool use_visible = is_hardware && visible;
3096#define LOG (&LOG_WL_KEYBOARD_DEPRESSED_STATE)
3115 CLOG_WARN(
LOG,
"modifier (%d) has negative keys held (%d)!", index, value);
3167#define LOG (&LOG_WL_RELATIVE_POINTER)
3174 const wl_fixed_t
xy[2],
3180#ifdef USE_GNOME_CONFINE_HACK
3201 zwp_relative_pointer_v1 * ,
3202 const uint32_t utime_hi,
3203 const uint32_t utime_lo,
3204 const wl_fixed_t dx,
3205 const wl_fixed_t dy,
3216 const wl_fixed_t xy_next[2] = {
3240#define LOG (&LOG_WL_DATA_SOURCE)
3259 const char *mime_receive,
3261 const bool nil_terminate,
3265 const bool pipefd_ok = pipe(pipefd) == 0;
3267 wl_data_offer_receive(data_offer->
wl.
id, mime_receive, pipefd[1]);
3271 CLOG_WARN(
LOG,
"error creating pipe: %s", std::strerror(errno));
3282 char *buf =
nullptr;
3285 if (buf ==
nullptr) {
3286 CLOG_WARN(
LOG,
"unable to pipe into buffer: %s", std::strerror(errno));
3297 const char *mime_receive,
3299 const bool nil_terminate,
3303 const bool pipefd_ok = pipe(pipefd) == 0;
3305 zwp_primary_selection_offer_v1_receive(data_offer->
wp.
id, mime_receive, pipefd[1]);
3309 CLOG_WARN(
LOG,
"error creating pipe: %s", std::strerror(errno));
3316 char *buf =
nullptr;
3319 if (buf ==
nullptr) {
3320 CLOG_WARN(
LOG,
"unable to pipe into buffer: %s", std::strerror(errno));
3349 auto write_file_fn = [](
GWL_Seat *seat,
const int fd) {
3354 CLOG_WARN(
LOG,
"error writing to clipboard: %s", std::strerror(errno));
3361 std::thread write_thread(write_file_fn, seat, fd);
3362 write_thread.detach();
3374 wl_data_source_destroy(wl_data_source);
3411 const uint32_t dnd_action)
3413 CLOG_DEBUG(
LOG,
"handle_action (dnd_action=%u)", dnd_action);
3434#define LOG (&LOG_WL_DATA_OFFER)
3438 const char *mime_type)
3443 data_offer->
types.insert(mime_type);
3448 const uint32_t source_actions)
3453 data_offer->
dnd.
source_actions = (
enum wl_data_device_manager_dnd_action)source_actions;
3458 const uint32_t dnd_action)
3463 data_offer->
dnd.
action = (
enum wl_data_device_manager_dnd_action)dnd_action;
3481#define LOG (&LOG_WL_DATA_DEVICE)
3501 data_offer->
wl.
id = id;
3507 const uint32_t serial,
3529 wl_data_offer_destroy(data_offer->
wl.
id);
3538 data_offer->
dnd.
xy[0] =
x;
3539 data_offer->
dnd.
xy[1] =
y;
3541 wl_data_offer_set_actions(
id,
3542 WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
3543 WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE,
3544 WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
3548 wl_data_offer_accept(
id, serial, type);
3582 const uint32_t time,
3621 const char *mime_receive =
"";
3624 if (data_offer->
types.count(type)) {
3625 mime_receive = type;
3632 auto read_drop_data_fn = [](
GWL_Seat *
const seat,
3635 const char *mime_receive) {
3640 size_t data_buf_len = 0;
3642 data_offer, mime_receive,
nullptr, nil_terminate, &data_buf_len);
3644 CLOG_DEBUG(
LOG,
"read_drop_data mime_receive=%s, data_len=%zu", mime_receive, data_buf_len);
3646 wl_data_offer_finish(data_offer->
wl.
id);
3647 wl_data_offer_destroy(data_offer->
wl.
id);
3650 data_offer =
nullptr;
3654 if (data_buf !=
nullptr) {
3656 void *ghost_dnd_data =
nullptr;
3664 flist->
count = int(uris.size());
3665 flist->
strings =
static_cast<uint8_t **
>(malloc(uris.size() *
sizeof(uint8_t *)));
3666 for (
size_t i = 0;
i < uris.size();
i++) {
3667 flist->
strings[
i] =
reinterpret_cast<uint8_t *
>(
3673 ghost_dnd_data = flist;
3677 ghost_dnd_data = (
void *)data_buf;
3699 free(
const_cast<char *
>(data_buf));
3705 std::thread read_thread(
3707 read_thread.detach();
3726 if (
id ==
nullptr) {
3756#define LOG (&LOG_WL_CURSOR_BUFFER)
3763 wl_buffer_destroy(wl_buffer);
3765 if (wl_buffer == cursor->
wl.
buffer) {
3784#define LOG (&LOG_WL_CURSOR_SURFACE)
3795 scale = std::max(scale,
output->scale);
3797 if (scale > 0 && seat_state_pointer->
buffer_scale != scale) {
3807 if (wl_surface_focus) {
3831 seat_state_pointer->
outputs.insert(reg_output);
3847 seat_state_pointer->
outputs.erase(reg_output);
3856 CLOG_DEBUG(
LOG,
"handle_preferred_buffer_scale (factor=%d)", factor);
3859#if defined(WL_SURFACE_PREFERRED_BUFFER_SCALE_SINCE_VERSION) && \
3860 defined(WL_SURFACE_PREFERRED_BUFFER_TRANSFORM_SINCE_VERSION)
3861static void cursor_surface_handle_preferred_buffer_transform(
void * ,
3874#if defined(WL_SURFACE_PREFERRED_BUFFER_SCALE_SINCE_VERSION) && \
3875 defined(WL_SURFACE_PREFERRED_BUFFER_TRANSFORM_SINCE_VERSION)
3877 cursor_surface_handle_preferred_buffer_transform,
3890#define LOG (&LOG_WL_POINTER)
3894 const uint32_t serial,
3896 const wl_fixed_t surface_x,
3897 const wl_fixed_t surface_y)
3912 seat->
pointer.serial = serial;
3913 seat->
pointer.xy[0] = surface_x;
3914 seat->
pointer.xy[1] = surface_y;
3936 static_cast<GWL_Seat *
>(
data)->pointer.
wl.surface_window =
nullptr;
3946 const uint32_t time,
3947 const wl_fixed_t surface_x,
3948 const wl_fixed_t surface_y)
3953 seat->
pointer.xy[0] = surface_x;
3954 seat->
pointer.xy[1] = surface_y;
3964 const uint32_t serial,
3965 const uint32_t time,
3966 const uint32_t button,
3967 const uint32_t
state)
3978 case WL_POINTER_BUTTON_STATE_RELEASED: {
3982 case WL_POINTER_BUTTON_STATE_PRESSED: {
4005 const uint32_t time,
4006 const uint32_t axis,
4007 const wl_fixed_t value)
4056 GHOST_ASSERT(event_ms == 0,
"Scroll events are not expected to have a time!");
4059 for (
int i = 0;
i < 2;
i++) {
4070 if (ps.
axis_source == WL_POINTER_AXIS_SOURCE_WHEEL) {
4078 else if (ps.
axis_source == WL_POINTER_AXIS_SOURCE_FINGER) {
4085 for (
int i = 0;
i < 2;
i++) {
4104 if (ps.
axis_source == WL_POINTER_AXIS_SOURCE_WHEEL) {
4191 const int button_index = button_enum_offset / 2;
4192 const bool button_down = (button_index * 2) == button_enum_offset;
4196 seat->
pointer.buttons.set(ebutton, button_down);
4209 const uint32_t axis_source)
4211 CLOG_DEBUG(
LOG,
"axis_source (axis_source=%u)", axis_source);
4217 const uint32_t time,
4218 const uint32_t axis)
4238 const uint32_t axis,
4243 CLOG_DEBUG(
LOG,
"axis_discrete (axis=%u, discrete=%d)", axis, discrete);
4255 const uint32_t axis,
4259 CLOG_DEBUG(
LOG,
"axis_value120 (axis=%u, value120=%d)", axis, value120);
4269#ifdef WL_POINTER_AXIS_RELATIVE_DIRECTION_ENUM
4270static void pointer_handle_axis_relative_direction(
void *
data,
4272 const uint32_t axis,
4273 const uint32_t direction)
4276 CLOG_DEBUG(
LOG,
"axis_relative_direction (axis=%u, direction=%u)", axis, direction);
4283 WL_POINTER_AXIS_RELATIVE_DIRECTION_INVERTED);
4298#ifdef WL_POINTER_AXIS_RELATIVE_DIRECTION_ENUM
4299 pointer_handle_axis_relative_direction,
4311#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
4312static CLG_LogRef LOG_WL_POINTER_GESTURE_HOLD = {
"ghost.wl.handle.pointer_gesture.hold"};
4313# define LOG (&LOG_WL_POINTER_GESTURE_HOLD)
4315static void gesture_hold_handle_begin(
4317 zwp_pointer_gesture_hold_v1 * ,
4321 const uint32_t fingers)
4326static void gesture_hold_handle_end(
void * ,
4327 zwp_pointer_gesture_hold_v1 * ,
4335static const zwp_pointer_gesture_hold_v1_listener gesture_hold_listener = {
4336 gesture_hold_handle_begin,
4337 gesture_hold_handle_end,
4349#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE
4350static CLG_LogRef LOG_WL_POINTER_GESTURE_PINCH = {
"ghost.wl.handle.pointer_gesture.pinch"};
4351# define LOG (&LOG_WL_POINTER_GESTURE_PINCH)
4353static void gesture_pinch_handle_begin(
void *
data,
4354 zwp_pointer_gesture_pinch_v1 * ,
4356 const uint32_t time,
4358 const uint32_t fingers)
4410static void gesture_pinch_handle_update(
void *
data,
4411 zwp_pointer_gesture_pinch_v1 * ,
4412 const uint32_t time,
4413 const wl_fixed_t dx,
4414 const wl_fixed_t dy,
4415 const wl_fixed_t scale,
4416 const wl_fixed_t rotation)
4422 "update (dx=%.3f, dy=%.3f, scale=%.3f, rotation=%.3f)",
4423 wl_fixed_to_double(dx),
4424 wl_fixed_to_double(dy),
4425 wl_fixed_to_double(scale),
4426 wl_fixed_to_double(rotation));
4446 if (scale_as_delta_px) {
4457 if (rotation_as_delta_px) {
4463 rotation_as_delta_px,
4470static void gesture_pinch_handle_end(
void *
data,
4471 zwp_pointer_gesture_pinch_v1 * ,
4473 const uint32_t time,
4482static const zwp_pointer_gesture_pinch_v1_listener gesture_pinch_listener = {
4483 gesture_pinch_handle_begin,
4484 gesture_pinch_handle_update,
4485 gesture_pinch_handle_end,
4502#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE
4503static CLG_LogRef LOG_WL_POINTER_GESTURE_SWIPE = {
"ghost.wl.handle.pointer_gesture.swipe"};
4504# define LOG (&LOG_WL_POINTER_GESTURE_SWIPE)
4506static void gesture_swipe_handle_begin(
4508 zwp_pointer_gesture_swipe_v1 * ,
4517static void gesture_swipe_handle_update(
4519 zwp_pointer_gesture_swipe_v1 * ,
4524 CLOG_DEBUG(
LOG,
"update (dx=%.3f, dy=%.3f)", wl_fixed_to_double(dx), wl_fixed_to_double(dy));
4527static void gesture_swipe_handle_end(
4529 zwp_pointer_gesture_swipe_v1 * ,
4537static const zwp_pointer_gesture_swipe_v1_listener gesture_swipe_listener = {
4538 gesture_swipe_handle_begin,
4539 gesture_swipe_handle_update,
4540 gesture_swipe_handle_end,
4561#define LOG (&LOG_WL_TOUCH)
4565 const uint32_t serial,
4566 const uint32_t time,
4594 seat->
touch.serial = serial;
4595 seat->
touch.wl.surface_window = surface;
4617 const uint32_t time,
4636 const uint32_t time,
4668 int touch_events_num = 0;
4711 seat->
touch.wl.surface_window =
nullptr;
4717 if (
UNLIKELY(touch_events_num > 1)) {
4718 std::sort(touch_events,
4719 touch_events + touch_events_num,
4725 for (
int i = 0;
i < touch_events_num;
i++) {
4773#define LOG (&LOG_WL_TABLET_TOOL)
4776 zwp_tablet_tool_v2 * ,
4777 const uint32_t tool_type)
4787 zwp_tablet_tool_v2 * ,
4795 zwp_tablet_tool_v2 * ,
4803 zwp_tablet_tool_v2 * ,
4804 const uint32_t capability)
4807 "capability (tilt=%d, distance=%d, rotation=%d, slider=%d, wheel=%d)",
4808 (capability & ZWP_TABLET_TOOL_V2_CAPABILITY_TILT) != 0,
4809 (capability & ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE) != 0,
4810 (capability & ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION) != 0,
4811 (capability & ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER) != 0,
4812 (capability & ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL) != 0);
4830 wp_cursor_shape_device_v1_destroy(tablet_tool->
shape.
device);
4837 zwp_tablet_tool_v2 * ,
4838 const uint32_t serial,
4850 tablet_tool->
serial = serial;
4873 zwp_tablet_tool_v2 * )
4884 zwp_tablet_tool_v2 * ,
4885 const uint32_t serial)
4907 zwp_tablet_tool_v2 * ,
4915 tablet_tool->
xy[0] =
x;
4916 tablet_tool->
xy[1] =
y;
4917 tablet_tool->
has_xy =
true;
4923 zwp_tablet_tool_v2 * ,
4924 const uint32_t pressure)
4926 const float pressure_unit =
float(pressure) / 65535;
4937 zwp_tablet_tool_v2 * ,
4944 zwp_tablet_tool_v2 * ,
4945 const wl_fixed_t tilt_x,
4946 const wl_fixed_t tilt_y)
4950 const float tilt_unit[2] = {
4951 float(wl_fixed_to_double(tilt_x) / 90.0f),
4952 float(wl_fixed_to_double(tilt_y) / 90.0f),
4957 td.
Xtilt = std::clamp(tilt_unit[0], -1.0f, 1.0f);
4958 td.
Ytilt = std::clamp(tilt_unit[1], -1.0f, 1.0f);
4964 zwp_tablet_tool_v2 * ,
4971 zwp_tablet_tool_v2 * ,
4977 zwp_tablet_tool_v2 * ,
4995 zwp_tablet_tool_v2 * ,
4996 const uint32_t serial,
4997 const uint32_t button,
4998 const uint32_t
state)
5005 bool is_press =
false;
5007 case WL_POINTER_BUTTON_STATE_RELEASED: {
5011 case WL_POINTER_BUTTON_STATE_PRESSED: {
5043 zwp_tablet_tool_v2 * ,
5044 const uint32_t time)
5055 bool has_motion =
false;
5069 if (tablet_tool->
has_xy ==
false) {
5096 const int button_index = button_enum_offset / 2;
5097 const bool button_down = (button_index * 2) == button_enum_offset;
5160#define LOG (&LOG_WL_TABLET_SEAT)
5163 zwp_tablet_seat_v2 * ,
5170 zwp_tablet_seat_v2 * ,
5171 zwp_tablet_tool_v2 *
id)
5177 tablet_tool->
seat = seat;
5183 wl_surface_add_listener(
5192 zwp_tablet_seat_v2 * ,
5193 zwp_tablet_pad_v2 *
id)
5213#define LOG (&LOG_WL_KEYBOARD)
5219 const uint32_t
size)
5223 if ((!
data) || (
format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)) {
5229 char *map_str =
static_cast<char *
>(mmap(
nullptr,
size, PROT_READ, MAP_PRIVATE, fd, 0));
5230 if (map_str == MAP_FAILED) {
5232 CLOG_DEBUG(
LOG,
"keymap mmap failed: %s", std::strerror(errno));
5236 xkb_keymap *keymap = xkb_keymap_new_from_string(
5237 seat->
xkb.
context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
5238 munmap(map_str,
size);
5260 XKB_COMPOSE_STATE_NO_FLAGS);
5265 seat->
xkb.
state = xkb_state_new(keymap);
5293#ifdef USE_NON_LATIN_KB_WORKAROUND
5302 if (!(sym_test >= XKB_KEY_0 && sym_test <= XKB_KEY_9)) {
5312 xkb_keymap_unref(keymap);
5322 const uint32_t serial,
5349 uint32_t key = std::numeric_limits<uint32_t>::max();
5350 xkb_keysym_t sym = 0;
5357 const xkb_keysym_t sym = xkb_state_key_get_one_sym(seat->
xkb.
state, key_code);
5363 if (xkb_keymap_key_repeats(xkb_state_get_keymap(seat->
xkb.
state), key_code)) {
5373 if ((repeat.key != std::numeric_limits<uint32_t>::max()) && (seat->
key_repeat.
rate > 0)) {
5376#ifdef USE_EVENT_BACKGROUND_THREAD
5384 const xkb_keycode_t key_code = repeat.key +
EVDEV_OFFSET;
5388 key_repeat_payload->
seat = seat;
5389 key_repeat_payload->
key_code = key_code;
5416 seat->
keyboard.wl.surface_window =
nullptr;
5419#ifdef USE_EVENT_BACKGROUND_THREAD
5434 xkb_state *xkb_state_empty,
5435 xkb_state *xkb_state_empty_with_numlock,
5436 xkb_state *xkb_state_empty_with_shift,
5437 const bool xkb_use_non_latin_workaround,
5438 const xkb_keycode_t key)
5441 xkb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state_empty, key);
5451 if (sym >= XKB_KEY_KP_Home && sym <= XKB_KEY_KP_Delete) {
5452 if (xkb_state_empty_with_numlock) {
5453 const xkb_keysym_t sym_test = xkb_state_key_get_one_sym(xkb_state_empty_with_numlock, key);
5454 if (sym_test != XKB_KEY_NoSymbol) {
5460#ifdef USE_NON_LATIN_KB_WORKAROUND
5462 if (xkb_state_empty_with_shift && xkb_use_non_latin_workaround) {
5463 const xkb_keysym_t sym_test = xkb_state_key_get_one_sym(xkb_state_empty_with_shift, key);
5464 if (sym_test != XKB_KEY_NoSymbol) {
5466 GHOST_ASSERT(sym_test >= XKB_KEY_0 && sym_test <= XKB_KEY_9,
"Unexpected key");
5472 (void)xkb_state_empty_with_shift;
5473 (void)xkb_use_non_latin_workaround;
5481 xkb_compose_state *compose_state,
5483 const xkb_keycode_t key,
5486 const xkb_keysym_t sym = xkb_state_key_get_one_sym(
state, key);
5487 const xkb_compose_feed_result
result = xkb_compose_state_feed(compose_state, sym);
5488 bool handled =
false;
5490 if (
result == XKB_COMPOSE_FEED_ACCEPTED) {
5491 switch (xkb_compose_state_get_status(compose_state)) {
5492 case XKB_COMPOSE_NOTHING: {
5495 case XKB_COMPOSE_COMPOSING: {
5496 r_utf8_buf[0] =
'\0';
5500 case XKB_COMPOSE_COMPOSED: {
5502 const int utf8_buf_compose_len = xkb_compose_state_get_utf8(
5503 compose_state, utf8_buf_compose,
sizeof(utf8_buf_compose));
5504 if (utf8_buf_compose_len > 0) {
5516 CLOG_WARN(
LOG,
"key (compose_size=%d) exceeds the maximum size", utf8_buf_compose_len);
5523 case XKB_COMPOSE_CANCELLED: {
5529 r_utf8_buf[0] =
'\0';
5568 const uint32_t serial,
5569 const uint32_t time,
5571 const uint32_t
state)
5588 if (sym == XKB_KEY_NoSymbol) {
5589 CLOG_DEBUG(
LOG,
"key (code=%d, state=%u, no symbol, skipped)",
int(key_code),
state);
5595 bool is_repeat =
false;
5597 case WL_KEYBOARD_KEY_STATE_RELEASED: {
5601#ifdef WL_KEYBOARD_KEY_STATE_REPEATED_SINCE_VERSION
5602 case WL_KEYBOARD_KEY_STATE_REPEATED: {
5608 case WL_KEYBOARD_KEY_STATE_PRESSED: {
5614#ifdef USE_EVENT_BACKGROUND_THREAD
5623 enum { NOP = 1, RESET, CANCEL } timer_action = NOP;
5629 timer_action = CANCEL;
5631 else if (key_code == key_repeat_payload->
key_code) {
5633 timer_action = CANCEL;
5635 else if (xkb_keymap_key_repeats(xkb_state_get_keymap(seat->
xkb.
state), key_code)) {
5638 timer_action = CANCEL;
5646 timer_action = RESET;
5650 switch (timer_action) {
5653 key_repeat_payload =
nullptr;
5662 delete key_repeat_payload;
5663 key_repeat_payload =
nullptr;
5682 xkb_state_key_get_utf8(seat->
xkb.
state, key_code, utf8_buf,
sizeof(utf8_buf));
5693 new GHOST_EventKey(event_ms, etype, win, gkey, is_repeat, utf8_buf));
5697 if (key_repeat_payload ==
nullptr) {
5700 xkb_keymap_key_repeats(xkb_state_get_keymap(seat->
xkb.
state), key_code))
5703 key_repeat_payload->
seat = seat;
5704 key_repeat_payload->
key_code = key_code;
5709 if (key_repeat_payload) {
5716 const uint32_t serial,
5717 const uint32_t mods_depressed,
5718 const uint32_t mods_latched,
5719 const uint32_t mods_locked,
5720 const uint32_t group)
5723 "modifiers (depressed=%u, latched=%u, locked=%u, group=%u)",
5730 xkb_state_update_mask(seat->
xkb.
state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
5742#ifdef USE_EVENT_BACKGROUND_THREAD
5765#ifdef USE_EVENT_BACKGROUND_THREAD
5799#define LOG (&LOG_WL_PRIMARY_SELECTION_OFFER)
5802 zwp_primary_selection_offer_v1 *
id,
5807 if (data_offer->
wp.
id !=
id) {
5808 CLOG_DEBUG(
LOG,
"offer: %p: offer for unknown selection %p of %s (skipped)",
data,
id, type);
5812 data_offer->
types.insert(std::string(type));
5828#define LOG (&LOG_WL_PRIMARY_SELECTION_DEVICE)
5832 zwp_primary_selection_device_v1 * ,
5833 zwp_primary_selection_offer_v1 *
id)
5838 data_offer->
wp.
id = id;
5844 zwp_primary_selection_device_v1 * ,
5845 zwp_primary_selection_offer_v1 *
id)
5856 if (
id ==
nullptr) {
5863 zwp_primary_selection_offer_v1_get_user_data(
id));
5881#define LOG (&LOG_WL_PRIMARY_SELECTION_SOURCE)
5884 zwp_primary_selection_source_v1 * ,
5897 CLOG_WARN(
LOG,
"error writing to primary clipboard: %s", std::strerror(errno));
5904 std::thread write_thread(write_file_fn, primary, fd);
5905 write_thread.detach();
5932#ifdef WITH_INPUT_IME
5936 GHOST_TEventImeData event_ime_data;
5947 GHOST_IWindow *window,
5948 const GHOST_TEventImeData *customdata)
5949 : GHOST_Event(msec, type, window)
5953 this->event_ime_data = *customdata;
5954 this->data_ = &this->event_ime_data;
5958static CLG_LogRef LOG_WL_TEXT_INPUT = {
"ghost.wl.handle.text_input"};
5959# define LOG (&LOG_WL_TEXT_INPUT)
5961static void text_input_handle_enter(
void *
data,
5962 zwp_text_input_v3 * ,
5971 seat->ime.surface_window = surface;
5974 if (seat->ime.is_enabled) {
5975 zwp_text_input_v3_enable(seat->
wp.text_input);
5976 zwp_text_input_v3_commit(seat->
wp.text_input);
5980static void text_input_handle_leave(
void *
data,
5981 zwp_text_input_v3 * ,
5990 if (seat->ime.surface_window == surface) {
5991 seat->ime.surface_window =
nullptr;
5994 zwp_text_input_v3_disable(seat->
wp.text_input);
5995 zwp_text_input_v3_commit(seat->
wp.text_input);
5998static void text_input_handle_preedit_string(
void *
data,
5999 zwp_text_input_v3 * ,
6005 "preedit_string (text=\"%s\", cursor_begin=%d, cursor_end=%d)",
6006 text ? text :
"<null>",
6011 if (seat->ime.has_preedit ==
false) {
6013 gwl_seat_ime_full_reset(seat);
6016 seat->ime.composite_is_null = (text ==
nullptr);
6017 if (!seat->ime.composite_is_null) {
6018 seat->ime.event_ime_data.composite = text;
6020 seat->ime.event_ime_data.cursor_position = cursor_begin;
6021 seat->ime.event_ime_data.target_start = cursor_begin;
6022 seat->ime.event_ime_data.target_end = cursor_end;
6025 seat->ime.has_preedit_string_callback =
true;
6028static void text_input_handle_commit_string(
void *
data,
6029 zwp_text_input_v3 * ,
6032 CLOG_DEBUG(
LOG,
"commit_string (text=\"%s\")", text ? text :
"<null>");
6035 seat->ime.result_is_null = (text ==
nullptr);
6036 seat->ime.event_ime_data.result = text ? text :
"";
6037 seat->ime.event_ime_data.cursor_position = seat->ime.event_ime_data.result.size();
6039 seat->ime.has_commit_string_callback =
true;
6042static void text_input_handle_delete_surrounding_text(
void * ,
6043 zwp_text_input_v3 * ,
6044 const uint32_t before_length,
6045 const uint32_t after_length)
6048 "delete_surrounding_text (before_length=%u, after_length=%u)",
6056static void text_input_handle_done(
void *
data,
6057 zwp_text_input_v3 * ,
6069 if (seat->ime.has_commit_string_callback) {
6070 if (seat->ime.has_preedit) {
6071 const bool is_end = seat->ime.composite_is_null;
6073 seat->ime.has_preedit =
false;
6096 if (seat->ime.has_preedit ==
false) {
6097 gwl_seat_ime_preedit_reset(seat);
6100 else if (seat->ime.has_preedit_string_callback) {
6101 const bool is_end = seat->ime.composite_is_null;
6104 seat->ime.has_preedit =
false;
6109 const bool is_start = seat->ime.has_preedit ==
false;
6111 seat->ime.has_preedit =
true;
6116 &seat->ime.event_ime_data));
6120 seat->ime.has_preedit_string_callback =
false;
6121 seat->ime.has_commit_string_callback =
false;
6124static zwp_text_input_v3_listener text_input_listener = {
6125 text_input_handle_enter,
6126 text_input_handle_leave,
6127 text_input_handle_preedit_string,
6128 text_input_handle_commit_string,
6129 text_input_handle_delete_surrounding_text,
6130 text_input_handle_done,
6144#define LOG (&LOG_WL_SEAT)
6149 if (pointer_gestures ==
nullptr) {
6154#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
6155 if (seat->
wp.pointer_gesture_hold) {
6160#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE
6166#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE
6167 if (seat->
wp.pointer_gesture_swipe) {
6176 if (found ==
false) {
6189 if (pointer_gestures ==
nullptr) {
6193 const uint pointer_gestures_version = zwp_pointer_gestures_v1_get_version(pointer_gestures);
6194#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
6195 if (pointer_gestures_version >= ZWP_POINTER_GESTURES_V1_GET_HOLD_GESTURE_SINCE_VERSION)
6197 zwp_pointer_gesture_hold_v1 *gesture = zwp_pointer_gestures_v1_get_hold_gesture(
6199 zwp_pointer_gesture_hold_v1_set_user_data(gesture, seat);
6200 zwp_pointer_gesture_hold_v1_add_listener(gesture, &gesture_hold_listener, seat);
6201 seat->
wp.pointer_gesture_hold = gesture;
6204#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE
6206 zwp_pointer_gesture_pinch_v1 *gesture = zwp_pointer_gestures_v1_get_pinch_gesture(
6208 zwp_pointer_gesture_pinch_v1_set_user_data(gesture, seat);
6209 zwp_pointer_gesture_pinch_v1_add_listener(gesture, &gesture_pinch_listener, seat);
6213#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE
6215 zwp_pointer_gesture_swipe_v1 *gesture = zwp_pointer_gestures_v1_get_swipe_gesture(
6217 zwp_pointer_gesture_swipe_v1_set_user_data(gesture, seat);
6218 zwp_pointer_gesture_swipe_v1_add_listener(gesture, &gesture_swipe_listener, seat);
6219 seat->
wp.pointer_gesture_swipe = gesture;
6233 if (pointer_gestures ==
nullptr) {
6236#ifdef ZWP_POINTER_GESTURE_HOLD_V1_INTERFACE
6238 zwp_pointer_gesture_hold_v1 **gesture_p = &seat->
wp.pointer_gesture_hold;
6240 zwp_pointer_gesture_hold_v1_destroy(*gesture_p);
6241 *gesture_p =
nullptr;
6245#ifdef ZWP_POINTER_GESTURE_PINCH_V1_INTERFACE
6249 zwp_pointer_gesture_pinch_v1_destroy(*gesture_p);
6250 *gesture_p =
nullptr;
6254#ifdef ZWP_POINTER_GESTURE_SWIPE_V1_INTERFACE
6256 zwp_pointer_gesture_swipe_v1 **gesture_p = &seat->
wp.pointer_gesture_swipe;
6258 zwp_pointer_gesture_swipe_v1_destroy(*gesture_p);
6259 *gesture_p =
nullptr;
6285 env = getenv(
"XCURSOR_SIZE");
6288 if (env && (*env !=
'\0')) {
6289 char *env_end =
nullptr;
6292 const long value = strtol(env, &env_end, 10);
6293 if ((*env_end ==
'\0') && (value > 0)) {
6342#ifdef USE_EVENT_BACKGROUND_THREAD
6359 wl_touch_set_user_data(seat->
wl.
touch, seat);
6368 wl_touch_destroy(seat->
wl.
touch);
6374 [[maybe_unused]] wl_seat *wl_seat,
6375 const uint32_t capabilities)
6378 "capabilities (pointer=%d, keyboard=%d, touch=%d)",
6379 (capabilities & WL_SEAT_CAPABILITY_POINTER) != 0,
6380 (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) != 0,
6381 (capabilities & WL_SEAT_CAPABILITY_TOUCH) != 0);
6386 if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
6393 if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
6400 if (capabilities & WL_SEAT_CAPABILITY_TOUCH) {
6428#define LOG (&LOG_WL_XDG_OUTPUT)
6438 output->position_logical[0] =
x;
6439 output->position_logical[1] =
y;
6440 output->has_position_logical =
true;
6451 if (
output->size_native[0] != 0 &&
output->size_native[1] != 0) {
6459 int width_native =
output->size_native[(
output->transform & WL_OUTPUT_TRANSFORM_90) ? 1 : 0];
6461 GHOST_PRINT(
"xdg_output scale did not match, overriding with wl_output scale\n");
6463#ifdef USE_GNOME_CONFINE_HACK
6473 output->size_logical[0] = width;
6474 output->size_logical[1] = height;
6475 output->has_size_logical =
true;
6484 if (zxdg_output_v1_get_version(
output->xdg.output) < 3) {
6498 const char *description)
6500 CLOG_DEBUG(
LOG,
"description (description=\"%s\")", description);
6520#define LOG (&LOG_WL_OUTPUT)
6527 const int32_t physical_height,
6534 "geometry (make=\"%s\", model=\"%s\", transform=%d, size=[%d, %d])",
6544 output->model = std::string(model);
6545 output->size_mm[0] = physical_width;
6546 output->size_mm[1] = physical_height;
6551 const uint32_t flags,
6556 if ((flags & WL_OUTPUT_MODE_CURRENT) == 0) {
6560 CLOG_DEBUG(
LOG,
"mode (size=[%d, %d], flags=%u)", width, height, flags);
6563 output->size_native[0] = width;
6564 output->size_native[1] = height;
6581 if (
output->transform & WL_OUTPUT_TRANSFORM_90) {
6582 std::swap(size_native[0], size_native[1]);
6586 if (
output->has_size_logical) {
6592 "Screen size values were not set when they were expected to be.");
6595 output->has_scale_fractional =
true;
6614 const char *description)
6638#define LOG (&LOG_WL_XDG_WM_BASE)
6643 xdg_wm_base_pong(xdg_wm_base, serial);
6658#ifdef WITH_GHOST_WAYLAND_LIBDECOR
6660static CLG_LogRef LOG_WL_LIBDECOR = {
"ghost.wl.handle.libdecor"};
6661# define LOG (&LOG_WL_LIBDECOR)
6663static void decor_handle_error(libdecor * ,
6664 enum libdecor_error
error,
6665 const char *message)
6671 GHOST_PRINT(
"decoration error (" <<
error <<
"): " << message << std::endl);
6675static libdecor_interface libdecor_interface = {
6690#define LOG (&LOG_WL_REGISTRY)
6700 wl_registry_bind(display->
wl.
registry,
params.name, &wl_compositor_interface, version));
6708 wl_compositor_destroy(*value_p);
6720 decor.
shell =
static_cast<xdg_wm_base *
>(
6721 wl_registry_bind(display->
wl.
registry,
params.name, &xdg_wm_base_interface, version));
6731 xdg_wm_base **value_p = &decor.
shell;
6733 xdg_wm_base_destroy(*value_p);
6746 decor.
manager =
static_cast<zxdg_decoration_manager_v1 *
>(wl_registry_bind(
6747 display->
wl.
registry,
params.name, &zxdg_decoration_manager_v1_interface, version));
6756 zxdg_decoration_manager_v1 **value_p = &decor.
manager;
6758 zxdg_decoration_manager_v1_destroy(*value_p);
6773 display->
xdg.
output_manager =
static_cast<zxdg_output_manager_v1 *
>(wl_registry_bind(
6774 display->
wl.
registry,
params.name, &zxdg_output_manager_v1_interface, version));
6782 zxdg_output_manager_v1_destroy(*value_p);
6794 output->wl.output =
static_cast<wl_output *
>(
6795 wl_registry_bind(display->
wl.
registry,
params.name, &wl_output_interface, version));
6808 if (
output->xdg.output ==
nullptr) {
6815 output->xdg.output =
nullptr;
6834 "mis-behaving compositor failed to call \"surface_listener.leave\" "
6835 "window scale may be invalid!");
6839 if (
output->xdg.output) {
6840 zxdg_output_v1_destroy(
output->xdg.output);
6842 wl_output_destroy(
output->wl.output);
6843 std::vector<GWL_Output *>::iterator iter = std::find(
6845 const int index = (iter != display->
outputs.cend()) ?
6846 std::distance(display->
outputs.begin(), iter) :
6862 seat->
xkb.
context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
6869 seat->
wl.
seat =
static_cast<wl_seat *
>(
6870 wl_registry_bind(display->
wl.
registry,
params.name, &wl_seat_interface, version));
6871 display->
seats.push_back(seat);
6885 seat->
wl.
data_device = wl_data_device_manager_get_data_device(
6919#ifdef WITH_INPUT_IME
6920 if (display->
wp.text_input_manager) {
6921 if (seat->
wp.text_input ==
nullptr) {
6922 seat->
wp.text_input = zwp_text_input_manager_v3_get_text_input(
6923 display->
wp.text_input_manager, seat->
wl.
seat);
6924 zwp_text_input_v3_set_user_data(seat->
wp.text_input, seat);
6925 zwp_text_input_v3_add_listener(seat->
wp.text_input, &text_input_listener, seat);
6929 seat->
wp.text_input =
nullptr;
6982#ifdef WITH_INPUT_IME
6983 if (seat->
wp.text_input) {
6984 zwp_text_input_v3_destroy(seat->
wp.text_input);
7031 wl_seat_destroy(seat->
wl.
seat);
7033 std::vector<GWL_Seat *>::iterator iter = std::find(
7034 display->
seats.begin(), display->
seats.end(), seat);
7035 const int index = (iter != display->
seats.cend()) ? std::distance(display->
seats.begin(), iter) :
7043 display->
seats.erase(display->
seats.begin() + index);
7054 display->
wl.
shm =
static_cast<wl_shm *
>(
7055 wl_registry_bind(display->
wl.
registry,
params.name, &wl_shm_interface, version));
7062 wl_shm **value_p = &display->
wl.
shm;
7063 wl_shm_destroy(*value_p);
7075 display->
wl.
registry,
params.name, &wl_data_device_manager_interface, version));
7083 wl_data_device_manager_destroy(*value_p);
7094 display->
wp.
tablet_manager =
static_cast<zwp_tablet_manager_v2 *
>(wl_registry_bind(
7095 display->
wl.
registry,
params.name, &zwp_tablet_manager_v2_interface, version));
7103 zwp_tablet_manager_v2_destroy(*value_p);
7116 display->
wl.
registry,
params.name, &zwp_relative_pointer_manager_v1_interface, version));
7124 zwp_relative_pointer_manager_v1_destroy(*value_p);
7136 display->
wl.
registry,
params.name, &zwp_pointer_constraints_v1_interface, version));
7144 zwp_pointer_constraints_v1_destroy(*value_p);
7158 &zwp_pointer_gestures_v1_interface,
7159 std::min(
params.version, version)));
7167 zwp_pointer_gestures_v1_destroy(*value_p);
7179 wl_registry_bind(display->
wl.
registry,
params.name, &xdg_activation_v1_interface, version));
7187 xdg_activation_v1_destroy(*value_p);
7200 display->
wl.
registry,
params.name, &wp_fractional_scale_manager_v1_interface, version));
7208 wp_fractional_scale_manager_v1_destroy(*value_p);
7220 wl_registry_bind(display->
wl.
registry,
params.name, &wp_viewporter_interface, version));
7228 wp_viewporter_destroy(*value_p);
7240 static_cast<zwp_primary_selection_device_manager_v1 *
>(
7243 &zwp_primary_selection_device_manager_v1_interface,
7251 zwp_primary_selection_device_manager_v1 **value_p =
7253 zwp_primary_selection_device_manager_v1_destroy(*value_p);
7257#ifdef WITH_INPUT_IME
7261static void gwl_registry_wp_text_input_manager_add(
GWL_Display *display,
7266 display->
wp.text_input_manager =
static_cast<zwp_text_input_manager_v3 *
>(wl_registry_bind(
7267 display->
wl.
registry,
params.name, &zwp_text_input_manager_v3_interface, version));
7270static void gwl_registry_wp_text_input_manager_remove(
GWL_Display *display,
7274 zwp_text_input_manager_v3 **value_p = &display->
wp.text_input_manager;
7275 zwp_text_input_manager_v3_destroy(*value_p);
7289 display->
wl.
registry,
params.name, &wp_cursor_shape_manager_v1_interface, version));
7297 wp_cursor_shape_manager_v1_destroy(*value_p);
7314 &wl_compositor_interface.name,
7320 &wl_shm_interface.name,
7326 &xdg_wm_base_interface.name,
7333 &zxdg_decoration_manager_v1_interface.name,
7339 &zxdg_output_manager_v1_interface.name,
7345 &wl_data_device_manager_interface.name,
7351 &zwp_primary_selection_device_manager_v1_interface.name,
7357 &zwp_tablet_manager_v2_interface.name,
7363 &zwp_relative_pointer_manager_v1_interface.name,
7368#ifdef WITH_INPUT_IME
7370 &zwp_text_input_manager_v3_interface.name,
7371 gwl_registry_wp_text_input_manager_add,
7373 gwl_registry_wp_text_input_manager_remove,
7377 &wp_cursor_shape_manager_v1_interface.name,
7384 &zwp_pointer_constraints_v1_interface.name,
7390 &zwp_pointer_gestures_v1_interface.name,
7396 &xdg_activation_v1_interface.name,
7402 &wp_fractional_scale_manager_v1_interface.name,
7408 &wp_viewporter_interface.name,
7415 &wl_output_interface.name,
7424 &wl_seat_interface.name,
7457 "Index out of range");
7462 [[maybe_unused]] wl_registry *wl_registry,
7463 const uint32_t
name,
7465 const uint32_t version)
7474 if (interface_slot != -1) {
7481 params.interface_slot = interface_slot;
7482 params.version = version;
7490 "add %s(interface=%s, version=%u, name=%u)",
7491 (interface_slot != -1) ? (added ?
"" :
"(found but not added)") :
"(skipped), ",
7515 [[maybe_unused]] wl_registry *wl_registry,
7516 const uint32_t
name)
7521 int interface_slot = 0;
7525 "remove (name=%u, interface=%s)",
7550#ifdef USE_EVENT_BACKGROUND_THREAD
7619 display_->system =
this;
7620 display_->background = background;
7621 display_->use_window_frame = use_window_frame;
7626 if (!display_->wl.display) {
7627 display_destroy_and_free_all();
7628 throw std::runtime_error(
"unable to connect to display!");
7636 display_->registry_skip_update_all =
true;
7637 wl_registry *registry = wl_display_get_registry(display_->wl.display);
7638 display_->wl.registry = registry;
7648 display_->registry_skip_update_all =
false;
7651#ifdef WITH_GHOST_WAYLAND_LIBDECOR
7652 bool libdecor_required =
false;
7653 if (use_window_frame) {
7654 const char *xdg_current_desktop = [] {
7656 const char *key =
"ORIGINAL_XDG_CURRENT_DESKTOP";
7657 const char *value = getenv(key);
7658 return value ? value : getenv(key + 9);
7661 if (xdg_current_desktop) {
7665 if (string_elem_split_by_delim(xdg_current_desktop,
':',
"GNOME")) {
7666 libdecor_required =
true;
7671 if (libdecor_required) {
7677 libdecor_required =
false;
7679# ifdef WITH_GHOST_X11
7680 else if (!has_libdecor && !ghost_wayland_is_x11_available()) {
7683 libdecor_required =
false;
7688 if (libdecor_required) {
7690 display_->xdg_decor =
nullptr;
7692 if (!has_libdecor) {
7693# ifdef WITH_GHOST_X11
7696 "WAYLAND found but libdecor was not, install libdecor for Wayland support, "
7697 "falling back to X11\n");
7699 display_destroy_and_free_all();
7700 throw std::runtime_error(
"unable to find libdecor!");
7704 use_libdecor =
false;
7708#ifdef WITH_GHOST_WAYLAND_LIBDECOR
7710 display_->libdecor =
new GWL_LibDecor_System;
7711 GWL_LibDecor_System &decor = *display_->libdecor;
7712 decor.context =
libdecor_new(display_->wl.display, &libdecor_interface);
7713 if (!decor.context) {
7714 display_destroy_and_free_all();
7715 throw std::runtime_error(
"unable to create window decorations!");
7723 display_destroy_and_free_all();
7724 throw std::runtime_error(
"unable to access xdg_shell!");
7734#ifdef USE_EVENT_BACKGROUND_THREAD
7738 GHOST_ASSERT(display_->events_pthread_is_active ==
false,
"Expected to be false");
7749void GHOST_SystemWayland::display_destroy_and_free_all()
7753#ifdef USE_EVENT_BACKGROUND_THREAD
7761 display_destroy_and_free_all();
7769#ifdef WITH_INPUT_NDOF
7782 bool any_processed =
false;
7784#ifdef USE_EVENT_BACKGROUND_THREAD
7793 if (!display_->background) {
7794 std::lock_guard
lock{display_->events_pending_mutex};
7795 for (
const GHOST_IEvent *event : display_->events_pending) {
7814 display_->events_pending.clear();
7819 display_->events_pending.shrink_to_fit();
7827#ifdef USE_EVENT_BACKGROUND_THREAD
7829 std::lock_guard lock_timer_guard{*display_->system->timer_mutex};
7831 any_processed =
true;
7836 any_processed =
true;
7840#ifdef WITH_INPUT_NDOF
7844 waitForEvent =
false;
7845 any_processed =
true;
7850#ifdef USE_EVENT_BACKGROUND_THREAD
7858#ifdef USE_EVENT_BACKGROUND_THREAD
7875 any_processed =
true;
7878 return any_processed;
7888#ifdef USE_EVENT_BACKGROUND_THREAD
7913 const bool is_keyboard_active = seat->
keyboard.wl.surface_window !=
nullptr;
7914 const xkb_mod_mask_t
state = is_keyboard_active ?
7915 xkb_state_serialize_mods(seat->
xkb.
state,
7916 XKB_STATE_MODS_DEPRESSED) :
7935 bool val_l = depressed_l > 0;
7936 bool val_r = depressed_r > 0;
7938 if (is_keyboard_active) {
7945 "modifier (%s) state is inconsistent (GHOST held keys do not match XKB)",
7956 "modifier (%s) state is inconsistent (GHOST released keys do not match XKB)",
7975#ifdef USE_EVENT_BACKGROUND_THREAD
7984 if (!seat_state_pointer) {
7988 buttons = seat_state_pointer->
buttons;
7997 const std::unordered_set<std::string> &data_offer_types)
8000 for (
size_t i = 0;
i <
ARRAY_SIZE(ghost_supported_types);
i++) {
8001 if (data_offer_types.count(ghost_supported_types[
i])) {
8002 return ghost_supported_types[
i];
8009 const bool nil_terminate,
8010 const char *mime_receive_override,
8021 bool mutex_locked =
true;
8022 char *
data =
nullptr;
8025 if (data_offer !=
nullptr) {
8026 const char *mime_receive = mime_receive_override ?
8027 mime_receive_override :
8030 data_offer->
types.count(mime_receive_override) != 0,
8031 "Mime type override not found in data offer, caller must check");
8036 struct ThreadResult {
8037 char *
data =
nullptr;
8038 size_t data_len = 0;
8039 std::atomic<bool> done =
false;
8042 const bool nil_terminate,
8043 const char *mime_receive,
8045 ThreadResult *thread_result) {
8047 data_offer, mime_receive,
mutex, nil_terminate, &thread_result->data_len);
8048 thread_result->done =
true;
8050 std::thread read_thread(
8051 read_clipboard_fn, data_offer, nil_terminate, mime_receive, &
mutex, &thread_result);
8052 read_thread.detach();
8054 while (!thread_result.done) {
8057 data = thread_result.data;
8058 *r_data_len = thread_result.data_len;
8061 mutex_locked =
false;
8071 const bool nil_terminate,
8072 const char *mime_receive_override,
8082 bool mutex_locked =
true;
8083 char *
data =
nullptr;
8086 if (data_offer !=
nullptr) {
8087 const char *mime_receive = mime_receive_override ?
8088 mime_receive_override :
8091 data_offer->
types.count(mime_receive_override) != 0,
8092 "Mime type override not found in data offer, caller must check");
8097 struct ThreadResult {
8098 char *
data =
nullptr;
8099 size_t data_len = 0;
8100 std::atomic<bool> done =
false;
8103 const bool nil_terminate,
8104 const char *mime_receive,
8106 ThreadResult *thread_result) {
8108 data_offer, mime_receive,
mutex, nil_terminate, &thread_result->data_len);
8109 thread_result->done =
true;
8111 std::thread read_thread(
8112 read_clipboard_fn, data_offer, nil_terminate, mime_receive, &
mutex, &thread_result);
8113 read_thread.detach();
8115 while (!thread_result.done) {
8118 data = thread_result.data;
8119 *r_data_len = thread_result.data_len;
8122 mutex_locked =
false;
8133#ifdef USE_EVENT_BACKGROUND_THREAD
8137 const bool nil_terminate =
true;
8138 char *
data =
nullptr;
8139 size_t data_len = 0;
8170 data_source->
wp.
source = zwp_primary_selection_device_manager_v1_create_source(
8173 zwp_primary_selection_source_v1_add_listener(
8181 zwp_primary_selection_device_v1_set_selection(
8202 data_source->
wl.
source = wl_data_device_manager_create_data_source(
8212 wl_data_device_set_selection(
8219#ifdef USE_EVENT_BACKGROUND_THREAD
8235#ifdef USE_EVENT_BACKGROUND_THREAD
8256 const bool nil_terminate =
true;
8257 size_t data_buf_len = 0;
8263 if (!uris.empty()) {
8264 const std::string_view &uri = uris.front();
8283#ifdef USE_EVENT_BACKGROUND_THREAD
8292 uint *rgba =
nullptr;
8296 ImBuf *ibuf =
nullptr;
8302 size_t data_len = 0;
8313 const bool nil_terminate =
true;
8314 size_t data_len = 0;
8320 if (!uris.empty()) {
8321 const std::string_view &uri = uris.front();
8332 *r_height = ibuf->
y;
8333 const size_t byte_count = size_t(ibuf->
x) * size_t(ibuf->
y) * 4;
8334 rgba = (
uint *)malloc(byte_count);
8345#ifdef USE_EVENT_BACKGROUND_THREAD
8371 char *
data =
static_cast<char *
>(malloc(imgbuffer->
data_size));
8375 data_source->
wl.
source = wl_data_device_manager_create_data_source(
8376 display_->wl.data_device_manager);
8383 wl_data_device_set_selection(
8393#ifdef USE_EVENT_BACKGROUND_THREAD
8397 return display_ ? uint8_t(display_->outputs.size()) : 0;
8403 timespec ts = {0, 0};
8404 clock_gettime(CLOCK_MONOTONIC, &ts);
8422 wl_fixed_t xy_wrap[2] = {
8423 seat_state_pointer->
xy[0],
8424 seat_state_pointer->
xy[1],
8479 const wl_fixed_t xy_next[2]{
8495#ifdef USE_EVENT_BACKGROUND_THREAD
8515#ifdef USE_EVENT_BACKGROUND_THREAD
8529#ifdef USE_EVENT_BACKGROUND_THREAD
8538 if (!seat_state_pointer) {
8554#ifdef USE_EVENT_BACKGROUND_THREAD
8574#ifdef USE_EVENT_BACKGROUND_THREAD
8583#ifdef USE_EVENT_BACKGROUND_THREAD
8587 if (!display_->outputs.empty()) {
8591 if (
output->transform & WL_OUTPUT_TRANSFORM_90) {
8592 std::swap(size_native[0], size_native[1]);
8594 width = uint32_t(size_native[0]);
8595 height = uint32_t(size_native[1]);
8601#ifdef USE_EVENT_BACKGROUND_THREAD
8604 if (!display_->outputs.empty()) {
8611 if (
output->has_position_logical) {
8612 xy[0] =
output->position_logical[0];
8613 xy[1] =
output->position_logical[1];
8615 if (
output->transform & WL_OUTPUT_TRANSFORM_90) {
8616 std::swap(size_native[0], size_native[1]);
8618 xy_min[0] = std::min(xy_min[0],
xy[0]);
8619 xy_min[1] = std::min(xy_min[1],
xy[1]);
8620 xy_max[0] = std::max(xy_max[0],
xy[0] + size_native[0]);
8621 xy_max[1] = std::max(xy_max[1],
xy[1] + size_native[1]);
8624 width = xy_max[0] - xy_min[0];
8625 height = xy_max[1] - xy_min[1];
8631#ifdef USE_EVENT_BACKGROUND_THREAD
8640#ifdef WITH_VULKAN_BACKEND
8641 case GHOST_kDrawingContextTypeVulkan: {
8646 GHOST_kVulkanPlatformWayland,
8650 display_->wl.display,
8656 if (context->initializeDrawingContext()) {
8669#ifdef WITH_OPENGL_BACKEND
8670 case GHOST_kDrawingContextTypeOpenGL: {
8675 for (
int minor = 6; minor >= 3; --minor) {
8679 context_params_offscreen,
8680 EGLNativeWindowType(egl_window),
8681 EGLNativeDisplayType(display_->wl.display),
8682 EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
8686 (context_params_offscreen.
is_debug ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
8690 if (context->initializeDrawingContext()) {
8691 wl_surface_set_user_data(
wl_surface, egl_window);
8698 GHOST_PRINT(
"Cannot create off-screen EGL context" << std::endl);
8718#ifdef USE_EVENT_BACKGROUND_THREAD
8723#ifdef WITH_OPENGL_BACKEND
8725 type = GHOST_kDrawingContextTypeOpenGL;
8728#ifdef WITH_VULKAN_BACKEND
8730 type = GHOST_kDrawingContextTypeVulkan;
8741#ifdef WITH_OPENGL_BACKEND
8742 if (type == GHOST_kDrawingContextTypeOpenGL) {
8743 wl_egl_window *egl_window =
static_cast<wl_egl_window *
>(wl_surface_get_user_data(
wl_surface));
8744 if (egl_window !=
nullptr) {
8760 const uint32_t width,
8761 const uint32_t height,
8764 const bool exclusive,
8765 const bool is_dialog,
8806#ifdef USE_GNOME_CONFINE_HACK
8808 if (use_software_confine) {
8813 (void)use_software_confine;
8827 if (!display_->wp.cursor_shape_manager) {
8831 const std::optional<wp_cursor_shape_device_v1_shape> wl_shape =
8833 if (wl_shape == std::nullopt) {
8841 display_->wp.cursor_shape_manager, seat->
wl.
pointer);
8845 wp_cursor_shape_device_v1_set_shape(
8858 for (zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->
wp.
tablet_tools) {
8860 zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
8862 tablet_tool->
shape.
device = wp_cursor_shape_manager_v1_get_tablet_tool_v2(
8863 display_->wp.cursor_shape_manager, zwp_tablet_tool_v2);
8867 wp_cursor_shape_device_v1_set_shape(
8885 if (!display_->wp.cursor_shape_manager) {
8889 const std::optional<wp_cursor_shape_device_v1_shape> wl_shape =
8891 if (wl_shape == std::nullopt) {
8899 void **buffer_data_p,
8900 size_t *buffer_data_size_p,
8901 const int cursor_size,
8902 const int cursor_size_max,
8903 const int use_dark_theme,
8905 int r_bitmap_size[2],
8908 if (*buffer_data_p) {
8909 munmap(*buffer_data_p, *buffer_data_size_p);
8910 *buffer_data_p =
nullptr;
8911 *buffer_data_size_p = 0;
8914 int bitmap_size_src[2];
8916 bool can_invert_color =
false;
8922 [](
size_t size) -> uint8_t * {
return new uint8_t[
size]; },
8927 if (bitmap_src ==
nullptr) {
8931 const bool invert_color = can_invert_color && use_dark_theme;
8934 int bitmap_size_dst[2] = {
8940 shm, bitmap_size_dst, WL_SHM_FORMAT_ARGB8888, buffer_data_p, buffer_data_size_p);
8942 if (buffer !=
nullptr) {
8943 const bool is_trivial_copy = (bitmap_size_src[0] == bitmap_size_dst[0]) &&
8944 (bitmap_size_src[1] == bitmap_size_dst[1]);
8947 if (is_trivial_copy) {
8949 const uint32_t *px_src =
reinterpret_cast<const uint32_t *
>(bitmap_src);
8950 uint32_t *px_dst =
static_cast<uint32_t *
>(*buffer_data_p);
8952 for (
int y = 0;
y < bitmap_size_src[1];
y++) {
8953 for (
int x = 0;
x < bitmap_size_src[0];
x++) {
8959 for (
int y = 0;
y < bitmap_size_src[1];
y++) {
8960 for (
int x = 0;
x < bitmap_size_src[0];
x++) {
8968 const uint32_t *px_src =
reinterpret_cast<const uint32_t *
>(bitmap_src);
8969 uint32_t *px_dst =
static_cast<uint32_t *
>(*buffer_data_p);
8971 for (
int y = 0;
y < bitmap_size_dst[1];
y++) {
8972 for (
int x = 0;
x < bitmap_size_dst[0];
x++) {
8973 *px_dst++ = (
x >= bitmap_size_src[0] ||
y >= bitmap_size_src[1]) ?
8980 for (
int y = 0;
y < bitmap_size_dst[1];
y++) {
8981 for (
int x = 0;
x < bitmap_size_dst[0];
x++) {
8982 *px_dst++ = (
x >= bitmap_size_src[0] ||
y >= bitmap_size_src[1]) ?
8990 r_bitmap_size[0] = bitmap_size_dst[0];
8991 r_bitmap_size[1] = bitmap_size_dst[1];
8993 r_hot_spot[0] = hot_spot[0];
8994 r_hot_spot[1] = hot_spot[1];
8997 delete[] bitmap_src;
9017 for (zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->
wp.
tablet_tools) {
9019 zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
9021 wp_cursor_shape_device_v1_destroy(tablet_tool->
shape.
device);
9029 int bitmap_size[2] = {0, 0};
9030 int hot_spot[2] = {0, 0};
9039 const int cursor_size_max = std::min(256, cursor_size * 2);
9061 cursor.
wl.
image.width = uint32_t(bitmap_size[0]);
9062 cursor.
wl.
image.height = uint32_t(bitmap_size[1]);
9063 cursor.
wl.
image.hotspot_x = uint32_t(hot_spot[0]);
9064 cursor.
wl.
image.hotspot_y = uint32_t(hot_spot[1]);
9115 "The trackpad direction was expected to be initialized");
9162#ifdef USE_GNOME_CONFINE_HACK
9165 const bool use_software_confine =
false;
9171#ifdef USE_GNOME_CONFINE_HACK
9175# ifndef USE_GNOME_CONFINE_HACK_ALWAYS_ON
9188# ifndef USE_GNOME_CONFINE_HACK_ALWAYS_ON
9198 const bool use_software_confine)
9215#ifdef USE_EVENT_BACKGROUND_THREAD
9219 for (
GWL_Seat *seat : display_->seats) {
9245 const wl_proxy *proxy =
reinterpret_cast<const wl_proxy *
>(wl_output);
9251 const wl_proxy *proxy =
reinterpret_cast<const wl_proxy *
>(
wl_surface);
9262 const wl_proxy *proxy =
reinterpret_cast<const wl_proxy *
>(
wl_surface);
9269 const wl_proxy *proxy =
reinterpret_cast<const wl_proxy *
>(
wl_surface);
9275 wl_proxy *proxy =
reinterpret_cast<wl_proxy *
>(wl_output);
9281 wl_proxy *proxy =
reinterpret_cast<wl_proxy *
>(
wl_surface);
9287 wl_proxy *proxy =
reinterpret_cast<wl_proxy *
>(
wl_surface);
9293 wl_proxy *proxy =
reinterpret_cast<wl_proxy *
>(
wl_surface);
9307 return display_->wl.display;
9312 return display_->wl.compositor;
9317 return display_->wp.primary_selection_device_manager;
9322 return display_->xdg.activation_manager;
9327 return display_->wp.fractional_scale_manager;
9331 return display_->wp.viewporter;
9336 return display_->wp.pointer_gestures;
9347#ifdef WITH_GHOST_WAYLAND_APP_ID
9359#ifdef WITH_GHOST_WAYLAND_LIBDECOR
9361libdecor *GHOST_SystemWayland::libdecor_context_get()
9363 return display_->libdecor->context;
9375 return display_->xdg_decor->manager;
9382 return display_->outputs;
9387 return display_->wl.shm;
9390#ifdef USE_EVENT_BACKGROUND_THREAD
9393 return display_->ghost_timer_manager;
9399 return display_->use_window_frame;
9410#ifdef WITH_INPUT_IME
9417 const bool completed)
const
9423 if (seat->
wp.text_input ==
nullptr) {
9430 gwl_seat_ime_result_reset(seat);
9433 if (seat->ime.is_enabled && completed) {
9437 bool force_rect_update =
false;
9438 if (seat->ime.is_enabled ==
false) {
9439 seat->ime.has_preedit =
false;
9440 seat->ime.is_enabled =
true;
9442 zwp_text_input_v3_enable(seat->
wp.text_input);
9443 zwp_text_input_v3_commit(seat->
wp.text_input);
9446 zwp_text_input_v3_set_content_type(seat->
wp.text_input,
9447 ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE,
9448 ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL);
9450 gwl_seat_ime_rect_reset(seat);
9451 force_rect_update =
true;
9454 if ((force_rect_update ==
false) &&
9455 (seat->ime.rect.x ==
x) &&
9456 (seat->ime.rect.y ==
y) &&
9457 (seat->ime.rect.w ==
w) &&
9458 (seat->ime.rect.h == h))
9468 zwp_text_input_v3_set_cursor_rectangle(seat->
wp.text_input, rect_x, rect_y, rect_w, rect_h);
9470 zwp_text_input_v3_commit(seat->
wp.text_input);
9472 seat->ime.rect.x =
x;
9473 seat->ime.rect.y =
y;
9474 seat->ime.rect.w =
w;
9475 seat->ime.rect.h = h;
9486 seat->ime.is_enabled =
false;
9488 gwl_seat_ime_rect_reset(seat);
9490 if (seat->
wp.text_input ==
nullptr) {
9494 zwp_text_input_v3_disable(seat->
wp.text_input);
9495 zwp_text_input_v3_commit(seat->
wp.text_input);
9541 if (
UNLIKELY(timestamp_as_uint < input_timestamp.
last)) {
9549 if (input_timestamp.
last - timestamp_as_uint > std::numeric_limits<uint32_t>::max() / 2) {
9553 uint64_t(std::numeric_limits<uint32_t>::max()) + 1;
9559 input_timestamp.
offset = offset_test;
9563 input_timestamp.
last = timestamp_as_uint;
9566 timestamp += input_timestamp.
offset;
9570 const uint32_t now_as_uint32 = uint32_t(now);
9571 if (now_as_uint32 == timestamp_as_uint) {
9579 if (!input_timestamp.
offset) {
9580 input_timestamp.
offset = (now - timestamp);
9582 timestamp += input_timestamp.
offset;
9584 if (timestamp > now) {
9585 input_timestamp.
offset -= (timestamp - now);
9596#ifdef USE_EVENT_BACKGROUND_THREAD
9597 GHOST_ASSERT(!display_->background,
"Foreground only");
9599 std::lock_guard
lock{display_->events_pending_mutex};
9600 display_->events_pending.push_back(event);
9625 bool changed =
false;
9626#define SURFACE_CLEAR_PTR(surface_test) \
9627 if (surface_test == wl_surface) { \
9628 surface_test = nullptr; \
9634 for (
GWL_Seat *seat : display_->seats) {
9639#ifdef WITH_INPUT_IME
9643#undef SURFACE_CLEAR_PTR
9650 bool changed =
false;
9658 if (window_manager) {
9667 for (
GWL_Seat *seat : display_->seats) {
9682 if (window_manager) {
9691 for (
GWL_Seat *seat : display_->seats) {
9713 if (
UNLIKELY(!display_->wp.relative_pointer_manager || !display_->wp.pointer_constraints)) {
9722 if (mode == mode_current) {
9726#ifdef USE_GNOME_CONFINE_HACK
9730 const bool was_software_confine =
false;
9731 const bool use_software_confine =
false;
9735 was_software_confine);
9756 wl_fixed_t xy_motion[2] = {0, 0};
9757 bool xy_motion_create_event =
false;
9768 wl_fixed_from_int(wrap_bounds->
l_));
9770 wl_fixed_from_int(wrap_bounds->
t_));
9772 wl_fixed_from_int(wrap_bounds->
r_));
9774 wl_fixed_from_int(wrap_bounds->
b_));
9779 if ((xy_next[0] != seat->
pointer.xy[0]) || (xy_next[1] != seat->
pointer.xy[1])) {
9780 xy_motion[0] = xy_next[0];
9781 xy_motion[1] = xy_next[1];
9782 xy_motion_create_event =
true;
9784 seat->
pointer.xy[0] = xy_next[0];
9785 seat->
pointer.xy[1] = xy_next[1];
9791 const wl_fixed_t xy_next[2] = {
9806 xy_motion[0] = xy_next[0];
9807 xy_motion[1] = xy_next[1];
9808 xy_motion_create_event =
true;
9810 else if (grab_state_prev.
use_lock) {
9814 xy_motion[0] = xy_next[0];
9815 xy_motion[1] = xy_next[1];
9816 xy_motion_create_event =
true;
9819#ifdef USE_GNOME_CONFINE_HACK
9821 if (was_software_confine) {
9829 if (xy_motion_create_event) {
9862 display_->wp.relative_pointer_manager, seat->
wl.
pointer);
9863 zwp_relative_pointer_v1_add_listener(
9866 display_->wp.pointer_constraints,
9870 ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
9875 init_grab_xy[0] = wl_fixed_to_int(
9877 init_grab_xy[1] = wl_fixed_to_int(
9886 display_->wp.pointer_constraints,
9890 ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
9898#ifdef USE_GNOME_CONFINE_HACK
9905#ifdef WITH_GHOST_WAYLAND_LIBDECOR
9906bool GHOST_SystemWayland::use_libdecor_runtime()
9908 return use_libdecor;
9912#ifdef WITH_GHOST_WAYLAND_DYNLOAD
9913bool ghost_wl_dynload_libraries_init(
const bool use_window_frame)
9915# ifdef WITH_GHOST_X11
9919 bool verbose = getenv(
"WAYLAND_DISPLAY") !=
nullptr;
9926# ifdef WITH_OPENGL_BACKEND
9927 wayland_dynload_egl_init(
verbose)
9933# ifdef WITH_GHOST_WAYLAND_LIBDECOR
9934 if (use_window_frame) {
9935 has_libdecor = wayland_dynload_libdecor_init(
verbose);
9938 (void)use_window_frame;
9945# ifdef WITH_OPENGL_BACKEND
9952void ghost_wl_dynload_libraries_exit()
9956# ifdef WITH_OPENGL_BACKEND
9959# ifdef WITH_GHOST_WAYLAND_LIBDECOR
KDTree *BLI_kdtree_nd_ new(unsigned int nodes_len_capacity)
void BLI_kdtree_nd_ free(KDTree *tree)
#define CLOG_DEBUG(clg_ref,...)
#define CLOG_WARN(clg_ref,...)
#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 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)
static int gwl_seat_cursor_buffer_scale_calc(const GWL_Seat *seat)
bool ghost_wl_surface_own(const wl_surface *wl_surface)
static char * system_clipboard_get(GWL_Display *display, const bool nil_terminate, const char *mime_receive_override, size_t *r_data_len)
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 touch_seat_handle_down(void *data, wl_touch *, const uint32_t serial, const uint32_t time, wl_surface *surface, const int32_t id, const wl_fixed_t x, const wl_fixed_t y)
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 pointer_handle_axis_discrete(void *data, wl_pointer *, const uint32_t axis, const int32_t discrete)
static void gwl_seat_capability_keyboard_disable(GWL_Seat *seat)
static void tablet_tool_handle_type(void *data, zwp_tablet_tool_v2 *, const uint32_t tool_type)
static bool gwl_registry_entry_remove_by_interface_slot(GWL_Display *display, const int interface_slot, const bool on_exit)
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 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)
static void touch_seat_handle_motion(void *data, wl_touch *, const uint32_t time, const int32_t id, const wl_fixed_t x, const wl_fixed_t y)
#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 touch_seat_handle_up(void *data, wl_touch *, const uint32_t, const uint32_t time, const int32_t id)
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 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 uint32_t rgba_straight_to_premul(uint32_t rgba_uint)
static CLG_LogRef LOG_WL_RELATIVE_POINTER
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 wl_buffer * ghost_wl_buffer_from_cursor_generator(const GHOST_CursorGenerator &cg, wl_shm *shm, void **buffer_data_p, size_t *buffer_data_size_p, const int cursor_size, const int cursor_size_max, const int use_dark_theme, const int scale, int r_bitmap_size[2], int r_hot_spot[2])
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_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 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 void gwl_registry_wp_cursor_shape_manager_add(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms)
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 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 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 primary_selection_source_send(void *data, zwp_primary_selection_source_v1 *, const char *, const int32_t fd)
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 ghost_wayland_log_handler_background(const char *msg, va_list arg)
static void gwl_registry_wl_seat_remove(GWL_Display *display, void *user_data, const bool on_exit)
static void keyboard_depressed_state_key_event(GWL_Seat *seat, const GHOST_TKey gkey, const GHOST_TEventType etype)
static void touch_seat_handle_frame(void *data, wl_touch *)
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 char * system_clipboard_get_primary_selection(GWL_Display *display, const bool nil_terminate, const char *mime_receive_override, size_t *r_data_len)
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 gwl_seat_capability_touch_disable(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 CLG_LogRef LOG_WL_KEYBOARD
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)
void(*)(GWL_Display *display, const GWL_RegisteryUpdate_Params ¶ms) GWL_RegistryHandler_UpdateFn
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)
#define XKB_VMOD_NAME_HYPER
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 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_motion(void *data, wl_pointer *, const uint32_t time, const wl_fixed_t surface_x, const wl_fixed_t surface_y)
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 constexpr const char * ghost_wl_mime_text_uri_list
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 pointer_handle_axis_source(void *data, wl_pointer *, const uint32_t axis_source)
static uint32_t rgba_straight_to_premul_inverted(uint32_t rgba_uint)
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 pointer_handle_axis_stop(void *data, wl_pointer *, const uint32_t time, const uint32_t axis)
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_shape(void *, wl_touch *, const int32_t, const wl_fixed_t, const wl_fixed_t)
static uint32_t round_up_uint(const uint32_t x, const uint32_t multiple)
static void gwl_seat_capability_touch_enable(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)
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 void pointer_handle_axis_value120(void *data, wl_pointer *, const uint32_t axis, const int32_t value120)
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_cursor_shape_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)
static void output_handle_description(void *, wl_output *, const char *description)
static std::vector< std::string_view > gwl_clipboard_uri_ranges(const char *data_buf, size_t data_buf_len)
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)
void(*)(GWL_Display *display, const GWL_RegisteryAdd_Params ¶ms) GWL_RegistryHandler_AddFn
static void touch_seat_handle_orientation(void *, wl_touch *, const int32_t, const wl_fixed_t)
static CLG_LogRef LOG_WL_CURSOR_BUFFER
static CLG_LogRef LOG_WL_DATA_DEVICE
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 bool update_cursor_scale(GWL_Seat *seat, GWL_Cursor &cursor, GWL_SeatStatePointer *seat_state_pointer)
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 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 std::optional< wp_cursor_shape_device_v1_shape > gwl_seat_cursor_find_wl_shape_from_ghost(const GHOST_TStandardCursor shape)
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 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 int gwl_registry_handler_interface_slot_max()
static void gwl_registry_wl_output_update(GWL_Display *display, const GWL_RegisteryUpdate_Params ¶ms)
static void cursor_surface_handle_preferred_buffer_scale(void *, wl_surface *, const int32_t factor)
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_kEventWheelAxisVertical
@ GHOST_kEventWheelAxisHorizontal
@ 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_kStandardCursorBlade
@ GHOST_kStandardCursorSlip
@ 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)
@ 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_kCapabilityMultiMonitorPlacement
@ GHOST_kCapabilityWindowDecorationStyles
@ GHOST_kCapabilityDesktopSample
#define GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS(gpu_settings)
#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_kModifierKeyRightHyper
@ GHOST_kModifierKeyRightAlt
@ GHOST_kModifierKeyRightShift
@ GHOST_kModifierKeyLeftAlt
@ GHOST_kModifierKeyLeftShift
@ GHOST_kModifierKeyLeftOS
@ GHOST_kModifierKeyRightOS
@ GHOST_kModifierKeyLeftHyper
void(* GHOST_TBacktraceFn)(void *file_handle)
#define GHOST_CONTEXT_PARAMS_FROM_GPU_SETTINGS_OFFSCREEN(gpu_settings)
@ 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
ImBuf * IMB_load_image_from_filepath(const char *filepath, const int flags, char r_colorspace[IM_MAX_SPACE]=nullptr)
ImBuf * IMB_load_image_from_memory(const unsigned char *mem, const size_t size, const int flags, const char *descr, const char *filepath=nullptr, char r_colorspace[IM_MAX_SPACE]=nullptr)
ImBuf * IMB_allocFromBuffer(const uint8_t *byte_buffer, const float *float_buffer, unsigned int w, unsigned int h, unsigned int channels)
void IMB_freeImBuf(ImBuf *ibuf)
bool IMB_save_image(ImBuf *ibuf, const char *filepath, const int flags)
bool IMB_test_image(const char *filepath)
BMesh const char void * data
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
uint64_t getTime() const override
virtual GHOST_TEventType getType() const =0
virtual GHOST_IWindow * getWindow() const =0
static GHOST_TBacktraceFn getBacktraceFn()
static bool getUseWindowFrame()
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 use_window_frame_get()
bool window_surface_unref(const wl_surface *wl_surface)
uint64_t getMilliSeconds() const override
GHOST_IContext * createOffscreenContext(GHOST_GPUSettings gpu_settings) 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
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()
GHOST_IWindow * createWindow(const char *title, int32_t left, int32_t top, uint32_t width, uint32_t height, GHOST_TWindowState state, GHOST_GPUSettings gpu_settings, const bool exclusive, const bool is_dialog, const GHOST_IWindow *parent_window) override
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
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 GHOST_CursorGenerator &cg)
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 cursor_shape_check(GHOST_TStandardCursor cursor_shape)
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()
uint32_t getCursorPreferredLogicalSize() const override
struct zwp_pointer_gestures_v1 * wp_pointer_gestures_get()
void ime_end(const GHOST_WindowWayland *win) const
void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const override
GHOST_TSuccess putClipboardImage(uint *rgba, int width, int height) const override
GHOST_TSuccess removeTimer(GHOST_ITimerTask *timerTask) override
GHOST_EventManager * getEventManager() const
GHOST_WindowManager * getWindowManager() const
GHOST_ITimerTask * installTimer(uint64_t delay, uint64_t interval, GHOST_TimerProcPtr timer_proc, GHOST_TUserDataPtr user_data=nullptr) override
GHOST_WindowManager * window_manager_
GHOST_TSuccess init() override
GHOST_TimerManager * getTimerManager() const
bool multitouch_gestures_
GHOST_TSuccess removeTimer(GHOST_TimerTask *timer)
GHOST_TSuccess addTimer(GHOST_TimerTask *timer)
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()
void pending_actions_handle()
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 std::vector< GWL_Output * > & outputs_get()
GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds) const override
GHOST_TAxisFlag getCursorGrabAxis() const
bool getCursorGrabModeIsWarp() const
static __attribute__((constructor)) void cpu_check()
float distance(VecOp< float, D >, VecOp< float, D >) RET
constexpr T degrees(T) RET
static void error(const char *str)
static int make(const char *input_file_name, const char *output_file_name)
static void add(blender::Map< std::string, std::string > &messages, Message &msg)
int context(const bContext *C, const char *member, bContextDataResult *result)
bool is_enabled(const Sculpt &sd, const Object &object, const Brush *br)
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
static blender::bke::bNodeSocketTemplate outputs[]
uint8_t *(* generate_fn)(const struct GHOST_CursorGenerator *cursor_generator, int cursor_size, int cursor_size_max, uint8_t *(*alloc_fn)(size_t size), int r_bitmap_size[2], int r_hot_spot[2], bool *r_can_invert_color)
GHOST_TDrawingContextType context_type
GHOST_GPUDevice preferred_device
void set(GHOST_TModifierKey mask, bool down)
wp_cursor_shape_device_v1_shape enum_id
wp_cursor_shape_device_v1 * device
struct GWL_Cursor::@361377342315024131007131141106246124016160013120 wl
wl_surface * surface_cursor
std::unordered_set< std::string > types
struct GWL_DataOffer::@334103022322207061254104303345205274250014044005 wl
enum wl_data_device_manager_dnd_action source_actions
struct GWL_DataOffer::@217324163252040336113376260233024075243016057037 dnd
enum wl_data_device_manager_dnd_action action
GWL_SimpleBuffer buffer_out
struct GWL_DataSource::@266042222204251015347010154006334262054211005334 wl
wp_viewporter * viewporter
zwp_primary_selection_device_manager_v1 * primary_selection_device_manager
std::vector< GWL_Seat * > seats
struct GWL_Display::@377160373310317124234021123011227252215025331223 wp
bool events_pthread_is_active
GHOST_TimerManager * ghost_timer_manager
wp_cursor_shape_manager_v1 * cursor_shape_manager
std::vector< const GHOST_IEvent * > events_pending
std::vector< GWL_Output * > outputs
zwp_pointer_gestures_v1 * pointer_gestures
GWL_DisplayTimeStamp input_timestamp
GWL_XDG_Decor_System * xdg_decor
bool registry_skip_update_all
GWL_RegistryEntry * registry_entry
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
GHOST_SystemWayland * system
struct GWL_Display::@234333126216254210337351216147121177233062323122 xdg
std::mutex events_pending_mutex
wp_fractional_scale_manager_v1 * fractional_scale_manager
struct GWL_Display::@321377230270061333154270000162234377344051377131 wl
struct GWL_KeyRepeatPlayload::@077373356266136034236002110051217054213267072014 key_data
int16_t mods[GHOST_KEY_MODIFIER_NUM]
const char * display_name
zwp_primary_selection_offer_v1 * id
struct GWL_PrimarySelection_DataOffer::@126163024221241304171225225122074375250327314300 wp
std::unordered_set< std::string > types
GWL_SimpleBuffer buffer_out
zwp_primary_selection_source_v1 * source
struct GWL_PrimarySelection_DataSource::@146206146215104204277350107221366004233173220362 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::@353342232162005204307367117272165333367002150347 wl
GWL_ScaledFixedT rotation
struct GWL_SeatStatePointer_Events::@244132231361010161020033004333042172111261173215 frame_pending
GWL_Pointer_EventTypes frame_types[GWL_TabletTool_FrameTypes_NUM]
uint64_t frame_event_ms[GWL_TabletTool_FrameTypes_NUM]
struct GWL_SeatStatePointer::@336213342257301200376135072032273072076332056355 wl
wl_surface * surface_window
std::unordered_set< const GWL_Output * > outputs
uint64_t down_event_time_ms
GHOST_SystemWayland * system
GWL_SeatStatePointerScroll pointer_scroll
GWL_KeyboardDepressedState key_depressed
GWL_SeatStatePointer_Events pointer_events
GWL_DataSource * data_source
uint32_t data_source_serial
std::unordered_set< zwp_tablet_tool_v2 * > tablet_tools
GWL_DataOffer * data_offer_copy_paste
zwp_primary_selection_device_v1 * primary_selection_device
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
std::optional< GHOST_TSuccess > data_offer_copy_paste_has_image
xkb_state * state_empty_with_shift
std::mutex data_offer_dnd_mutex
xkb_state * state_empty_with_numlock
struct GWL_Seat::@132041123005365121307037035360256064046111337367 touch_state
struct GWL_Seat::@360021217123271153135215030240240320226166147312 wl
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
struct GWL_Seat::@375225021115324154323117303040370103243002125241 xkb
xkb_mod_index_t xkb_keymap_mod_index_numlock
bool xkb_use_non_latin_workaround
uint64_t up_event_time_ms
wl_fixed_t grab_lock_xy[2]
struct GWL_Seat::@133203264172213324173147220125305012136217124230 wp
GWL_DataOffer * data_offer_dnd
struct GWL_Seat::@225162300071177161133132354334042056236157324101 key_repeat
xkb_mod_index_t xkb_keymap_mod_index_mod2
zwp_locked_pointer_v1 * locked_pointer
GWL_SeatStatePointerGesture_Pinch pointer_gesture_pinch
uint64_t motion_event_time_ms
bool use_pointer_software_confine
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(...)
void wayland_dynload_egl_exit(void)
#define wl_egl_window_create(...)
#define wl_egl_window_destroy(...)
void wayland_dynload_libdecor_exit(void)
#define libdecor_unref(...)
#define libdecor_new(...)