From eb9fa052a173355475be3d91395ec24fb2b0f865 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 10 Jun 2022 13:15:07 +1000 Subject: Clenaup: use early returns in GHOST/Wayland --- intern/ghost/intern/GHOST_SystemWayland.cpp | 74 ++++++++++++++++------------- 1 file changed, 41 insertions(+), 33 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index a5789a2526f..05f2c5d1177 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1561,42 +1561,44 @@ int GHOST_SystemWayland::setConsoleWindowState(GHOST_TConsoleWindowState /*actio GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) const { - if (!d->inputs.empty()) { - static const xkb_state_component mods_all = xkb_state_component( - XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED | - XKB_STATE_MODS_EFFECTIVE); - - keys.set(GHOST_kModifierKeyLeftShift, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) == - 1); - keys.set(GHOST_kModifierKeyRightShift, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) == - 1); - keys.set(GHOST_kModifierKeyLeftAlt, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "LAlt", mods_all) == 1); - keys.set(GHOST_kModifierKeyRightAlt, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "RAlt", mods_all) == 1); - keys.set(GHOST_kModifierKeyLeftControl, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "LControl", mods_all) == 1); - keys.set(GHOST_kModifierKeyRightControl, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "RControl", mods_all) == 1); - keys.set(GHOST_kModifierKeyOS, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "Super", mods_all) == 1); - keys.set(GHOST_kModifierKeyNumMasks, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "NumLock", mods_all) == 1); - - return GHOST_kSuccess; + if (d->inputs.empty()) { + return GHOST_kFailure; } - return GHOST_kFailure; + + static const xkb_state_component mods_all = xkb_state_component( + XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED | + XKB_STATE_MODS_EFFECTIVE); + + keys.set(GHOST_kModifierKeyLeftShift, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) == + 1); + keys.set(GHOST_kModifierKeyRightShift, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) == + 1); + keys.set(GHOST_kModifierKeyLeftAlt, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "LAlt", mods_all) == 1); + keys.set(GHOST_kModifierKeyRightAlt, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "RAlt", mods_all) == 1); + keys.set(GHOST_kModifierKeyLeftControl, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "LControl", mods_all) == 1); + keys.set(GHOST_kModifierKeyRightControl, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "RControl", mods_all) == 1); + keys.set(GHOST_kModifierKeyOS, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "Super", mods_all) == 1); + keys.set(GHOST_kModifierKeyNumMasks, + xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "NumLock", mods_all) == 1); + + return GHOST_kSuccess; } GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const { - if (!d->inputs.empty()) { - buttons = d->inputs[0]->buttons; - return GHOST_kSuccess; + if (d->inputs.empty()) { + return GHOST_kFailure; } - return GHOST_kFailure; + + buttons = d->inputs[0]->buttons; + return GHOST_kSuccess; } char *GHOST_SystemWayland::getClipboard(bool /*selection*/) const @@ -1813,14 +1815,20 @@ static void set_cursor_buffer(input_t *input, wl_buffer *buffer) c->visible = (buffer != nullptr); + const int32_t image_size_x = int32_t(c->image.width); + const int32_t image_size_y = int32_t(c->image.height); + + const int32_t hotspot_x = int32_t(c->image.hotspot_x) / c->scale; + const int32_t hotspot_y = int32_t(c->image.hotspot_y) / c->scale; + wl_surface_attach(c->surface, buffer, 0, 0); + wl_surface_damage(c->surface, 0, 0, image_size_x, image_size_y); - wl_surface_damage(c->surface, 0, 0, int32_t(c->image.width), int32_t(c->image.height)); wl_pointer_set_cursor(input->pointer, input->pointer_serial, c->visible ? c->surface : nullptr, - int32_t(c->image.hotspot_x) / c->scale, - int32_t(c->image.hotspot_y) / c->scale); + hotspot_x, + hotspot_y); wl_surface_commit(c->surface); } -- cgit v1.2.3 From 178c18482546ba7a9e8c7bfdf2164ef6c5993d1a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 10 Jun 2022 15:15:38 +1000 Subject: GHOST/Wayland: define a log handler to help tracking down errors Many errors involving mis-use or unexpected situations report an error and close Blender's window buy don't crash, making it difficult to track down when the error occurs. Define an error handler prints the error and a back-trace, it can also be useful for setting a break-point --- intern/ghost/intern/GHOST_SystemWayland.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 05f2c5d1177..c446963c082 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -171,6 +171,23 @@ struct display_t { static GHOST_WindowManager *window_manager = nullptr; +/** + * Callback for WAYLAND to run when there is an error. + * + * \note It's useful to set a break-point on this function as some errors are fatal + * (for all intents and purposes) but don't crash the process. + */ +static void ghost_wayland_log_handler(const char *msg, va_list arg) +{ + fprintf(stderr, "GHOST/Wayland: "); + vfprintf(stderr, msg, arg); /* Includes newline. */ + + GHOST_TBacktraceFn backtrace_fn = GHOST_ISystem::getBacktraceFn(); + if (backtrace_fn) { + backtrace_fn(stderr); /* Includes newline. */ + } +} + static void display_destroy(display_t *d) { if (d->data_device_manager) { @@ -1503,6 +1520,8 @@ static const struct wl_registry_listener registry_listener = { GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new display_t) { + wl_log_set_handler_client(ghost_wayland_log_handler); + d->system = this; /* Connect to the Wayland server. */ d->display = wl_display_connect(nullptr); -- cgit v1.2.3 From 00aa57594c74c69d53ba326e48d2d1339ab99b75 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 10 Jun 2022 16:32:22 +1000 Subject: Fix dropping files in Wayland There were two problems dropping files into blender: - The inputs `focus_pointer` was NULL, causing a crash. - The wl_data_device_manager version was set to 1, causing the Blender window to close (when dropping files in gnome-shell 42). Resolve by storing the drop surface separately from the pointer surface and bump the device manager version to 3. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index c446963c082..b9696ab6354 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -38,6 +38,8 @@ #include +static GHOST_IWindow *get_window(struct wl_surface *surface); + /* -------------------------------------------------------------------- */ /** \name Private Types & Defines * \{ */ @@ -131,6 +133,7 @@ struct input_t { struct wl_surface *focus_pointer = nullptr; struct wl_surface *focus_keyboard = nullptr; + struct wl_surface *focus_dnd = nullptr; struct wl_data_device *data_device = nullptr; /** Drag & Drop. */ @@ -508,7 +511,7 @@ static void dnd_events(const input_t *const input, const GHOST_TEventType event) { const uint64_t time = input->system->getMilliSeconds(); GHOST_IWindow *const window = static_cast( - wl_surface_get_user_data(input->focus_pointer)); + wl_surface_get_user_data(input->focus_dnd)); for (const std::string &type : mime_preference_order) { input->system->pushEvent(new GHOST_EventDragnDrop(time, event, @@ -670,7 +673,7 @@ static void data_device_data_offer(void * /*data*/, static void data_device_enter(void *data, struct wl_data_device * /*wl_data_device*/, uint32_t serial, - struct wl_surface * /*surface*/, + struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y, struct wl_data_offer *id) @@ -692,6 +695,7 @@ static void data_device_enter(void *data, wl_data_offer_accept(id, serial, type.c_str()); } + input->focus_dnd = surface; dnd_events(input, GHOST_kEventDraggingEntered); } @@ -700,6 +704,7 @@ static void data_device_leave(void *data, struct wl_data_device * /*wl_data_devi input_t *input = static_cast(data); dnd_events(input, GHOST_kEventDraggingExited); + input->focus_dnd = nullptr; if (input->data_offer_dnd && !input->data_offer_dnd->in_use.load()) { wl_data_offer_destroy(input->data_offer_dnd->id); @@ -732,6 +737,7 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic auto read_uris = [](input_t *const input, data_offer_t *data_offer, + wl_surface *surface, const std::string mime_receive) { const int x = data_offer->dnd.x; const int y = data_offer->dnd.y; @@ -750,6 +756,9 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic static constexpr const char *file_proto = "file://"; static constexpr const char *crlf = "\r\n"; + GHOST_WindowWayland *win = static_cast(get_window(surface)); + GHOST_ASSERT(win != nullptr, "Unable to find window for drop event from surface"); + std::vector uris; size_t pos = 0; @@ -773,8 +782,6 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic flist->strings[i] = static_cast(malloc((uris[i].size() + 1) * sizeof(uint8_t))); memcpy(flist->strings[i], uris[i].data(), uris[i].size() + 1); } - GHOST_IWindow *win = static_cast( - wl_surface_get_user_data(input->focus_pointer)); system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(), GHOST_kEventDraggingDropDone, GHOST_kDragnDropTypeFilenames, @@ -790,7 +797,9 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic wl_display_roundtrip(system->display()); }; - std::thread read_thread(read_uris, input, data_offer, mime_receive); + /* Pass in `input->focus_dnd` instead of accessing it from `input` since the leave callback + * (#data_device_leave) will clear the value once this function starts. */ + std::thread read_thread(read_uris, input, data_offer, input->focus_dnd, mime_receive); read_thread.detach(); } @@ -1480,7 +1489,7 @@ static void global_add(void *data, } else if (!strcmp(interface, wl_data_device_manager_interface.name)) { display->data_device_manager = static_cast( - wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 1)); + wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 3)); } else if (!strcmp(interface, zwp_relative_pointer_manager_v1_interface.name)) { display->relative_pointer_manager = static_cast( -- cgit v1.2.3 From 28f852ccc396eff600467b150b279ada43c00d6b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 10 Jun 2022 18:24:26 +1000 Subject: Fix T98758: Crash setting the clipboard in Wayland Accessing the clipboard in wayland wasn't thread safe, use locks for the clipboard, drag & drop data access and when setting the systems clipboard. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 90 +++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 25 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index b9696ab6354..c2240e34890 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -37,6 +37,7 @@ #include #include +#include static GHOST_IWindow *get_window(struct wl_surface *surface); @@ -91,8 +92,6 @@ struct data_offer_t { struct data_source_t { struct wl_data_source *data_source; - /** Last device that was active. */ - uint32_t source_serial; char *buffer_out; }; @@ -138,10 +137,17 @@ struct input_t { struct wl_data_device *data_device = nullptr; /** Drag & Drop. */ struct data_offer_t *data_offer_dnd; + std::mutex data_offer_dnd_lock; + /** Copy & Paste. */ struct data_offer_t *data_offer_copy_paste; + std::mutex data_offer_copy_paste_mutex; struct data_source_t *data_source; + std::mutex data_source_mutex; + + /** Last device that was active. */ + uint32_t data_source_serial; }; struct display_t { @@ -174,6 +180,9 @@ struct display_t { static GHOST_WindowManager *window_manager = nullptr; +/** Check this lock before accessing `GHOST_SystemWayland::selection` from a thread. */ +static std::mutex system_selection_mutex; + /** * Callback for WAYLAND to run when there is an error. * @@ -509,6 +518,7 @@ static const zwp_relative_pointer_v1_listener relative_pointer_listener = { static void dnd_events(const input_t *const input, const GHOST_TEventType event) { + /* NOTE: `input->data_offer_dnd_lock` must already be locked. */ const uint64_t time = input->system->getMilliSeconds(); GHOST_IWindow *const window = static_cast( wl_surface_get_user_data(input->focus_dnd)); @@ -523,7 +533,9 @@ static void dnd_events(const input_t *const input, const GHOST_TEventType event) } } -static std::string read_pipe(data_offer_t *data_offer, const std::string mime_receive) +static std::string read_pipe(data_offer_t *data_offer, + const std::string mime_receive, + std::mutex *mutex) { int pipefd[2]; if (pipe(pipefd) != 0) { @@ -532,6 +544,13 @@ static std::string read_pipe(data_offer_t *data_offer, const std::string mime_re wl_data_offer_receive(data_offer->id, mime_receive.c_str(), pipefd[1]); close(pipefd[1]); + data_offer->in_use.store(false); + + if (mutex) { + mutex->unlock(); + } + /* WARNING: `data_offer` may be freed from now on. */ + std::string data; ssize_t len; char buffer[4096]; @@ -539,7 +558,6 @@ static std::string read_pipe(data_offer_t *data_offer, const std::string mime_re data.insert(data.end(), buffer, buffer + len); } close(pipefd[0]); - data_offer->in_use.store(false); return data; } @@ -562,7 +580,10 @@ static void data_source_send(void *data, const char * /*mime_type*/, int32_t fd) { - const char *const buffer = static_cast(data); + input_t *input = static_cast(data); + std::lock_guard lock{input->data_source_mutex}; + + const char *const buffer = input->data_source->buffer_out; if (write(fd, buffer, strlen(buffer)) < 0) { GHOST_PRINT("error writing to clipboard: " << std::strerror(errno) << std::endl); } @@ -679,6 +700,8 @@ static void data_device_enter(void *data, struct wl_data_offer *id) { input_t *input = static_cast(data); + std::lock_guard lock{input->data_offer_dnd_lock}; + input->data_offer_dnd = static_cast(wl_data_offer_get_user_data(id)); data_offer_t *data_offer = input->data_offer_dnd; @@ -702,6 +725,7 @@ static void data_device_enter(void *data, static void data_device_leave(void *data, struct wl_data_device * /*wl_data_device*/) { input_t *input = static_cast(data); + std::lock_guard lock{input->data_offer_dnd_lock}; dnd_events(input, GHOST_kEventDraggingExited); input->focus_dnd = nullptr; @@ -720,6 +744,8 @@ static void data_device_motion(void *data, wl_fixed_t y) { input_t *input = static_cast(data); + std::lock_guard lock{input->data_offer_dnd_lock}; + input->data_offer_dnd->dnd.x = wl_fixed_to_int(x); input->data_offer_dnd->dnd.y = wl_fixed_to_int(y); dnd_events(input, GHOST_kEventDraggingUpdated); @@ -728,6 +754,8 @@ static void data_device_motion(void *data, static void data_device_drop(void *data, struct wl_data_device * /*wl_data_device*/) { input_t *input = static_cast(data); + std::lock_guard lock{input->data_offer_dnd_lock}; + data_offer_t *data_offer = input->data_offer_dnd; const std::string mime_receive = *std::find_first_of(mime_preference_order.begin(), @@ -742,7 +770,7 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic const int x = data_offer->dnd.x; const int y = data_offer->dnd.y; - const std::string data = read_pipe(data_offer, mime_receive); + const std::string data = read_pipe(data_offer, mime_receive, nullptr); wl_data_offer_finish(data_offer->id); wl_data_offer_destroy(data_offer->id); @@ -808,6 +836,9 @@ static void data_device_selection(void *data, struct wl_data_offer *id) { input_t *input = static_cast(data); + + std::lock_guard lock{input->data_offer_copy_paste_mutex}; + data_offer_t *data_offer = input->data_offer_copy_paste; /* Delete old data offer. */ @@ -825,22 +856,28 @@ static void data_device_selection(void *data, data_offer = static_cast(wl_data_offer_get_user_data(id)); input->data_offer_copy_paste = data_offer; - std::string mime_receive; - for (const std::string type : {mime_text_utf8, mime_text_plain}) { - if (data_offer->types.count(type)) { - mime_receive = type; - break; + auto read_selection = [](input_t *input) { + GHOST_SystemWayland *const system = input->system; + input->data_offer_copy_paste_mutex.lock(); + + data_offer_t *data_offer = input->data_offer_copy_paste; + std::string mime_receive; + for (const std::string type : {mime_text_utf8, mime_text_plain}) { + if (data_offer->types.count(type)) { + mime_receive = type; + break; + } } - } + const std::string data = read_pipe( + data_offer, mime_receive, &input->data_offer_copy_paste_mutex); - auto read_selection = [](GHOST_SystemWayland *const system, - data_offer_t *data_offer, - const std::string mime_receive) { - const std::string data = read_pipe(data_offer, mime_receive); - system->setSelection(data); + { + std::lock_guard lock{system_selection_mutex}; + system->setSelection(data); + } }; - std::thread read_thread(read_selection, input->system, data_offer, mime_receive); + std::thread read_thread(read_selection, input); read_thread.detach(); } @@ -1066,7 +1103,7 @@ static void pointer_button(void *data, break; } - input->data_source->source_serial = serial; + input->data_source_serial = serial; input->buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED); input->system->pushEvent(new GHOST_EventButton( input->system->getMilliSeconds(), etype, win, ebutton, GHOST_TABLET_DATA_NONE)); @@ -1241,7 +1278,7 @@ static void keyboard_key(void *data, key_data.utf8_buf[0] = '\0'; } - input->data_source->source_serial = serial; + input->data_source_serial = serial; GHOST_IWindow *win = static_cast( wl_surface_get_user_data(input->focus_keyboard)); @@ -1642,7 +1679,11 @@ void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) c return; } - data_source_t *data_source = d->inputs[0]->data_source; + input_t *input = d->inputs[0]; + + std::lock_guard lock{input->data_source_mutex}; + + data_source_t *data_source = input->data_source; /* Copy buffer. */ free(data_source->buffer_out); @@ -1652,16 +1693,15 @@ void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) c data_source->data_source = wl_data_device_manager_create_data_source(d->data_device_manager); - wl_data_source_add_listener( - data_source->data_source, &data_source_listener, data_source->buffer_out); + wl_data_source_add_listener(data_source->data_source, &data_source_listener, input); for (const std::string &type : mime_send) { wl_data_source_offer(data_source->data_source, type.c_str()); } - if (!d->inputs.empty() && d->inputs[0]->data_device) { + if (input->data_device) { wl_data_device_set_selection( - d->inputs[0]->data_device, data_source->data_source, data_source->source_serial); + input->data_device, data_source->data_source, input->data_source_serial); } } -- cgit v1.2.3 From a24a28db7b00551effcce2fb7d6de9b3fcdd05c5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 10 Jun 2022 18:57:39 +1000 Subject: Cleanup: inconsistent naming with recent locking checks in Wayland --- intern/ghost/intern/GHOST_SystemWayland.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index c2240e34890..34311c103eb 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -137,7 +137,7 @@ struct input_t { struct wl_data_device *data_device = nullptr; /** Drag & Drop. */ struct data_offer_t *data_offer_dnd; - std::mutex data_offer_dnd_lock; + std::mutex data_offer_dnd_mutex; /** Copy & Paste. */ struct data_offer_t *data_offer_copy_paste; @@ -518,7 +518,7 @@ static const zwp_relative_pointer_v1_listener relative_pointer_listener = { static void dnd_events(const input_t *const input, const GHOST_TEventType event) { - /* NOTE: `input->data_offer_dnd_lock` must already be locked. */ + /* NOTE: `input->data_offer_dnd_mutex` must already be locked. */ const uint64_t time = input->system->getMilliSeconds(); GHOST_IWindow *const window = static_cast( wl_surface_get_user_data(input->focus_dnd)); @@ -700,7 +700,7 @@ static void data_device_enter(void *data, struct wl_data_offer *id) { input_t *input = static_cast(data); - std::lock_guard lock{input->data_offer_dnd_lock}; + std::lock_guard lock{input->data_offer_dnd_mutex}; input->data_offer_dnd = static_cast(wl_data_offer_get_user_data(id)); data_offer_t *data_offer = input->data_offer_dnd; @@ -725,7 +725,7 @@ static void data_device_enter(void *data, static void data_device_leave(void *data, struct wl_data_device * /*wl_data_device*/) { input_t *input = static_cast(data); - std::lock_guard lock{input->data_offer_dnd_lock}; + std::lock_guard lock{input->data_offer_dnd_mutex}; dnd_events(input, GHOST_kEventDraggingExited); input->focus_dnd = nullptr; @@ -744,7 +744,7 @@ static void data_device_motion(void *data, wl_fixed_t y) { input_t *input = static_cast(data); - std::lock_guard lock{input->data_offer_dnd_lock}; + std::lock_guard lock{input->data_offer_dnd_mutex}; input->data_offer_dnd->dnd.x = wl_fixed_to_int(x); input->data_offer_dnd->dnd.y = wl_fixed_to_int(y); @@ -754,7 +754,7 @@ static void data_device_motion(void *data, static void data_device_drop(void *data, struct wl_data_device * /*wl_data_device*/) { input_t *input = static_cast(data); - std::lock_guard lock{input->data_offer_dnd_lock}; + std::lock_guard lock{input->data_offer_dnd_mutex}; data_offer_t *data_offer = input->data_offer_dnd; -- cgit v1.2.3 From 07a5869cf6f7d07c67acfd9305078682e8ffee67 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 12 Jun 2022 17:44:14 +1000 Subject: Fix GHOST/Wayland accessing Ctrl & Alt modifier keys Only the Shift key was working with GHOST's getModifierKeys method. Now all modifiers are accessible, since there is no way of detecting left/right modifiers both are set. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 39 ++++++++++++++++------------- 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 34311c103eb..fd7c0f8b6b6 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1634,24 +1634,27 @@ GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) co XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE); - keys.set(GHOST_kModifierKeyLeftShift, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) == - 1); - keys.set(GHOST_kModifierKeyRightShift, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) == - 1); - keys.set(GHOST_kModifierKeyLeftAlt, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "LAlt", mods_all) == 1); - keys.set(GHOST_kModifierKeyRightAlt, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "RAlt", mods_all) == 1); - keys.set(GHOST_kModifierKeyLeftControl, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "LControl", mods_all) == 1); - keys.set(GHOST_kModifierKeyRightControl, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "RControl", mods_all) == 1); - keys.set(GHOST_kModifierKeyOS, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "Super", mods_all) == 1); - keys.set(GHOST_kModifierKeyNumMasks, - xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, "NumLock", mods_all) == 1); + bool val; + + /* NOTE: XKB doesn't seem to differentiate between left/right modifiers. */ + + val = xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) == 1; + keys.set(GHOST_kModifierKeyLeftShift, val); + keys.set(GHOST_kModifierKeyRightShift, val); + + val = xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_ALT, mods_all) == 1; + keys.set(GHOST_kModifierKeyLeftAlt, val); + keys.set(GHOST_kModifierKeyRightAlt, val); + + val = xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_CTRL, mods_all) == 1; + keys.set(GHOST_kModifierKeyLeftControl, val); + keys.set(GHOST_kModifierKeyRightControl, val); + + val = xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_LOGO, mods_all) == 1; + keys.set(GHOST_kModifierKeyOS, val); + + val = xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_NUM, mods_all) == 1; + keys.set(GHOST_kModifierKeyNumMasks, val); return GHOST_kSuccess; } -- cgit v1.2.3 From 37097ae62a9c13fca81f3fb6d1342057b2f17763 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 13 Jun 2022 00:15:14 +1000 Subject: Fix T98714: Cursor grab restores to the initial location in Wayland While Wayland can't warp the cursor, it can set a hint for the cursor restore location when removing the lock. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 31 +++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index fd7c0f8b6b6..c3300c82b55 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -2131,6 +2131,37 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo input->relative_pointer = nullptr; } if (input->locked_pointer) { + /* Request location to restore to. */ + if (mode_current == GHOST_kGrabWrap) { + GHOST_WindowWayland *win = static_cast(get_window(surface)); + GHOST_Rect bounds; + int x_new = input->x, y_new = input->y; + + /* Fallback to window bounds. */ + if (win->getCursorGrabBounds(bounds) == GHOST_kFailure) { + ((GHOST_Window *)win)->getClientBounds(bounds); + } + bounds.wrapPoint(x_new, y_new, 0, win->getCursorGrabAxis()); + + /* Push an event so the new location is registered. */ + if ((x_new != input->x) || (y_new != input->y)) { + input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(), + GHOST_kEventCursorMove, + win, + x_new, + y_new, + GHOST_TABLET_DATA_NONE)); + } + input->x = x_new; + input->y = y_new; + + const int scale = win->scale(); + zwp_locked_pointer_v1_set_cursor_position_hint(input->locked_pointer, + wl_fixed_from_int(x_new) / scale, + wl_fixed_from_int(y_new) / scale); + wl_surface_commit(surface); + } + zwp_locked_pointer_v1_destroy(input->locked_pointer); input->locked_pointer = nullptr; } -- cgit v1.2.3 From 97f894881cab339eacbf69738ea7c5f687c5179d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 14 Jun 2022 14:51:26 +1000 Subject: GHOST/Wayland add tablet support Add support for tablet pressure, tilt and type detection (eraser, pen.. etc). There is currently an inconsistency where the tablets cursor is scaled larger than the mouse cursor (when the UI is scaled). Although there doesn't seem to be a way to control this from the client. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 423 +++++++++++++++++++++++++++- 1 file changed, 422 insertions(+), 1 deletion(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index c3300c82b55..75e06abdc87 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -29,6 +29,7 @@ #include "GHOST_WaylandCursorSettings.h" #include #include +#include #include #include @@ -60,6 +61,14 @@ static GHOST_IWindow *get_window(struct wl_surface *surface); #define BTN_BACK 0x116 // #define BTN_TASK 0x117 /* UNUSED. */ +/** + * Tablet events, also from `linux/input-event-codes.h`. + */ +#define BTN_STYLUS 0x14b /* Use as right-mouse. */ +#define BTN_STYLUS2 0x14c /* Use as middle-mouse. */ +/* NOTE(@campbellbarton): Map to an additional button (not sure which hardware uses this). */ +#define BTN_STYLUS3 0x149 + struct buffer_t { void *data; size_t size; @@ -79,6 +88,18 @@ struct cursor_t { int scale = 1; }; +/** + * A single tablet can have multiple tools (pen, eraser, brush... etc). + * WAYLAND exposes tools via #zwp_tablet_tool_v2. + * Since are no API's to access properties of the tool, store the values here. + */ +struct tablet_tool_input_t { + struct input_t *input; + struct wl_surface *cursor_surface; + + GHOST_TabletData data; +}; + struct data_offer_t { std::unordered_set types; uint32_t source_actions; @@ -109,8 +130,13 @@ struct input_t { struct wl_seat *seat; struct wl_pointer *pointer = nullptr; struct wl_keyboard *keyboard = nullptr; + struct zwp_tablet_seat_v2 *tablet_seat = nullptr; + + /** All currently active tablet tools (needed for changing the cursor). */ + std::unordered_set tablet_tools; uint32_t pointer_serial; + uint32_t tablet_serial; int x, y; GHOST_Buttons buttons; struct cursor_t cursor; @@ -130,6 +156,7 @@ struct input_t { GHOST_ITimerTask *timer = nullptr; } key_repeat; + struct wl_surface *focus_tablet = nullptr; struct wl_surface *focus_pointer = nullptr; struct wl_surface *focus_keyboard = nullptr; struct wl_surface *focus_dnd = nullptr; @@ -165,6 +192,7 @@ struct display_t { int size; } cursor; struct wl_data_device_manager *data_device_manager = nullptr; + struct zwp_tablet_manager_v2 *tablet_manager = nullptr; struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr; struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr; @@ -206,6 +234,10 @@ static void display_destroy(display_t *d) wl_data_device_manager_destroy(d->data_device_manager); } + if (d->tablet_manager) { + zwp_tablet_manager_v2_destroy(d->tablet_manager); + } + for (output_t *output : d->outputs) { wl_output_destroy(output->output); delete output; @@ -403,6 +435,27 @@ static GHOST_TKey xkb_map_gkey(const xkb_keysym_t &sym) return gkey; } +static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wl_tablet_tool_type) +{ + switch (wl_tablet_tool_type) { + case ZWP_TABLET_TOOL_V2_TYPE_ERASER: { + return GHOST_kTabletModeEraser; + } + case ZWP_TABLET_TOOL_V2_TYPE_PEN: + case ZWP_TABLET_TOOL_V2_TYPE_BRUSH: + case ZWP_TABLET_TOOL_V2_TYPE_PENCIL: + case ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH: + case ZWP_TABLET_TOOL_V2_TYPE_FINGER: + case ZWP_TABLET_TOOL_V2_TYPE_MOUSE: + case ZWP_TABLET_TOOL_V2_TYPE_LENS: { + return GHOST_kTabletModeStylus; + } + } + + GHOST_PRINT("unknown tablet tool: " << wl_tablet_tool_type << std::endl); + return GHOST_kTabletModeStylus; +} + static const int default_cursor_size = 24; static const std::unordered_map cursors = { @@ -1141,6 +1194,343 @@ static const struct wl_pointer_listener pointer_listener = { /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Listener (Tablet Tool), #zwp_tablet_tool_v2_listener + * \{ */ + +static void tablet_tool_type(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t tool_type) +{ + tablet_tool_input_t *tool_input = static_cast(data); + + tool_input->data.Active = tablet_tool_map_type((enum zwp_tablet_tool_v2_type)tool_type); +} + +static void tablet_tool_hardware_serial(void * /*data*/, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t /*hardware_serial_hi*/, + uint32_t /*hardware_serial_lo*/) +{ +} + +static void tablet_tool_hardware_id_wacom(void * /*data*/, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t /*hardware_id_hi*/, + uint32_t /*hardware_id_lo*/) +{ +} + +static void tablet_tool_capability(void * /*data*/, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t /*capability*/) +{ +} + +static void tablet_tool_done(void * /*data*/, struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/) +{ +} +static void tablet_tool_removed(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) +{ + tablet_tool_input_t *tool_input = static_cast(data); + input_t *input = tool_input->input; + + if (tool_input->cursor_surface) { + wl_surface_destroy(tool_input->cursor_surface); + } + input->tablet_tools.erase(zwp_tablet_tool_v2); + + delete tool_input; +} +static void tablet_tool_proximity_in(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t serial, + struct zwp_tablet_v2 * /*tablet*/, + struct wl_surface *surface) +{ + tablet_tool_input_t *tool_input = static_cast(data); + input_t *input = tool_input->input; + + input->focus_tablet = surface; + input->tablet_serial = serial; + input->data_source_serial = serial; + + /* Update #GHOST_TabletData. */ + GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + if (!win) { + return; + } + + win->activate(); + + GHOST_TabletData &td = tool_input->data; + /* Reset, to avoid using stale tilt/pressure. */ + td.Xtilt = 0.0f; + td.Ytilt = 0.0f; + /* In case pressure isn't supported. */ + td.Pressure = 1.0f; + + win->setCursorShape(win->getCursorShape()); +} +static void tablet_tool_proximity_out(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/) +{ + tablet_tool_input_t *tool_input = static_cast(data); + input_t *input = tool_input->input; + GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + + input->focus_tablet = nullptr; + + win->setCursorShape(win->getCursorShape()); +} + +static void tablet_tool_down(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t serial) +{ + tablet_tool_input_t *tool_input = static_cast(data); + input_t *input = tool_input->input; + + GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + if (!win) { + return; + } + + const GHOST_TEventType etype = GHOST_kEventButtonDown; + const GHOST_TButtonMask ebutton = GHOST_kButtonMaskLeft; + input->data_source_serial = serial; + input->buttons.set(ebutton, true); + input->system->pushEvent(new GHOST_EventButton( + input->system->getMilliSeconds(), etype, win, ebutton, tool_input->data)); +} + +static void tablet_tool_up(void *data, struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/) +{ + tablet_tool_input_t *tool_input = static_cast(data); + input_t *input = tool_input->input; + + GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + if (!win) { + return; + } + const GHOST_TEventType etype = GHOST_kEventButtonUp; + const GHOST_TButtonMask ebutton = GHOST_kButtonMaskLeft; + input->buttons.set(ebutton, false); + input->system->pushEvent(new GHOST_EventButton( + input->system->getMilliSeconds(), etype, win, ebutton, tool_input->data)); +} + +static void tablet_tool_motion(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + wl_fixed_t x, + wl_fixed_t y) +{ + tablet_tool_input_t *tool_input = static_cast(data); + input_t *input = tool_input->input; + + GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + if (!win) { + return; + } + + input->x = win->scale() * wl_fixed_to_int(x); + input->y = win->scale() * wl_fixed_to_int(y); + + input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(), + GHOST_kEventCursorMove, + win, + input->x, + input->y, + tool_input->data)); +} + +static void tablet_tool_pressure(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t pressure) +{ + tablet_tool_input_t *tool_input = static_cast(data); + input_t *input = tool_input->input; + + GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + if (!win) { + return; + } + GHOST_TabletData &td = tool_input->data; + td.Pressure = (float)pressure / 65535; +} +static void tablet_tool_distance(void * /*data*/, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t /*distance*/) +{ +} +static void tablet_tool_tilt(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + wl_fixed_t tilt_x, + wl_fixed_t tilt_y) +{ + tablet_tool_input_t *tool_input = static_cast(data); + input_t *input = tool_input->input; + + GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + if (!win) { + return; + } + + GHOST_TabletData &td = tool_input->data; + /* Map degrees to `-1.0..1.0`. */ + td.Xtilt = wl_fixed_to_double(tilt_x) / 90.0f; + td.Ytilt = wl_fixed_to_double(tilt_y) / 90.0f; + td.Xtilt = td.Xtilt < -1.0f ? -1.0f : (td.Xtilt > 1.0f ? 1.0f : td.Xtilt); + td.Ytilt = td.Ytilt < -1.0f ? -1.0f : (td.Ytilt > 1.0f ? 1.0f : td.Ytilt); +} + +static void tablet_tool_rotation(void * /*data*/, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + wl_fixed_t /*degrees*/) +{ + /* Pass. */ +} + +static void tablet_tool_slider(void * /*data*/, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + int32_t /*position*/) +{ + /* Pass. */ +} +static void tablet_tool_wheel(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + wl_fixed_t /*degrees*/, + int32_t clicks) +{ + if (clicks == 0) { + return; + } + + tablet_tool_input_t *tool_input = static_cast(data); + input_t *input = tool_input->input; + + GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + if (!win) { + return; + } + input->system->pushEvent(new GHOST_EventWheel(input->system->getMilliSeconds(), win, clicks)); +} +static void tablet_tool_button(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t serial, + uint32_t button, + uint32_t state) +{ + tablet_tool_input_t *tool_input = static_cast(data); + input_t *input = tool_input->input; + GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + if (!win) { + return; + } + + GHOST_TEventType etype = GHOST_kEventUnknown; + switch (state) { + case WL_POINTER_BUTTON_STATE_RELEASED: + etype = GHOST_kEventButtonUp; + break; + case WL_POINTER_BUTTON_STATE_PRESSED: + etype = GHOST_kEventButtonDown; + break; + } + + GHOST_TButtonMask ebutton = GHOST_kButtonMaskLeft; + switch (button) { + case BTN_STYLUS: + ebutton = GHOST_kButtonMaskRight; + break; + case BTN_STYLUS2: + ebutton = GHOST_kButtonMaskMiddle; + break; + case BTN_STYLUS3: + ebutton = GHOST_kButtonMaskButton4; + break; + } + + input->data_source_serial = serial; + input->buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED); + input->system->pushEvent(new GHOST_EventButton( + input->system->getMilliSeconds(), etype, win, ebutton, tool_input->data)); +} +static void tablet_tool_frame(void * /*data*/, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t /*time*/) +{ +} + +static const struct zwp_tablet_tool_v2_listener tablet_tool_listner = { + tablet_tool_type, + tablet_tool_hardware_serial, + tablet_tool_hardware_id_wacom, + tablet_tool_capability, + tablet_tool_done, + tablet_tool_removed, + tablet_tool_proximity_in, + tablet_tool_proximity_out, + tablet_tool_down, + tablet_tool_up, + tablet_tool_motion, + tablet_tool_pressure, + tablet_tool_distance, + tablet_tool_tilt, + tablet_tool_rotation, + tablet_tool_slider, + tablet_tool_wheel, + tablet_tool_button, + tablet_tool_frame, +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Listener (Table Seat), #zwp_tablet_seat_v2_listener + * \{ */ + +static void tablet_seat_tablet_added(void * /*data*/, + struct zwp_tablet_seat_v2 * /*zwp_tablet_seat_v2*/, + struct zwp_tablet_v2 * /*id*/) +{ + /* Pass. */ +} + +static void tablet_seat_tool_added(void *data, + struct zwp_tablet_seat_v2 * /*zwp_tablet_seat_v2*/, + struct zwp_tablet_tool_v2 *id) +{ + input_t *input = static_cast(data); + tablet_tool_input_t *tool_input = new tablet_tool_input_t(); + tool_input->input = input; + + /* Every tool has it's own cursor surface. */ + tool_input->cursor_surface = wl_compositor_create_surface(input->system->compositor()); + wl_surface_add_listener(tool_input->cursor_surface, &cursor_surface_listener, (void *)input); + + tool_input->data = GHOST_TABLET_DATA_NONE; + + zwp_tablet_tool_v2_add_listener(id, &tablet_tool_listner, tool_input); + + input->tablet_tools.insert(id); +} + +static void tablet_seat_pad_added(void * /*data*/, + struct zwp_tablet_seat_v2 * /*zwp_tablet_seat_v2*/, + struct zwp_tablet_pad_v2 * /*id*/) +{ + /* Pass. */ +} + +const struct zwp_tablet_seat_v2_listener tablet_seat_listener = { + tablet_seat_tablet_added, + tablet_seat_tool_added, + tablet_seat_pad_added, +}; + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Listener (Keyboard), #wl_keyboard_listener * \{ */ @@ -1528,6 +1918,10 @@ static void global_add(void *data, display->data_device_manager = static_cast( wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 3)); } + else if (!strcmp(interface, zwp_tablet_manager_v2_interface.name)) { + display->tablet_manager = static_cast( + wl_registry_bind(wl_registry, name, &zwp_tablet_manager_v2_interface, 1)); + } else if (!strcmp(interface, zwp_relative_pointer_manager_v1_interface.name)) { display->relative_pointer_manager = static_cast( wl_registry_bind(wl_registry, name, &zwp_relative_pointer_manager_v1_interface, 1)); @@ -1598,6 +1992,13 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new display_t) wl_data_device_add_listener(input->data_device, &data_device_listener, input); } } + + if (d->tablet_manager) { + for (input_t *input : d->inputs) { + input->tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(d->tablet_manager, input->seat); + zwp_tablet_seat_v2_add_listener(input->tablet_seat, &tablet_seat_listener, input); + } + } } GHOST_SystemWayland::~GHOST_SystemWayland() @@ -1715,7 +2116,8 @@ uint8_t GHOST_SystemWayland::getNumDisplays() const GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) const { - if (d->inputs.empty() || (d->inputs[0]->focus_pointer == nullptr)) { + if (d->inputs.empty() || + (d->inputs[0]->focus_pointer == nullptr && d->inputs[0]->focus_tablet == nullptr)) { return GHOST_kFailure; } @@ -1902,6 +2304,25 @@ static void set_cursor_buffer(input_t *input, wl_buffer *buffer) hotspot_y); wl_surface_commit(c->surface); + + /* Set the cursor for all tablet tools as well. */ + for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : input->tablet_tools) { + tablet_tool_input_t *tool_input = static_cast( + zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2)); + /* FIXME: for some reason cursor scale is applied twice (when the scale isn't 1x), + * this happens both in gnome-shell & KDE. Setting the surface scale here doesn't help. */ + // wl_surface_set_buffer_scale(tool_input->cursor_surface, 1); + wl_surface_attach(tool_input->cursor_surface, buffer, 0, 0); + wl_surface_damage(tool_input->cursor_surface, 0, 0, image_size_x, image_size_y); + + zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2, + input->tablet_serial, + c->visible ? tool_input->cursor_surface : nullptr, + hotspot_x, + hotspot_y); + + wl_surface_commit(tool_input->cursor_surface); + } } GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape) -- cgit v1.2.3 From f001c857722a8d7ebfc647be54f1a9cb3b2972c4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 14 Jun 2022 15:07:24 +1000 Subject: Cleanup: don't define wayland window methods as private This meant the system couldn't call window methods unless the window was cast to GHOST_Window. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 75e06abdc87..dceff4ef2b4 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -2560,7 +2560,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo /* Fallback to window bounds. */ if (win->getCursorGrabBounds(bounds) == GHOST_kFailure) { - ((GHOST_Window *)win)->getClientBounds(bounds); + win->getClientBounds(bounds); } bounds.wrapPoint(x_new, y_new, 0, win->getCursorGrabAxis()); -- cgit v1.2.3 From 827fa8176737f822b7f8d2354b05e59976c7101a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 14 Jun 2022 15:54:17 +1000 Subject: Fix cursor coordinates being quantized to the window scale in Wayland - Apply the scale before converting cursor coordinates to int. - Store sub-pixel cursor coordinates internally since this is what Wayland uses. - Use `wl_fixed_t xy[2]` for storing coordinates as it simplifies assigning/passing x/y coordinates to an argument / variable. - Also fix drag-and-drop coordinates which ignored scale. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 155 ++++++++++++++++++---------- 1 file changed, 102 insertions(+), 53 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index dceff4ef2b4..9e683ceb437 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -107,7 +107,8 @@ struct data_offer_t { struct wl_data_offer *id; std::atomic in_use; struct { - int x, y; + /** Compatible with #input_t.xy coordinates. */ + wl_fixed_t xy[2]; } dnd; }; @@ -137,7 +138,23 @@ struct input_t { uint32_t pointer_serial; uint32_t tablet_serial; - int x, y; + + /** Use to check if the last cursor input was tablet or pointer. */ + uint32_t cursor_serial; + + /** + * High precision mouse coordinates (pointer or tablet). + * + * The following example converts these values to screen coordinates. + * \code{.cc} + * const wl_fixed_t scale = win->scale(); + * const int event_xy[2] = { + * wl_fixed_to_int(scale * input->xy[0]), + * wl_fixed_to_int(scale * input->xy[1]), + * }; + * \endocde + */ + wl_fixed_t xy[2]; GHOST_Buttons buttons; struct cursor_t cursor; @@ -544,18 +561,19 @@ static void relative_pointer_relative_motion( wl_fixed_t /*dy_unaccel*/) { input_t *input = static_cast(data); - - input->x += wl_fixed_to_int(dx); - input->y += wl_fixed_to_int(dy); - - GHOST_IWindow *win = static_cast( - wl_surface_get_user_data(input->focus_pointer)); + GHOST_WindowWayland *win = static_cast(get_window(input->focus_pointer)); + if (win == nullptr) { + return; + } + const wl_fixed_t scale = win->scale(); + input->xy[0] += dx / scale; + input->xy[1] += dy / scale; input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(), GHOST_kEventCursorMove, win, - input->x, - input->y, + wl_fixed_to_int(scale * input->xy[0]), + wl_fixed_to_int(scale * input->xy[1]), GHOST_TABLET_DATA_NONE)); } @@ -573,16 +591,20 @@ static void dnd_events(const input_t *const input, const GHOST_TEventType event) { /* NOTE: `input->data_offer_dnd_mutex` must already be locked. */ const uint64_t time = input->system->getMilliSeconds(); - GHOST_IWindow *const window = static_cast( + GHOST_WindowWayland *const win = static_cast( wl_surface_get_user_data(input->focus_dnd)); + if (!win) { + return; + } + const wl_fixed_t scale = win->scale(); + const int event_xy[2] = { + wl_fixed_to_int(scale * input->data_offer_dnd->dnd.xy[0]), + wl_fixed_to_int(scale * input->data_offer_dnd->dnd.xy[1]), + }; + for (const std::string &type : mime_preference_order) { - input->system->pushEvent(new GHOST_EventDragnDrop(time, - event, - mime_dnd.at(type), - window, - input->data_offer_dnd->dnd.x, - input->data_offer_dnd->dnd.y, - nullptr)); + input->system->pushEvent(new GHOST_EventDragnDrop( + time, event, mime_dnd.at(type), win, event_xy[0], event_xy[1], nullptr)); } } @@ -759,8 +781,8 @@ static void data_device_enter(void *data, data_offer_t *data_offer = input->data_offer_dnd; data_offer->in_use.store(true); - data_offer->dnd.x = wl_fixed_to_int(x); - data_offer->dnd.y = wl_fixed_to_int(y); + data_offer->dnd.xy[0] = x; + data_offer->dnd.xy[1] = y; wl_data_offer_set_actions(id, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | @@ -799,8 +821,9 @@ static void data_device_motion(void *data, input_t *input = static_cast(data); std::lock_guard lock{input->data_offer_dnd_mutex}; - input->data_offer_dnd->dnd.x = wl_fixed_to_int(x); - input->data_offer_dnd->dnd.y = wl_fixed_to_int(y); + input->data_offer_dnd->dnd.xy[0] = x; + input->data_offer_dnd->dnd.xy[1] = y; + dnd_events(input, GHOST_kEventDraggingUpdated); } @@ -820,8 +843,7 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic data_offer_t *data_offer, wl_surface *surface, const std::string mime_receive) { - const int x = data_offer->dnd.x; - const int y = data_offer->dnd.y; + const wl_fixed_t *xy = data_offer->dnd.xy; const std::string data = read_pipe(data_offer, mime_receive, nullptr); @@ -863,12 +885,14 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic flist->strings[i] = static_cast(malloc((uris[i].size() + 1) * sizeof(uint8_t))); memcpy(flist->strings[i], uris[i].data(), uris[i].size() + 1); } + + const wl_fixed_t scale = win->scale(); system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(), GHOST_kEventDraggingDropDone, GHOST_kDragnDropTypeFilenames, win, - x, - y, + wl_fixed_to_int(scale * xy[0]), + wl_fixed_to_int(scale * xy[1]), flist)); } else if (mime_receive == mime_text_plain || mime_receive == mime_text_utf8) { @@ -1052,17 +1076,19 @@ static void pointer_enter(void *data, input_t *input = static_cast(data); input->pointer_serial = serial; - input->x = win->scale() * wl_fixed_to_int(surface_x); - input->y = win->scale() * wl_fixed_to_int(surface_y); + input->cursor_serial = serial; + input->xy[0] = surface_x; + input->xy[1] = surface_y; input->focus_pointer = surface; win->setCursorShape(win->getCursorShape()); + const wl_fixed_t scale = win->scale(); input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(), GHOST_kEventCursorMove, static_cast(win), - input->x, - input->y, + wl_fixed_to_int(scale * input->xy[0]), + wl_fixed_to_int(scale * input->xy[1]), GHOST_TABLET_DATA_NONE)); } @@ -1095,14 +1121,15 @@ static void pointer_motion(void *data, return; } - input->x = win->scale() * wl_fixed_to_int(surface_x); - input->y = win->scale() * wl_fixed_to_int(surface_y); + input->xy[0] = surface_x; + input->xy[1] = surface_y; + const wl_fixed_t scale = win->scale(); input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(), GHOST_kEventCursorMove, win, - input->x, - input->y, + wl_fixed_to_int(scale * input->xy[0]), + wl_fixed_to_int(scale * input->xy[1]), GHOST_TABLET_DATA_NONE)); } @@ -1253,6 +1280,8 @@ static void tablet_tool_proximity_in(void *data, input->focus_tablet = surface; input->tablet_serial = serial; + input->cursor_serial = serial; + input->data_source_serial = serial; /* Update #GHOST_TabletData. */ @@ -1333,14 +1362,15 @@ static void tablet_tool_motion(void *data, return; } - input->x = win->scale() * wl_fixed_to_int(x); - input->y = win->scale() * wl_fixed_to_int(y); + input->xy[0] = x; + input->xy[1] = y; + const wl_fixed_t scale = win->scale(); input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(), GHOST_kEventCursorMove, win, - input->x, - input->y, + wl_fixed_to_int(scale * input->xy[0]), + wl_fixed_to_int(scale * input->xy[1]), tool_input->data)); } @@ -2116,13 +2146,26 @@ uint8_t GHOST_SystemWayland::getNumDisplays() const GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) const { - if (d->inputs.empty() || - (d->inputs[0]->focus_pointer == nullptr && d->inputs[0]->focus_tablet == nullptr)) { + if (d->inputs.empty()) { + return GHOST_kFailure; + } + + input_t *input = d->inputs[0]; + struct wl_surface *surface = nullptr; + if (input->pointer_serial == input->cursor_serial) { + surface = input->focus_pointer; + } + else if (input->tablet_serial == input->cursor_serial) { + surface = input->focus_tablet; + } + if (!surface) { return GHOST_kFailure; } - x = d->inputs[0]->x; - y = d->inputs[0]->y; + GHOST_WindowWayland *win = static_cast(wl_surface_get_user_data(surface)); + const wl_fixed_t scale = win->scale(); + x = wl_fixed_to_int(scale * input->xy[0]); + y = wl_fixed_to_int(scale * input->xy[1]); return GHOST_kSuccess; } @@ -2556,30 +2599,36 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo if (mode_current == GHOST_kGrabWrap) { GHOST_WindowWayland *win = static_cast(get_window(surface)); GHOST_Rect bounds; - int x_new = input->x, y_new = input->y; + int32_t xy_new[2] = {input->xy[0], input->xy[1]}; /* Fallback to window bounds. */ if (win->getCursorGrabBounds(bounds) == GHOST_kFailure) { win->getClientBounds(bounds); } - bounds.wrapPoint(x_new, y_new, 0, win->getCursorGrabAxis()); + + const int scale = win->scale(); + + bounds.m_l = wl_fixed_from_int(bounds.m_l) / scale; + bounds.m_t = wl_fixed_from_int(bounds.m_t) / scale; + bounds.m_r = wl_fixed_from_int(bounds.m_r) / scale; + bounds.m_b = wl_fixed_from_int(bounds.m_b) / scale; + + bounds.wrapPoint(xy_new[0], xy_new[1], 0, win->getCursorGrabAxis()); /* Push an event so the new location is registered. */ - if ((x_new != input->x) || (y_new != input->y)) { + if ((xy_new[0] != input->xy[0]) || (xy_new[1] != input->xy[1])) { input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(), GHOST_kEventCursorMove, win, - x_new, - y_new, + wl_fixed_to_int(scale * xy_new[0]), + wl_fixed_to_int(scale * xy_new[1]), GHOST_TABLET_DATA_NONE)); } - input->x = x_new; - input->y = y_new; + input->xy[0] = xy_new[0]; + input->xy[1] = xy_new[1]; - const int scale = win->scale(); - zwp_locked_pointer_v1_set_cursor_position_hint(input->locked_pointer, - wl_fixed_from_int(x_new) / scale, - wl_fixed_from_int(y_new) / scale); + zwp_locked_pointer_v1_set_cursor_position_hint( + input->locked_pointer, xy_new[0], xy_new[1]); wl_surface_commit(surface); } -- cgit v1.2.3 From c1d295e905f9fb4a05218bf2db674e7739b179a6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 14 Jun 2022 17:35:29 +1000 Subject: Fix crash in 827fa8176737f822b7f8d2354b05e59976c7101a Missing null pointer check. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 9e683ceb437..49342110df7 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -2163,6 +2163,10 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) co } GHOST_WindowWayland *win = static_cast(wl_surface_get_user_data(surface)); + if (!win) { + return GHOST_kFailure; + } + const wl_fixed_t scale = win->scale(); x = wl_fixed_to_int(scale * input->xy[0]); y = wl_fixed_to_int(scale * input->xy[1]); -- cgit v1.2.3 From c654a922376aae692b643a03e0864ea22841272b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 14 Jun 2022 18:01:51 +1000 Subject: Fix use after free error in 827fa8176737f822b7f8d2354b05e59976c7101a --- intern/ghost/intern/GHOST_SystemWayland.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 49342110df7..caf65f477a1 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -843,7 +843,7 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic data_offer_t *data_offer, wl_surface *surface, const std::string mime_receive) { - const wl_fixed_t *xy = data_offer->dnd.xy; + const wl_fixed_t xy[2] = {data_offer->dnd.xy[0], data_offer->dnd.xy[1]}; const std::string data = read_pipe(data_offer, mime_receive, nullptr); -- cgit v1.2.3 From 08f5219d1c6c5efe76b7b8fb9579eb52f600ad78 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 15 Jun 2022 14:34:06 +1000 Subject: Cleanup: use `int32_t[2]` for Wayland display size variables --- intern/ghost/intern/GHOST_SystemWayland.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index caf65f477a1..de9c865f163 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1833,8 +1833,8 @@ static void output_geometry(void *data, output->transform = transform; output->make = std::string(make); output->model = std::string(model); - output->width_mm = physical_width; - output->height_mm = physical_height; + output->size_mm[0] = physical_width; + output->size_mm[1] = physical_height; } static void output_mode(void *data, @@ -1845,8 +1845,8 @@ static void output_mode(void *data, int32_t /*refresh*/) { output_t *output = static_cast(data); - output->width_pxl = width; - output->height_pxl = height; + output->size_native[0] = width; + output->size_native[1] = height; } /** @@ -2182,8 +2182,8 @@ void GHOST_SystemWayland::getMainDisplayDimensions(uint32_t &width, uint32_t &he { if (getNumDisplays() > 0) { /* We assume first output as main. */ - width = uint32_t(d->outputs[0]->width_pxl) / d->outputs[0]->scale; - height = uint32_t(d->outputs[0]->height_pxl) / d->outputs[0]->scale; + width = uint32_t(d->outputs[0]->size_native[0]) / d->outputs[0]->scale; + height = uint32_t(d->outputs[0]->size_native[1]) / d->outputs[0]->scale; } } -- cgit v1.2.3 From 2770010224aabd2fa858e8beba94eb07357e9d3c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 15 Jun 2022 14:53:33 +1000 Subject: GHOST/Wayland: fractional scaling support GHOST_GetDPIHint now returns a value that takes fractional scaling into account. Otherwise the integer scale is used since Wayland's API's use integer scale values exclusively. Use the same method as SDL to calculate the fractional scale. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 139 +++++++++++++++++++++++++++- 1 file changed, 135 insertions(+), 4 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index de9c865f163..9dc6f2fd00b 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -31,6 +31,8 @@ #include #include #include +#include + #include #include @@ -201,6 +203,7 @@ struct display_t { struct wl_compositor *compositor = nullptr; struct xdg_wm_base *xdg_shell = nullptr; struct zxdg_decoration_manager_v1 *xdg_decoration_manager = nullptr; + struct zxdg_output_manager_v1 *xdg_output_manager = nullptr; struct wl_shm *shm = nullptr; std::vector outputs; std::vector inputs; @@ -1814,6 +1817,79 @@ static const struct wl_seat_listener seat_listener = { /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Listener (XDG Output), #zxdg_output_v1_listener + * \{ */ + +static void xdg_output_handle_logical_position(void *data, + struct zxdg_output_v1 * /*xdg_output*/, + int32_t x, + int32_t y) +{ + output_t *output = static_cast(data); + output->position_logical[0] = x; + output->position_logical[1] = y; + output->has_position_logical = true; +} + +static void xdg_output_handle_logical_size(void *data, + struct zxdg_output_v1 * /*xdg_output*/, + int32_t width, + int32_t height) +{ + output_t *output = static_cast(data); + + if (output->size_logical[0] != 0 && output->size_logical[1] != 0) { + /* Original comment from SDL. */ + /* FIXME: GNOME has a bug where the logical size does not account for + * scale, resulting in bogus viewport sizes. + * + * Until this is fixed, validate that _some_ kind of scaling is being + * done (we can't match exactly because fractional scaling can't be + * detected otherwise), then override if necessary. + * -flibit + */ + if ((output->size_logical[0] == width) && (output->scale_fractional == wl_fixed_from_int(1))) { + GHOST_PRINT("xdg_output scale did not match, overriding with wl_output scale"); + return; + } + } + + output->size_logical[0] = width; + output->size_logical[1] = height; + output->has_size_logical = true; +} + +static void xdg_output_handle_done(void * /*data*/, struct zxdg_output_v1 * /*xdg_output*/) +{ + /* NOTE: `xdg-output.done` events are deprecated and only apply below version 3 of the protocol. + * `wl-output.done` event will be emitted in version 3 or higher. */ +} + +static void xdg_output_handle_name(void * /*data*/, + struct zxdg_output_v1 * /*xdg_output*/, + const char * /*name*/) +{ + /* Pass. */ +} + +static void xdg_output_handle_description(void * /*data*/, + struct zxdg_output_v1 * /*xdg_output*/, + const char * /*description*/) +{ + /* Pass. */ +} + +static const struct zxdg_output_v1_listener xdg_output_listener = { + xdg_output_handle_logical_position, + xdg_output_handle_logical_size, + xdg_output_handle_done, + xdg_output_handle_name, + xdg_output_handle_description, +}; + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Listener (Output), #wl_output_listener * \{ */ @@ -1839,14 +1915,24 @@ static void output_geometry(void *data, static void output_mode(void *data, struct wl_output * /*wl_output*/, - uint32_t /*flags*/, + uint32_t flags, int32_t width, int32_t height, int32_t /*refresh*/) { output_t *output = static_cast(data); - output->size_native[0] = width; - output->size_native[1] = height; + + if (flags & WL_OUTPUT_MODE_CURRENT) { + output->size_native[0] = width; + output->size_native[1] = height; + + /* Don't rotate this yet, `wl-output` coordinates are transformed in + * handle_done and `xdg-output` coordinates are pre-transformed. */ + if (!output->has_size_logical) { + output->size_logical[0] = width; + output->size_logical[1] = height; + } + } } /** @@ -1857,8 +1943,31 @@ static void output_mode(void *data, * changes done after that. This allows changes to the output * properties to be seen as atomic, even if they happen via multiple events. */ -static void output_done(void * /*data*/, struct wl_output * /*wl_output*/) +static void output_done(void *data, struct wl_output * /*wl_output*/) { + output_t *output = static_cast(data); + int32_t size_native[2]; + if (output->transform & WL_OUTPUT_TRANSFORM_90) { + size_native[0] = output->size_native[1]; + size_native[1] = output->size_native[1]; + } + else { + size_native[0] = output->size_native[0]; + size_native[1] = output->size_native[1]; + } + + /* If `xdg-output` is present, calculate the true scale of the desktop */ + if (output->has_size_logical) { + + /* NOTE: it's not necessary to divide these values by their greatest-common-denominator + * as even a 64k screen resolution doesn't approach overflowing an `int32_t`. */ + + GHOST_ASSERT(size_native[0] && output->size_logical[0], + "Screen size values were not set when they were expected to be."); + + output->scale_fractional = wl_fixed_from_int(size_native[0]) / output->size_logical[0]; + output->has_scale_fractional = true; + } } static void output_scale(void *data, struct wl_output * /*wl_output*/, int32_t factor) @@ -1914,13 +2023,35 @@ static void global_add(void *data, display->xdg_decoration_manager = static_cast( wl_registry_bind(wl_registry, name, &zxdg_decoration_manager_v1_interface, 1)); } + else if (!strcmp(interface, zxdg_output_manager_v1_interface.name)) { + display->xdg_output_manager = static_cast( + wl_registry_bind(wl_registry, name, &zxdg_output_manager_v1_interface, 3)); + for (output_t *output : display->outputs) { + output->xdg_output = zxdg_output_manager_v1_get_xdg_output(display->xdg_output_manager, + output->output); + zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output); + } + } else if (!strcmp(interface, wl_output_interface.name)) { output_t *output = new output_t; + output->scale = 1; + output->has_scale_fractional = false; + output->scale_fractional = wl_fixed_from_int(1); + + output->has_size_logical = false; + output->has_position_logical = false; + output->output = static_cast( wl_registry_bind(wl_registry, name, &wl_output_interface, 2)); display->outputs.push_back(output); wl_output_add_listener(output->output, &output_listener, output); + + if (display->xdg_output_manager) { + output->xdg_output = zxdg_output_manager_v1_get_xdg_output(display->xdg_output_manager, + output->output); + zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output); + } } else if (!strcmp(interface, wl_seat_interface.name)) { input_t *input = new input_t; -- cgit v1.2.3 From 9978689595f87a6b4d8244ee3d014c8fb239e38d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 15 Jun 2022 17:09:39 +1000 Subject: Cleanup: various minor changes to wayland internal conventions - Initialize values in the struct declarations (help avoid accidental uninitialized struct members). - Use `wl_` prefix for some types to avoid e.g. `output->output`. - Use `_fn` suffix for locally defined function variables. - Use `_handle_` as separator for handlers, making function names easier to follow as this separates the handler name from the interface. - Add doxy sections for listeners in GHOST_WaylandWindow.cpp. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 758 ++++++++++++++-------------- 1 file changed, 376 insertions(+), 382 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 9dc6f2fd00b..3d176bdb2f6 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -72,18 +72,18 @@ static GHOST_IWindow *get_window(struct wl_surface *surface); #define BTN_STYLUS3 0x149 struct buffer_t { - void *data; - size_t size; + void *data = nullptr; + size_t size = 0; }; struct cursor_t { - bool visible; - struct wl_surface *surface = nullptr; - struct wl_buffer *buffer; - struct wl_cursor_image image; + bool visible = false; + struct wl_surface *wl_surface = nullptr; + struct wl_buffer *wl_buffer = nullptr; + struct wl_cursor_image wl_image = {0}; + struct wl_cursor_theme *wl_theme = nullptr; struct buffer_t *file_buffer = nullptr; - struct wl_cursor_theme *theme = nullptr; - int size; + int size = 0; std::string theme_name; /** Outputs on which the cursor is visible. */ std::unordered_set outputs; @@ -96,27 +96,27 @@ struct cursor_t { * Since are no API's to access properties of the tool, store the values here. */ struct tablet_tool_input_t { - struct input_t *input; - struct wl_surface *cursor_surface; + struct input_t *input = nullptr; + struct wl_surface *cursor_surface = nullptr; - GHOST_TabletData data; + GHOST_TabletData data = GHOST_TABLET_DATA_NONE; }; struct data_offer_t { std::unordered_set types; - uint32_t source_actions; - uint32_t dnd_action; - struct wl_data_offer *id; - std::atomic in_use; + uint32_t source_actions = 0; + uint32_t dnd_action = 0; + struct wl_data_offer *id = nullptr; + std::atomic in_use = false; struct { /** Compatible with #input_t.xy coordinates. */ - wl_fixed_t xy[2]; + wl_fixed_t xy[2] = {0, 0}; } dnd; }; struct data_source_t { - struct wl_data_source *data_source; - char *buffer_out; + struct wl_data_source *data_source = nullptr; + char *buffer_out = nullptr; }; struct key_repeat_payload_t { @@ -130,9 +130,9 @@ struct input_t { GHOST_SystemWayland *system; std::string name; - struct wl_seat *seat; - struct wl_pointer *pointer = nullptr; - struct wl_keyboard *keyboard = nullptr; + struct wl_seat *wl_seat; + struct wl_pointer *wl_pointer = nullptr; + struct wl_keyboard *wl_keyboard = nullptr; struct zwp_tablet_seat_v2 *tablet_seat = nullptr; /** All currently active tablet tools (needed for changing the cursor). */ @@ -157,15 +157,15 @@ struct input_t { * \endocde */ wl_fixed_t xy[2]; - GHOST_Buttons buttons; + GHOST_Buttons buttons = GHOST_Buttons(); struct cursor_t cursor; - struct zwp_relative_pointer_v1 *relative_pointer; - struct zwp_locked_pointer_v1 *locked_pointer; - struct zwp_confined_pointer_v1 *confined_pointer; + struct zwp_relative_pointer_v1 *relative_pointer = nullptr; + struct zwp_locked_pointer_v1 *locked_pointer = nullptr; + struct zwp_confined_pointer_v1 *confined_pointer = nullptr; - struct xkb_context *xkb_context; - struct xkb_state *xkb_state; + struct xkb_context *xkb_context = nullptr; + struct xkb_state *xkb_state = nullptr; struct { /** Key repetition in character per second. */ int32_t rate; @@ -182,14 +182,14 @@ struct input_t { struct wl_data_device *data_device = nullptr; /** Drag & Drop. */ - struct data_offer_t *data_offer_dnd; + struct data_offer_t *data_offer_dnd = nullptr; std::mutex data_offer_dnd_mutex; /** Copy & Paste. */ - struct data_offer_t *data_offer_copy_paste; + struct data_offer_t *data_offer_copy_paste = nullptr; std::mutex data_offer_copy_paste_mutex; - struct data_source_t *data_source; + struct data_source_t *data_source = nullptr; std::mutex data_source_mutex; /** Last device that was active. */ @@ -197,9 +197,9 @@ struct input_t { }; struct display_t { - GHOST_SystemWayland *system; + GHOST_SystemWayland *system = nullptr; - struct wl_display *display; + struct wl_display *display = nullptr; struct wl_compositor *compositor = nullptr; struct xdg_wm_base *xdg_shell = nullptr; struct zxdg_decoration_manager_v1 *xdg_decoration_manager = nullptr; @@ -209,7 +209,7 @@ struct display_t { std::vector inputs; struct { std::string theme; - int size; + int size = 0; } cursor; struct wl_data_device_manager *data_device_manager = nullptr; struct zwp_tablet_manager_v2 *tablet_manager = nullptr; @@ -259,7 +259,7 @@ static void display_destroy(display_t *d) } for (output_t *output : d->outputs) { - wl_output_destroy(output->output); + wl_output_destroy(output->wl_output); delete output; } @@ -278,28 +278,28 @@ static void display_destroy(display_t *d) if (input->data_device) { wl_data_device_release(input->data_device); } - if (input->pointer) { + if (input->wl_pointer) { if (input->cursor.file_buffer) { munmap(input->cursor.file_buffer->data, input->cursor.file_buffer->size); delete input->cursor.file_buffer; } - if (input->cursor.surface) { - wl_surface_destroy(input->cursor.surface); + if (input->cursor.wl_surface) { + wl_surface_destroy(input->cursor.wl_surface); } - if (input->cursor.theme) { - wl_cursor_theme_destroy(input->cursor.theme); + if (input->cursor.wl_theme) { + wl_cursor_theme_destroy(input->cursor.wl_theme); } - if (input->pointer) { - wl_pointer_destroy(input->pointer); + if (input->wl_pointer) { + wl_pointer_destroy(input->wl_pointer); } } - if (input->keyboard) { + if (input->wl_keyboard) { if (input->key_repeat.timer) { delete static_cast(input->key_repeat.timer->getUserData()); input->system->removeTimer(input->key_repeat.timer); input->key_repeat.timer = nullptr; } - wl_keyboard_destroy(input->keyboard); + wl_keyboard_destroy(input->wl_keyboard); } if (input->xkb_state) { xkb_state_unref(input->xkb_state); @@ -307,7 +307,7 @@ static void display_destroy(display_t *d) if (input->xkb_context) { xkb_context_unref(input->xkb_context); } - wl_seat_destroy(input->seat); + wl_seat_destroy(input->wl_seat); delete input; } @@ -553,7 +553,7 @@ static const std::vector mime_send = { * an event is received from the compositor. * \{ */ -static void relative_pointer_relative_motion( +static void relative_pointer_handle_relative_motion( void *data, struct zwp_relative_pointer_v1 * /*zwp_relative_pointer_v1*/, uint32_t /*utime_hi*/, @@ -581,7 +581,7 @@ static void relative_pointer_relative_motion( } static const zwp_relative_pointer_v1_listener relative_pointer_listener = { - relative_pointer_relative_motion, + relative_pointer_handle_relative_motion, }; /** \} */ @@ -646,17 +646,17 @@ static std::string read_pipe(data_offer_t *data_offer, * Sent when a target accepts pointer_focus or motion events. If * a target does not accept any of the offered types, type is nullptr. */ -static void data_source_target(void * /*data*/, - struct wl_data_source * /*wl_data_source*/, - const char * /*mime_type*/) +static void data_source_handle_target(void * /*data*/, + struct wl_data_source * /*wl_data_source*/, + const char * /*mime_type*/) { /* pass */ } -static void data_source_send(void *data, - struct wl_data_source * /*wl_data_source*/, - const char * /*mime_type*/, - int32_t fd) +static void data_source_handle_send(void *data, + struct wl_data_source * /*wl_data_source*/, + const char * /*mime_type*/, + int32_t fd) { input_t *input = static_cast(data); std::lock_guard lock{input->data_source_mutex}; @@ -668,7 +668,7 @@ static void data_source_send(void *data, close(fd); } -static void data_source_cancelled(void * /*data*/, struct wl_data_source *wl_data_source) +static void data_source_handle_cancelled(void * /*data*/, struct wl_data_source *wl_data_source) { wl_data_source_destroy(wl_data_source); } @@ -680,8 +680,8 @@ static void data_source_cancelled(void * /*data*/, struct wl_data_source *wl_dat * indicate acceptance, #wl_data_source.cancelled may still be * emitted afterwards if the drop destination does not accept any mime type. */ -static void data_source_dnd_drop_performed(void * /*data*/, - struct wl_data_source * /*wl_data_source*/) +static void data_source_handle_dnd_drop_performed(void * /*data*/, + struct wl_data_source * /*wl_data_source*/) { /* pass */ } @@ -693,7 +693,8 @@ static void data_source_dnd_drop_performed(void * /*data*/, * source, so the client is now free to destroy this data source * and free all associated data. */ -static void data_source_dnd_finished(void * /*data*/, struct wl_data_source * /*wl_data_source*/) +static void data_source_handle_dnd_finished(void * /*data*/, + struct wl_data_source * /*wl_data_source*/) { /* pass */ } @@ -705,20 +706,20 @@ static void data_source_dnd_finished(void * /*data*/, struct wl_data_source * /* * after matching the source/destination side actions. Only one * action (or none) will be offered here. */ -static void data_source_action(void * /*data*/, - struct wl_data_source * /*wl_data_source*/, - uint32_t /*dnd_action*/) +static void data_source_handle_action(void * /*data*/, + struct wl_data_source * /*wl_data_source*/, + uint32_t /*dnd_action*/) { /* pass */ } static const struct wl_data_source_listener data_source_listener = { - data_source_target, - data_source_send, - data_source_cancelled, - data_source_dnd_drop_performed, - data_source_dnd_finished, - data_source_action, + data_source_handle_target, + data_source_handle_send, + data_source_handle_cancelled, + data_source_handle_dnd_drop_performed, + data_source_handle_dnd_finished, + data_source_handle_action, }; /** \} */ @@ -727,31 +728,31 @@ static const struct wl_data_source_listener data_source_listener = { /** \name Listener (Data Offer), #wl_data_offer_listener * \{ */ -static void data_offer_offer(void *data, - struct wl_data_offer * /*wl_data_offer*/, - const char *mime_type) +static void data_offer_handle_offer(void *data, + struct wl_data_offer * /*wl_data_offer*/, + const char *mime_type) { static_cast(data)->types.insert(mime_type); } -static void data_offer_source_actions(void *data, - struct wl_data_offer * /*wl_data_offer*/, - uint32_t source_actions) +static void data_offer_handle_source_actions(void *data, + struct wl_data_offer * /*wl_data_offer*/, + uint32_t source_actions) { static_cast(data)->source_actions = source_actions; } -static void data_offer_action(void *data, - struct wl_data_offer * /*wl_data_offer*/, - uint32_t dnd_action) +static void data_offer_handle_action(void *data, + struct wl_data_offer * /*wl_data_offer*/, + uint32_t dnd_action) { static_cast(data)->dnd_action = dnd_action; } static const struct wl_data_offer_listener data_offer_listener = { - data_offer_offer, - data_offer_source_actions, - data_offer_action, + data_offer_handle_offer, + data_offer_handle_source_actions, + data_offer_handle_action, }; /** \} */ @@ -760,22 +761,22 @@ static const struct wl_data_offer_listener data_offer_listener = { /** \name Listener (Data Device), #wl_data_device_listener * \{ */ -static void data_device_data_offer(void * /*data*/, - struct wl_data_device * /*wl_data_device*/, - struct wl_data_offer *id) +static void data_device_handle_data_offer(void * /*data*/, + struct wl_data_device * /*wl_data_device*/, + struct wl_data_offer *id) { data_offer_t *data_offer = new data_offer_t; data_offer->id = id; wl_data_offer_add_listener(id, &data_offer_listener, data_offer); } -static void data_device_enter(void *data, - struct wl_data_device * /*wl_data_device*/, - uint32_t serial, - struct wl_surface *surface, - wl_fixed_t x, - wl_fixed_t y, - struct wl_data_offer *id) +static void data_device_handle_enter(void *data, + struct wl_data_device * /*wl_data_device*/, + uint32_t serial, + struct wl_surface *surface, + wl_fixed_t x, + wl_fixed_t y, + struct wl_data_offer *id) { input_t *input = static_cast(data); std::lock_guard lock{input->data_offer_dnd_mutex}; @@ -800,7 +801,7 @@ static void data_device_enter(void *data, dnd_events(input, GHOST_kEventDraggingEntered); } -static void data_device_leave(void *data, struct wl_data_device * /*wl_data_device*/) +static void data_device_handle_leave(void *data, struct wl_data_device * /*wl_data_device*/) { input_t *input = static_cast(data); std::lock_guard lock{input->data_offer_dnd_mutex}; @@ -815,11 +816,11 @@ static void data_device_leave(void *data, struct wl_data_device * /*wl_data_devi } } -static void data_device_motion(void *data, - struct wl_data_device * /*wl_data_device*/, - uint32_t /*time*/, - wl_fixed_t x, - wl_fixed_t y) +static void data_device_handle_motion(void *data, + struct wl_data_device * /*wl_data_device*/, + uint32_t /*time*/, + wl_fixed_t x, + wl_fixed_t y) { input_t *input = static_cast(data); std::lock_guard lock{input->data_offer_dnd_mutex}; @@ -830,7 +831,7 @@ static void data_device_motion(void *data, dnd_events(input, GHOST_kEventDraggingUpdated); } -static void data_device_drop(void *data, struct wl_data_device * /*wl_data_device*/) +static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_data_device*/) { input_t *input = static_cast(data); std::lock_guard lock{input->data_offer_dnd_mutex}; @@ -842,10 +843,10 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic data_offer->types.begin(), data_offer->types.end()); - auto read_uris = [](input_t *const input, - data_offer_t *data_offer, - wl_surface *surface, - const std::string mime_receive) { + auto read_uris_fn = [](input_t *const input, + data_offer_t *data_offer, + wl_surface *surface, + const std::string mime_receive) { const wl_fixed_t xy[2] = {data_offer->dnd.xy[0], data_offer->dnd.xy[1]}; const std::string data = read_pipe(data_offer, mime_receive, nullptr); @@ -907,13 +908,13 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic /* Pass in `input->focus_dnd` instead of accessing it from `input` since the leave callback * (#data_device_leave) will clear the value once this function starts. */ - std::thread read_thread(read_uris, input, data_offer, input->focus_dnd, mime_receive); + std::thread read_thread(read_uris_fn, input, data_offer, input->focus_dnd, mime_receive); read_thread.detach(); } -static void data_device_selection(void *data, - struct wl_data_device * /*wl_data_device*/, - struct wl_data_offer *id) +static void data_device_handle_selection(void *data, + struct wl_data_device * /*wl_data_device*/, + struct wl_data_offer *id) { input_t *input = static_cast(data); @@ -936,7 +937,7 @@ static void data_device_selection(void *data, data_offer = static_cast(wl_data_offer_get_user_data(id)); input->data_offer_copy_paste = data_offer; - auto read_selection = [](input_t *input) { + auto read_selection_fn = [](input_t *input) { GHOST_SystemWayland *const system = input->system; input->data_offer_copy_paste_mutex.lock(); @@ -957,41 +958,47 @@ static void data_device_selection(void *data, } }; - std::thread read_thread(read_selection, input); + std::thread read_thread(read_selection_fn, input); read_thread.detach(); } static const struct wl_data_device_listener data_device_listener = { - data_device_data_offer, - data_device_enter, - data_device_leave, - data_device_motion, - data_device_drop, - data_device_selection, + data_device_handle_data_offer, + data_device_handle_enter, + data_device_handle_leave, + data_device_handle_motion, + data_device_handle_drop, + data_device_handle_selection, }; /** \} */ /* -------------------------------------------------------------------- */ -/** \name Listener (Surface), #wl_surface_listener +/** \name Listener (Buffer), #wl_buffer_listener * \{ */ -static void cursor_buffer_release(void *data, struct wl_buffer *wl_buffer) +static void cursor_buffer_handle_release(void *data, struct wl_buffer *wl_buffer) { cursor_t *cursor = static_cast(data); wl_buffer_destroy(wl_buffer); - if (wl_buffer == cursor->buffer) { + if (wl_buffer == cursor->wl_buffer) { /* the mapped buffer was from a custom cursor */ - cursor->buffer = nullptr; + cursor->wl_buffer = nullptr; } } const struct wl_buffer_listener cursor_buffer_listener = { - cursor_buffer_release, + cursor_buffer_handle_release, }; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Listener (Surface), #wl_surface_listener + * \{ */ + static GHOST_IWindow *get_window(struct wl_surface *surface) { if (!surface) { @@ -1017,34 +1024,34 @@ static bool update_cursor_scale(cursor_t &cursor, wl_shm *shm) if (scale > 0 && cursor.scale != scale) { cursor.scale = scale; - wl_surface_set_buffer_scale(cursor.surface, scale); - wl_cursor_theme_destroy(cursor.theme); - cursor.theme = wl_cursor_theme_load(cursor.theme_name.c_str(), scale * cursor.size, shm); + wl_surface_set_buffer_scale(cursor.wl_surface, scale); + wl_cursor_theme_destroy(cursor.wl_theme); + cursor.wl_theme = wl_cursor_theme_load(cursor.theme_name.c_str(), scale * cursor.size, shm); return true; } return false; } -static void cursor_surface_enter(void *data, - struct wl_surface * /*wl_surface*/, - struct wl_output *output) +static void cursor_surface_handle_enter(void *data, + struct wl_surface * /*wl_surface*/, + struct wl_output *output) { input_t *input = static_cast(data); for (const output_t *reg_output : input->system->outputs()) { - if (reg_output->output == output) { + if (reg_output->wl_output == output) { input->cursor.outputs.insert(reg_output); } } update_cursor_scale(input->cursor, input->system->shm()); } -static void cursor_surface_leave(void *data, - struct wl_surface * /*wl_surface*/, - struct wl_output *output) +static void cursor_surface_handle_leave(void *data, + struct wl_surface * /*wl_surface*/, + struct wl_output *output) { input_t *input = static_cast(data); for (const output_t *reg_output : input->system->outputs()) { - if (reg_output->output == output) { + if (reg_output->wl_output == output) { input->cursor.outputs.erase(reg_output); } } @@ -1052,8 +1059,8 @@ static void cursor_surface_leave(void *data, } struct wl_surface_listener cursor_surface_listener = { - cursor_surface_enter, - cursor_surface_leave, + cursor_surface_handle_enter, + cursor_surface_handle_leave, }; /** \} */ @@ -1062,12 +1069,12 @@ struct wl_surface_listener cursor_surface_listener = { /** \name Listener (Pointer), #wl_pointer_listener * \{ */ -static void pointer_enter(void *data, - struct wl_pointer * /*wl_pointer*/, - uint32_t serial, - struct wl_surface *surface, - wl_fixed_t surface_x, - wl_fixed_t surface_y) +static void pointer_handle_enter(void *data, + struct wl_pointer * /*wl_pointer*/, + uint32_t serial, + struct wl_surface *surface, + wl_fixed_t surface_x, + wl_fixed_t surface_y) { GHOST_WindowWayland *win = static_cast(get_window(surface)); @@ -1095,10 +1102,10 @@ static void pointer_enter(void *data, GHOST_TABLET_DATA_NONE)); } -static void pointer_leave(void *data, - struct wl_pointer * /*wl_pointer*/, - uint32_t /*serial*/, - struct wl_surface *surface) +static void pointer_handle_leave(void *data, + struct wl_pointer * /*wl_pointer*/, + uint32_t /*serial*/, + struct wl_surface *surface) { GHOST_IWindow *win = get_window(surface); @@ -1110,11 +1117,11 @@ static void pointer_leave(void *data, static_cast(win)->deactivate(); } -static void pointer_motion(void *data, - struct wl_pointer * /*wl_pointer*/, - uint32_t /*time*/, - wl_fixed_t surface_x, - wl_fixed_t surface_y) +static void pointer_handle_motion(void *data, + struct wl_pointer * /*wl_pointer*/, + uint32_t /*time*/, + wl_fixed_t surface_x, + wl_fixed_t surface_y) { input_t *input = static_cast(data); @@ -1136,12 +1143,12 @@ static void pointer_motion(void *data, GHOST_TABLET_DATA_NONE)); } -static void pointer_button(void *data, - struct wl_pointer * /*wl_pointer*/, - uint32_t serial, - uint32_t /*time*/, - uint32_t button, - uint32_t state) +static void pointer_handle_button(void *data, + struct wl_pointer * /*wl_pointer*/, + uint32_t serial, + uint32_t /*time*/, + uint32_t button, + uint32_t state) { input_t *input = static_cast(data); @@ -1192,11 +1199,11 @@ static void pointer_button(void *data, input->system->getMilliSeconds(), etype, win, ebutton, GHOST_TABLET_DATA_NONE)); } -static void pointer_axis(void *data, - struct wl_pointer * /*wl_pointer*/, - uint32_t /*time*/, - uint32_t axis, - wl_fixed_t value) +static void pointer_handle_axis(void *data, + struct wl_pointer * /*wl_pointer*/, + uint32_t /*time*/, + uint32_t axis, + wl_fixed_t value) { input_t *input = static_cast(data); @@ -1215,11 +1222,11 @@ static void pointer_axis(void *data, } static const struct wl_pointer_listener pointer_listener = { - pointer_enter, - pointer_leave, - pointer_motion, - pointer_button, - pointer_axis, + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, }; /** \} */ @@ -1228,39 +1235,41 @@ static const struct wl_pointer_listener pointer_listener = { /** \name Listener (Tablet Tool), #zwp_tablet_tool_v2_listener * \{ */ -static void tablet_tool_type(void *data, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, - uint32_t tool_type) +static void tablet_tool_handle_type(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t tool_type) { tablet_tool_input_t *tool_input = static_cast(data); tool_input->data.Active = tablet_tool_map_type((enum zwp_tablet_tool_v2_type)tool_type); } -static void tablet_tool_hardware_serial(void * /*data*/, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, - uint32_t /*hardware_serial_hi*/, - uint32_t /*hardware_serial_lo*/) +static void tablet_tool_handle_hardware_serial(void * /*data*/, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t /*hardware_serial_hi*/, + uint32_t /*hardware_serial_lo*/) { } -static void tablet_tool_hardware_id_wacom(void * /*data*/, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, - uint32_t /*hardware_id_hi*/, - uint32_t /*hardware_id_lo*/) +static void tablet_tool_handle_hardware_id_wacom( + void * /*data*/, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t /*hardware_id_hi*/, + uint32_t /*hardware_id_lo*/) { } -static void tablet_tool_capability(void * /*data*/, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, - uint32_t /*capability*/) +static void tablet_tool_handle_capability(void * /*data*/, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t /*capability*/) { } -static void tablet_tool_done(void * /*data*/, struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/) +static void tablet_tool_handle_done(void * /*data*/, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/) { } -static void tablet_tool_removed(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) +static void tablet_tool_handle_removed(void *data, struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; @@ -1272,11 +1281,11 @@ static void tablet_tool_removed(void *data, struct zwp_tablet_tool_v2 *zwp_table delete tool_input; } -static void tablet_tool_proximity_in(void *data, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, - uint32_t serial, - struct zwp_tablet_v2 * /*tablet*/, - struct wl_surface *surface) +static void tablet_tool_handle_proximity_in(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t serial, + struct zwp_tablet_v2 * /*tablet*/, + struct wl_surface *surface) { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; @@ -1304,8 +1313,8 @@ static void tablet_tool_proximity_in(void *data, win->setCursorShape(win->getCursorShape()); } -static void tablet_tool_proximity_out(void *data, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/) +static void tablet_tool_handle_proximity_out(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/) { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; @@ -1316,9 +1325,9 @@ static void tablet_tool_proximity_out(void *data, win->setCursorShape(win->getCursorShape()); } -static void tablet_tool_down(void *data, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, - uint32_t serial) +static void tablet_tool_handle_down(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t serial) { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; @@ -1336,7 +1345,7 @@ static void tablet_tool_down(void *data, input->system->getMilliSeconds(), etype, win, ebutton, tool_input->data)); } -static void tablet_tool_up(void *data, struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/) +static void tablet_tool_handle_up(void *data, struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/) { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; @@ -1352,10 +1361,10 @@ static void tablet_tool_up(void *data, struct zwp_tablet_tool_v2 * /*zwp_tablet_ input->system->getMilliSeconds(), etype, win, ebutton, tool_input->data)); } -static void tablet_tool_motion(void *data, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, - wl_fixed_t x, - wl_fixed_t y) +static void tablet_tool_handle_motion(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + wl_fixed_t x, + wl_fixed_t y) { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; @@ -1377,9 +1386,9 @@ static void tablet_tool_motion(void *data, tool_input->data)); } -static void tablet_tool_pressure(void *data, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, - uint32_t pressure) +static void tablet_tool_handle_pressure(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t pressure) { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; @@ -1391,15 +1400,15 @@ static void tablet_tool_pressure(void *data, GHOST_TabletData &td = tool_input->data; td.Pressure = (float)pressure / 65535; } -static void tablet_tool_distance(void * /*data*/, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, - uint32_t /*distance*/) +static void tablet_tool_handle_distance(void * /*data*/, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t /*distance*/) { } -static void tablet_tool_tilt(void *data, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, - wl_fixed_t tilt_x, - wl_fixed_t tilt_y) +static void tablet_tool_handle_tilt(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + wl_fixed_t tilt_x, + wl_fixed_t tilt_y) { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; @@ -1417,23 +1426,23 @@ static void tablet_tool_tilt(void *data, td.Ytilt = td.Ytilt < -1.0f ? -1.0f : (td.Ytilt > 1.0f ? 1.0f : td.Ytilt); } -static void tablet_tool_rotation(void * /*data*/, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, - wl_fixed_t /*degrees*/) +static void tablet_tool_handle_rotation(void * /*data*/, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + wl_fixed_t /*degrees*/) { /* Pass. */ } -static void tablet_tool_slider(void * /*data*/, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, - int32_t /*position*/) +static void tablet_tool_handle_slider(void * /*data*/, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + int32_t /*position*/) { /* Pass. */ } -static void tablet_tool_wheel(void *data, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, - wl_fixed_t /*degrees*/, - int32_t clicks) +static void tablet_tool_handle_wheel(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + wl_fixed_t /*degrees*/, + int32_t clicks) { if (clicks == 0) { return; @@ -1448,11 +1457,11 @@ static void tablet_tool_wheel(void *data, } input->system->pushEvent(new GHOST_EventWheel(input->system->getMilliSeconds(), win, clicks)); } -static void tablet_tool_button(void *data, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, - uint32_t serial, - uint32_t button, - uint32_t state) +static void tablet_tool_handle_button(void *data, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t serial, + uint32_t button, + uint32_t state) { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; @@ -1489,32 +1498,32 @@ static void tablet_tool_button(void *data, input->system->pushEvent(new GHOST_EventButton( input->system->getMilliSeconds(), etype, win, ebutton, tool_input->data)); } -static void tablet_tool_frame(void * /*data*/, - struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, - uint32_t /*time*/) +static void tablet_tool_handle_frame(void * /*data*/, + struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/, + uint32_t /*time*/) { } static const struct zwp_tablet_tool_v2_listener tablet_tool_listner = { - tablet_tool_type, - tablet_tool_hardware_serial, - tablet_tool_hardware_id_wacom, - tablet_tool_capability, - tablet_tool_done, - tablet_tool_removed, - tablet_tool_proximity_in, - tablet_tool_proximity_out, - tablet_tool_down, - tablet_tool_up, - tablet_tool_motion, - tablet_tool_pressure, - tablet_tool_distance, - tablet_tool_tilt, - tablet_tool_rotation, - tablet_tool_slider, - tablet_tool_wheel, - tablet_tool_button, - tablet_tool_frame, + tablet_tool_handle_type, + tablet_tool_handle_hardware_serial, + tablet_tool_handle_hardware_id_wacom, + tablet_tool_handle_capability, + tablet_tool_handle_done, + tablet_tool_handle_removed, + tablet_tool_handle_proximity_in, + tablet_tool_handle_proximity_out, + tablet_tool_handle_down, + tablet_tool_handle_up, + tablet_tool_handle_motion, + tablet_tool_handle_pressure, + tablet_tool_handle_distance, + tablet_tool_handle_tilt, + tablet_tool_handle_rotation, + tablet_tool_handle_slider, + tablet_tool_handle_wheel, + tablet_tool_handle_button, + tablet_tool_handle_frame, }; /** \} */ @@ -1523,16 +1532,16 @@ static const struct zwp_tablet_tool_v2_listener tablet_tool_listner = { /** \name Listener (Table Seat), #zwp_tablet_seat_v2_listener * \{ */ -static void tablet_seat_tablet_added(void * /*data*/, - struct zwp_tablet_seat_v2 * /*zwp_tablet_seat_v2*/, - struct zwp_tablet_v2 * /*id*/) +static void tablet_seat_handle_tablet_added(void * /*data*/, + struct zwp_tablet_seat_v2 * /*zwp_tablet_seat_v2*/, + struct zwp_tablet_v2 * /*id*/) { /* Pass. */ } -static void tablet_seat_tool_added(void *data, - struct zwp_tablet_seat_v2 * /*zwp_tablet_seat_v2*/, - struct zwp_tablet_tool_v2 *id) +static void tablet_seat_handle_tool_added(void *data, + struct zwp_tablet_seat_v2 * /*zwp_tablet_seat_v2*/, + struct zwp_tablet_tool_v2 *id) { input_t *input = static_cast(data); tablet_tool_input_t *tool_input = new tablet_tool_input_t(); @@ -1542,24 +1551,22 @@ static void tablet_seat_tool_added(void *data, tool_input->cursor_surface = wl_compositor_create_surface(input->system->compositor()); wl_surface_add_listener(tool_input->cursor_surface, &cursor_surface_listener, (void *)input); - tool_input->data = GHOST_TABLET_DATA_NONE; - zwp_tablet_tool_v2_add_listener(id, &tablet_tool_listner, tool_input); input->tablet_tools.insert(id); } -static void tablet_seat_pad_added(void * /*data*/, - struct zwp_tablet_seat_v2 * /*zwp_tablet_seat_v2*/, - struct zwp_tablet_pad_v2 * /*id*/) +static void tablet_seat_handle_pad_added(void * /*data*/, + struct zwp_tablet_seat_v2 * /*zwp_tablet_seat_v2*/, + struct zwp_tablet_pad_v2 * /*id*/) { /* Pass. */ } const struct zwp_tablet_seat_v2_listener tablet_seat_listener = { - tablet_seat_tablet_added, - tablet_seat_tool_added, - tablet_seat_pad_added, + tablet_seat_handle_tablet_added, + tablet_seat_handle_tool_added, + tablet_seat_handle_pad_added, }; /** \} */ @@ -1568,7 +1575,7 @@ const struct zwp_tablet_seat_v2_listener tablet_seat_listener = { /** \name Listener (Keyboard), #wl_keyboard_listener * \{ */ -static void keyboard_keymap( +static void keyboard_handle_keymap( void *data, struct wl_keyboard * /*wl_keyboard*/, uint32_t format, int32_t fd, uint32_t size) { input_t *input = static_cast(data); @@ -1604,11 +1611,11 @@ static void keyboard_keymap( * Notification that this seat's keyboard focus is on a certain * surface. */ -static void keyboard_enter(void *data, - struct wl_keyboard * /*wl_keyboard*/, - uint32_t /*serial*/, - struct wl_surface *surface, - struct wl_array * /*keys*/) +static void keyboard_handle_enter(void *data, + struct wl_keyboard * /*wl_keyboard*/, + uint32_t /*serial*/, + struct wl_surface *surface, + struct wl_array * /*keys*/) { if (surface != nullptr) { static_cast(data)->focus_keyboard = surface; @@ -1621,10 +1628,10 @@ static void keyboard_enter(void *data, * Notification that this seat's keyboard focus is no longer on a * certain surface. */ -static void keyboard_leave(void *data, - struct wl_keyboard * /*wl_keyboard*/, - uint32_t /*serial*/, - struct wl_surface *surface) +static void keyboard_handle_leave(void *data, + struct wl_keyboard * /*wl_keyboard*/, + uint32_t /*serial*/, + struct wl_surface *surface) { if (surface != nullptr) { static_cast(data)->focus_keyboard = nullptr; @@ -1657,12 +1664,12 @@ static xkb_keysym_t xkb_state_key_get_one_sym_without_modifiers(struct xkb_state return sym; } -static void keyboard_key(void *data, - struct wl_keyboard * /*wl_keyboard*/, - uint32_t serial, - uint32_t /*time*/, - uint32_t key, - uint32_t state) +static void keyboard_handle_key(void *data, + struct wl_keyboard * /*wl_keyboard*/, + uint32_t serial, + uint32_t /*time*/, + uint32_t key, + uint32_t state) { input_t *input = static_cast(data); @@ -1720,7 +1727,7 @@ static void keyboard_key(void *data, .key_data = key_data, }); - auto cb = [](GHOST_ITimerTask *task, uint64_t /*time*/) { + auto key_repeat_fn = [](GHOST_ITimerTask *task, uint64_t /*time*/) { struct key_repeat_payload_t *payload = static_cast( task->getUserData()); payload->system->pushEvent(new GHOST_EventKey(payload->system->getMilliSeconds(), @@ -1732,17 +1739,17 @@ static void keyboard_key(void *data, true)); }; input->key_repeat.timer = input->system->installTimer( - input->key_repeat.delay, 1000 / input->key_repeat.rate, cb, payload); + input->key_repeat.delay, 1000 / input->key_repeat.rate, key_repeat_fn, payload); } } -static void keyboard_modifiers(void *data, - struct wl_keyboard * /*wl_keyboard*/, - uint32_t /*serial*/, - uint32_t mods_depressed, - uint32_t mods_latched, - uint32_t mods_locked, - uint32_t group) +static void keyboard_handle_modifiers(void *data, + struct wl_keyboard * /*wl_keyboard*/, + uint32_t /*serial*/, + uint32_t mods_depressed, + uint32_t mods_latched, + uint32_t mods_locked, + uint32_t group) { xkb_state_update_mask(static_cast(data)->xkb_state, mods_depressed, @@ -1753,10 +1760,10 @@ static void keyboard_modifiers(void *data, group); } -static void keyboard_repeat_info(void *data, - struct wl_keyboard * /*wl_keyboard*/, - int32_t rate, - int32_t delay) +static void keyboard_repeat_handle_info(void *data, + struct wl_keyboard * /*wl_keyboard*/, + int32_t rate, + int32_t delay) { input_t *input = static_cast(data); @@ -1765,12 +1772,12 @@ static void keyboard_repeat_info(void *data, } static const struct wl_keyboard_listener keyboard_listener = { - keyboard_keymap, - keyboard_enter, - keyboard_leave, - keyboard_key, - keyboard_modifiers, - keyboard_repeat_info, + keyboard_handle_keymap, + keyboard_handle_enter, + keyboard_handle_leave, + keyboard_handle_key, + keyboard_handle_modifiers, + keyboard_repeat_handle_info, }; /** \} */ @@ -1779,40 +1786,40 @@ static const struct wl_keyboard_listener keyboard_listener = { /** \name Listener (Seat), #wl_seat_listener * \{ */ -static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) +static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) { input_t *input = static_cast(data); - input->pointer = nullptr; - input->keyboard = nullptr; + input->wl_pointer = nullptr; + input->wl_keyboard = nullptr; if (capabilities & WL_SEAT_CAPABILITY_POINTER) { - input->pointer = wl_seat_get_pointer(wl_seat); - input->cursor.surface = wl_compositor_create_surface(input->system->compositor()); + input->wl_pointer = wl_seat_get_pointer(wl_seat); + input->cursor.wl_surface = wl_compositor_create_surface(input->system->compositor()); input->cursor.visible = true; - input->cursor.buffer = nullptr; + input->cursor.wl_buffer = nullptr; input->cursor.file_buffer = new buffer_t; if (!get_cursor_settings(input->cursor.theme_name, input->cursor.size)) { input->cursor.theme_name = std::string(); input->cursor.size = default_cursor_size; } - wl_pointer_add_listener(input->pointer, &pointer_listener, data); - wl_surface_add_listener(input->cursor.surface, &cursor_surface_listener, data); + wl_pointer_add_listener(input->wl_pointer, &pointer_listener, data); + wl_surface_add_listener(input->cursor.wl_surface, &cursor_surface_listener, data); } if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { - input->keyboard = wl_seat_get_keyboard(wl_seat); - wl_keyboard_add_listener(input->keyboard, &keyboard_listener, data); + input->wl_keyboard = wl_seat_get_keyboard(wl_seat); + wl_keyboard_add_listener(input->wl_keyboard, &keyboard_listener, data); } } -static void seat_name(void *data, struct wl_seat * /*wl_seat*/, const char *name) +static void seat_handle_name(void *data, struct wl_seat * /*wl_seat*/, const char *name) { static_cast(data)->name = std::string(name); } static const struct wl_seat_listener seat_listener = { - seat_capabilities, - seat_name, + seat_handle_capabilities, + seat_handle_name, }; /** \} */ @@ -1894,16 +1901,16 @@ static const struct zxdg_output_v1_listener xdg_output_listener = { /** \name Listener (Output), #wl_output_listener * \{ */ -static void output_geometry(void *data, - struct wl_output * /*wl_output*/, - int32_t /*x*/, - int32_t /*y*/, - int32_t physical_width, - int32_t physical_height, - int32_t /*subpixel*/, - const char *make, - const char *model, - int32_t transform) +static void output_handle_geometry(void *data, + struct wl_output * /*wl_output*/, + int32_t /*x*/, + int32_t /*y*/, + int32_t physical_width, + int32_t physical_height, + int32_t /*subpixel*/, + const char *make, + const char *model, + int32_t transform) { output_t *output = static_cast(data); output->transform = transform; @@ -1913,12 +1920,12 @@ static void output_geometry(void *data, output->size_mm[1] = physical_height; } -static void output_mode(void *data, - struct wl_output * /*wl_output*/, - uint32_t flags, - int32_t width, - int32_t height, - int32_t /*refresh*/) +static void output_handle_mode(void *data, + struct wl_output * /*wl_output*/, + uint32_t flags, + int32_t width, + int32_t height, + int32_t /*refresh*/) { output_t *output = static_cast(data); @@ -1943,7 +1950,7 @@ static void output_mode(void *data, * changes done after that. This allows changes to the output * properties to be seen as atomic, even if they happen via multiple events. */ -static void output_done(void *data, struct wl_output * /*wl_output*/) +static void output_handle_done(void *data, struct wl_output * /*wl_output*/) { output_t *output = static_cast(data); int32_t size_native[2]; @@ -1970,16 +1977,16 @@ static void output_done(void *data, struct wl_output * /*wl_output*/) } } -static void output_scale(void *data, struct wl_output * /*wl_output*/, int32_t factor) +static void output_handle_scale(void *data, struct wl_output * /*wl_output*/, int32_t factor) { static_cast(data)->scale = factor; } static const struct wl_output_listener output_listener = { - output_geometry, - output_mode, - output_done, - output_scale, + output_handle_geometry, + output_handle_mode, + output_handle_done, + output_handle_scale, }; /** \} */ @@ -1988,13 +1995,13 @@ static const struct wl_output_listener output_listener = { /** \name Listener (XDG WM Base), #xdg_wm_base_listener * \{ */ -static void shell_ping(void * /*data*/, struct xdg_wm_base *xdg_wm_base, uint32_t serial) +static void shell_handle_ping(void * /*data*/, struct xdg_wm_base *xdg_wm_base, uint32_t serial) { xdg_wm_base_pong(xdg_wm_base, serial); } static const struct xdg_wm_base_listener shell_listener = { - shell_ping, + shell_handle_ping, }; /** \} */ @@ -2003,11 +2010,11 @@ static const struct xdg_wm_base_listener shell_listener = { /** \name Listener (Registry), #wl_registry_listener * \{ */ -static void global_add(void *data, - struct wl_registry *wl_registry, - uint32_t name, - const char *interface, - uint32_t /*version*/) +static void global_handle_add(void *data, + struct wl_registry *wl_registry, + uint32_t name, + const char *interface, + uint32_t /*version*/) { struct display_t *display = static_cast(data); if (!strcmp(interface, wl_compositor_interface.name)) { @@ -2028,28 +2035,20 @@ static void global_add(void *data, wl_registry_bind(wl_registry, name, &zxdg_output_manager_v1_interface, 3)); for (output_t *output : display->outputs) { output->xdg_output = zxdg_output_manager_v1_get_xdg_output(display->xdg_output_manager, - output->output); + output->wl_output); zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output); } } else if (!strcmp(interface, wl_output_interface.name)) { output_t *output = new output_t; - - output->scale = 1; - output->has_scale_fractional = false; - output->scale_fractional = wl_fixed_from_int(1); - - output->has_size_logical = false; - output->has_position_logical = false; - - output->output = static_cast( + output->wl_output = static_cast( wl_registry_bind(wl_registry, name, &wl_output_interface, 2)); display->outputs.push_back(output); - wl_output_add_listener(output->output, &output_listener, output); + wl_output_add_listener(output->wl_output, &output_listener, output); if (display->xdg_output_manager) { output->xdg_output = zxdg_output_manager_v1_get_xdg_output(display->xdg_output_manager, - output->output); + output->wl_output); zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output); } } @@ -2057,19 +2056,11 @@ static void global_add(void *data, input_t *input = new input_t; input->system = display->system; input->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - input->xkb_state = nullptr; - input->data_offer_dnd = nullptr; - input->data_offer_copy_paste = nullptr; input->data_source = new data_source_t; - input->data_source->data_source = nullptr; - input->data_source->buffer_out = nullptr; - input->relative_pointer = nullptr; - input->locked_pointer = nullptr; - input->confined_pointer = nullptr; - input->seat = static_cast( + input->wl_seat = static_cast( wl_registry_bind(wl_registry, name, &wl_seat_interface, 4)); display->inputs.push_back(input); - wl_seat_add_listener(input->seat, &seat_listener, input); + wl_seat_add_listener(input->wl_seat, &seat_listener, input); } else if (!strcmp(interface, wl_shm_interface.name)) { display->shm = static_cast( @@ -2102,13 +2093,15 @@ static void global_add(void *data, * name is no longer available. If the client bound to the global * using the bind request, the client should now destroy that object. */ -static void global_remove(void * /*data*/, struct wl_registry * /*wl_registry*/, uint32_t /*name*/) +static void global_handle_remove(void * /*data*/, + struct wl_registry * /*wl_registry*/, + uint32_t /*name*/) { } static const struct wl_registry_listener registry_listener = { - global_add, - global_remove, + global_handle_add, + global_handle_remove, }; /** \} */ @@ -2149,14 +2142,15 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new display_t) if (d->data_device_manager) { for (input_t *input : d->inputs) { input->data_device = wl_data_device_manager_get_data_device(d->data_device_manager, - input->seat); + input->wl_seat); wl_data_device_add_listener(input->data_device, &data_device_listener, input); } } if (d->tablet_manager) { for (input_t *input : d->inputs) { - input->tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(d->tablet_manager, input->seat); + input->tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(d->tablet_manager, + input->wl_seat); zwp_tablet_seat_v2_add_listener(input->tablet_seat, &tablet_seat_listener, input); } } @@ -2435,12 +2429,12 @@ wl_compositor *GHOST_SystemWayland::compositor() return d->compositor; } -xdg_wm_base *GHOST_SystemWayland::shell() +xdg_wm_base *GHOST_SystemWayland::xdg_shell() { return d->xdg_shell; } -zxdg_decoration_manager_v1 *GHOST_SystemWayland::decoration_manager() +zxdg_decoration_manager_v1 *GHOST_SystemWayland::xdg_decoration_manager() { return d->xdg_decoration_manager; } @@ -2466,22 +2460,22 @@ static void set_cursor_buffer(input_t *input, wl_buffer *buffer) c->visible = (buffer != nullptr); - const int32_t image_size_x = int32_t(c->image.width); - const int32_t image_size_y = int32_t(c->image.height); + const int32_t image_size_x = int32_t(c->wl_image.width); + const int32_t image_size_y = int32_t(c->wl_image.height); - const int32_t hotspot_x = int32_t(c->image.hotspot_x) / c->scale; - const int32_t hotspot_y = int32_t(c->image.hotspot_y) / c->scale; + const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / c->scale; + const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / c->scale; - wl_surface_attach(c->surface, buffer, 0, 0); - wl_surface_damage(c->surface, 0, 0, image_size_x, image_size_y); + wl_surface_attach(c->wl_surface, buffer, 0, 0); + wl_surface_damage(c->wl_surface, 0, 0, image_size_x, image_size_y); - wl_pointer_set_cursor(input->pointer, + wl_pointer_set_cursor(input->wl_pointer, input->pointer_serial, - c->visible ? c->surface : nullptr, + c->visible ? c->wl_surface : nullptr, hotspot_x, hotspot_y); - wl_surface_commit(c->surface); + wl_surface_commit(c->wl_surface); /* Set the cursor for all tablet tools as well. */ for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : input->tablet_tools) { @@ -2514,12 +2508,13 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape) input_t *input = d->inputs[0]; cursor_t *c = &input->cursor; - if (!c->theme) { + if (!c->wl_theme) { /* The cursor surface hasn't entered an output yet. Initialize theme with scale 1. */ - c->theme = wl_cursor_theme_load(c->theme_name.c_str(), c->size, d->inputs[0]->system->shm()); + c->wl_theme = wl_cursor_theme_load( + c->theme_name.c_str(), c->size, d->inputs[0]->system->shm()); } - wl_cursor *cursor = wl_cursor_theme_get_cursor(c->theme, cursor_name.c_str()); + wl_cursor *cursor = wl_cursor_theme_get_cursor(c->wl_theme, cursor_name.c_str()); if (!cursor) { GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl); @@ -2532,8 +2527,8 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape) return GHOST_kFailure; } - c->buffer = buffer; - c->image = *image; + c->wl_buffer = buffer; + c->wl_image = *image; set_cursor_buffer(input, buffer); @@ -2639,11 +2634,11 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap, } } - cursor->buffer = buffer; - cursor->image.width = uint32_t(sizex); - cursor->image.height = uint32_t(sizey); - cursor->image.hotspot_x = uint32_t(hotX); - cursor->image.hotspot_y = uint32_t(hotY); + cursor->wl_buffer = buffer; + cursor->wl_image.width = uint32_t(sizex); + cursor->wl_image.height = uint32_t(sizey); + cursor->wl_image.hotspot_x = uint32_t(hotX); + cursor->wl_image.hotspot_y = uint32_t(hotY); set_cursor_buffer(d->inputs[0], buffer); @@ -2661,7 +2656,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(bool visible) cursor_t *cursor = &input->cursor; if (visible) { if (!cursor->visible) { - set_cursor_buffer(input, cursor->buffer); + set_cursor_buffer(input, cursor->wl_buffer); } } else { @@ -2680,7 +2675,6 @@ bool GHOST_SystemWayland::supportsCursorWarp() GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mode, const GHOST_TGrabCursorMode mode_current, - wl_surface *surface) { /* ignore, if the required protocols are not supported */ @@ -2787,13 +2781,13 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo * An alternative could be to draw the cursor in software (and hide the real cursor), * or just accept a locked cursor on WAYLAND. */ input->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer( - d->relative_pointer_manager, input->pointer); + d->relative_pointer_manager, input->wl_pointer); zwp_relative_pointer_v1_add_listener( input->relative_pointer, &relative_pointer_listener, input); input->locked_pointer = zwp_pointer_constraints_v1_lock_pointer( d->pointer_constraints, surface, - input->pointer, + input->wl_pointer, nullptr, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); } @@ -2803,7 +2797,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo input->confined_pointer = zwp_pointer_constraints_v1_confine_pointer( d->pointer_constraints, surface, - input->pointer, + input->wl_pointer, nullptr, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); } -- cgit v1.2.3 From 66483c58ebff87805a71f98950bfac83d5c94fdb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 15 Jun 2022 17:51:46 +1000 Subject: Cleanup: avoid static_cast when accessing wayland windows Rename get_window to window_from_surface and return a GHOST_WindowWayland instead of an GHOST_IWindow since most callers needed to cast. It also makes sense that an call for accessing windows would return the native type. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 68 ++++++++++++----------------- 1 file changed, 28 insertions(+), 40 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 3d176bdb2f6..635c5bef50e 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -42,7 +42,7 @@ #include #include -static GHOST_IWindow *get_window(struct wl_surface *surface); +static GHOST_WindowWayland *window_from_surface(struct wl_surface *surface); /* -------------------------------------------------------------------- */ /** \name Private Types & Defines @@ -564,7 +564,7 @@ static void relative_pointer_handle_relative_motion( wl_fixed_t /*dy_unaccel*/) { input_t *input = static_cast(data); - GHOST_WindowWayland *win = static_cast(get_window(input->focus_pointer)); + GHOST_WindowWayland *win = window_from_surface(input->focus_pointer); if (win == nullptr) { return; } @@ -863,7 +863,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat static constexpr const char *file_proto = "file://"; static constexpr const char *crlf = "\r\n"; - GHOST_WindowWayland *win = static_cast(get_window(surface)); + GHOST_WindowWayland *win = window_from_surface(surface); GHOST_ASSERT(win != nullptr, "Unable to find window for drop event from surface"); std::vector uris; @@ -999,15 +999,14 @@ const struct wl_buffer_listener cursor_buffer_listener = { /** \name Listener (Surface), #wl_surface_listener * \{ */ -static GHOST_IWindow *get_window(struct wl_surface *surface) +static GHOST_WindowWayland *window_from_surface(struct wl_surface *surface) { - if (!surface) { - return nullptr; - } - - for (GHOST_IWindow *win : window_manager->getWindows()) { - if (surface == static_cast(win)->surface()) { - return win; + if (surface) { + for (GHOST_IWindow *iwin : window_manager->getWindows()) { + GHOST_WindowWayland *win = static_cast(iwin); + if (surface == win->surface()) { + return win; + } } } return nullptr; @@ -1076,8 +1075,7 @@ static void pointer_handle_enter(void *data, wl_fixed_t surface_x, wl_fixed_t surface_y) { - GHOST_WindowWayland *win = static_cast(get_window(surface)); - + GHOST_WindowWayland *win = window_from_surface(surface); if (!win) { return; } @@ -1107,8 +1105,7 @@ static void pointer_handle_leave(void *data, uint32_t /*serial*/, struct wl_surface *surface) { - GHOST_IWindow *win = get_window(surface); - + GHOST_IWindow *win = window_from_surface(surface); if (!win) { return; } @@ -1124,9 +1121,7 @@ static void pointer_handle_motion(void *data, wl_fixed_t surface_y) { input_t *input = static_cast(data); - - GHOST_WindowWayland *win = static_cast(get_window(input->focus_pointer)); - + GHOST_WindowWayland *win = window_from_surface(input->focus_pointer); if (!win) { return; } @@ -1151,9 +1146,7 @@ static void pointer_handle_button(void *data, uint32_t state) { input_t *input = static_cast(data); - - GHOST_IWindow *win = get_window(input->focus_pointer); - + GHOST_IWindow *win = window_from_surface(input->focus_pointer); if (!win) { return; } @@ -1206,9 +1199,7 @@ static void pointer_handle_axis(void *data, wl_fixed_t value) { input_t *input = static_cast(data); - - GHOST_IWindow *win = get_window(input->focus_pointer); - + GHOST_IWindow *win = window_from_surface(input->focus_pointer); if (!win) { return; } @@ -1297,7 +1288,7 @@ static void tablet_tool_handle_proximity_in(void *data, input->data_source_serial = serial; /* Update #GHOST_TabletData. */ - GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + GHOST_WindowWayland *win = window_from_surface(input->focus_tablet); if (!win) { return; } @@ -1318,7 +1309,7 @@ static void tablet_tool_handle_proximity_out(void *data, { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; - GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + GHOST_WindowWayland *win = window_from_surface(input->focus_tablet); input->focus_tablet = nullptr; @@ -1331,8 +1322,7 @@ static void tablet_tool_handle_down(void *data, { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; - - GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + GHOST_WindowWayland *win = window_from_surface(input->focus_tablet); if (!win) { return; } @@ -1349,11 +1339,11 @@ static void tablet_tool_handle_up(void *data, struct zwp_tablet_tool_v2 * /*zwp_ { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; - - GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + GHOST_WindowWayland *win = window_from_surface(input->focus_tablet); if (!win) { return; } + const GHOST_TEventType etype = GHOST_kEventButtonUp; const GHOST_TButtonMask ebutton = GHOST_kButtonMaskLeft; input->buttons.set(ebutton, false); @@ -1368,8 +1358,7 @@ static void tablet_tool_handle_motion(void *data, { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; - - GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + GHOST_WindowWayland *win = window_from_surface(input->focus_tablet); if (!win) { return; } @@ -1392,11 +1381,11 @@ static void tablet_tool_handle_pressure(void *data, { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; - - GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + GHOST_WindowWayland *win = window_from_surface(input->focus_tablet); if (!win) { return; } + GHOST_TabletData &td = tool_input->data; td.Pressure = (float)pressure / 65535; } @@ -1412,8 +1401,7 @@ static void tablet_tool_handle_tilt(void *data, { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; - - GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + GHOST_WindowWayland *win = window_from_surface(input->focus_tablet); if (!win) { return; } @@ -1450,11 +1438,11 @@ static void tablet_tool_handle_wheel(void *data, tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; - - GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + GHOST_WindowWayland *win = window_from_surface(input->focus_tablet); if (!win) { return; } + input->system->pushEvent(new GHOST_EventWheel(input->system->getMilliSeconds(), win, clicks)); } static void tablet_tool_handle_button(void *data, @@ -1465,7 +1453,7 @@ static void tablet_tool_handle_button(void *data, { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; - GHOST_WindowWayland *win = static_cast(get_window(input->focus_tablet)); + GHOST_WindowWayland *win = window_from_surface(input->focus_tablet); if (!win) { return; } @@ -2726,7 +2714,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo if (input->locked_pointer) { /* Request location to restore to. */ if (mode_current == GHOST_kGrabWrap) { - GHOST_WindowWayland *win = static_cast(get_window(surface)); + GHOST_WindowWayland *win = window_from_surface(surface); GHOST_Rect bounds; int32_t xy_new[2] = {input->xy[0], input->xy[1]}; -- cgit v1.2.3 From fc79b17dced91c6b5626b557f9255bb15cd45ccc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 15 Jun 2022 18:12:09 +1000 Subject: GHOST/Wayland: add NULL pointer checks on window access There were a few callers that missed checking a NULL return value which can happen in rare cases. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 87 ++++++++++++++++------------- 1 file changed, 47 insertions(+), 40 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 635c5bef50e..4ecaf2bed44 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -565,7 +565,7 @@ static void relative_pointer_handle_relative_motion( { input_t *input = static_cast(data); GHOST_WindowWayland *win = window_from_surface(input->focus_pointer); - if (win == nullptr) { + if (!win) { return; } const wl_fixed_t scale = win->scale(); @@ -1288,13 +1288,6 @@ static void tablet_tool_handle_proximity_in(void *data, input->data_source_serial = serial; /* Update #GHOST_TabletData. */ - GHOST_WindowWayland *win = window_from_surface(input->focus_tablet); - if (!win) { - return; - } - - win->activate(); - GHOST_TabletData &td = tool_input->data; /* Reset, to avoid using stale tilt/pressure. */ td.Xtilt = 0.0f; @@ -1302,6 +1295,12 @@ static void tablet_tool_handle_proximity_in(void *data, /* In case pressure isn't supported. */ td.Pressure = 1.0f; + GHOST_WindowWayland *win = window_from_surface(input->focus_tablet); + if (!win) { + return; + } + win->activate(); + win->setCursorShape(win->getCursorShape()); } static void tablet_tool_handle_proximity_out(void *data, @@ -1309,10 +1308,12 @@ static void tablet_tool_handle_proximity_out(void *data, { tablet_tool_input_t *tool_input = static_cast(data); input_t *input = tool_input->input; - GHOST_WindowWayland *win = window_from_surface(input->focus_tablet); - input->focus_tablet = nullptr; + GHOST_WindowWayland *win = window_from_surface(input->focus_tablet); + if (!win) { + return; + } win->setCursorShape(win->getCursorShape()); } @@ -2714,39 +2715,45 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo if (input->locked_pointer) { /* Request location to restore to. */ if (mode_current == GHOST_kGrabWrap) { + /* The chance this fails is _very_ low. */ GHOST_WindowWayland *win = window_from_surface(surface); - GHOST_Rect bounds; - int32_t xy_new[2] = {input->xy[0], input->xy[1]}; - - /* Fallback to window bounds. */ - if (win->getCursorGrabBounds(bounds) == GHOST_kFailure) { - win->getClientBounds(bounds); + if (!win) { + GHOST_PRINT("could not find window from surface when un-grabbing!" << std::endl); } - - const int scale = win->scale(); - - bounds.m_l = wl_fixed_from_int(bounds.m_l) / scale; - bounds.m_t = wl_fixed_from_int(bounds.m_t) / scale; - bounds.m_r = wl_fixed_from_int(bounds.m_r) / scale; - bounds.m_b = wl_fixed_from_int(bounds.m_b) / scale; - - bounds.wrapPoint(xy_new[0], xy_new[1], 0, win->getCursorGrabAxis()); - - /* Push an event so the new location is registered. */ - if ((xy_new[0] != input->xy[0]) || (xy_new[1] != input->xy[1])) { - input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(), - GHOST_kEventCursorMove, - win, - wl_fixed_to_int(scale * xy_new[0]), - wl_fixed_to_int(scale * xy_new[1]), - GHOST_TABLET_DATA_NONE)); + else { + GHOST_Rect bounds; + int32_t xy_new[2] = {input->xy[0], input->xy[1]}; + + /* Fallback to window bounds. */ + if (win->getCursorGrabBounds(bounds) == GHOST_kFailure) { + win->getClientBounds(bounds); + } + + const int scale = win->scale(); + + bounds.m_l = wl_fixed_from_int(bounds.m_l) / scale; + bounds.m_t = wl_fixed_from_int(bounds.m_t) / scale; + bounds.m_r = wl_fixed_from_int(bounds.m_r) / scale; + bounds.m_b = wl_fixed_from_int(bounds.m_b) / scale; + + bounds.wrapPoint(xy_new[0], xy_new[1], 0, win->getCursorGrabAxis()); + + /* Push an event so the new location is registered. */ + if ((xy_new[0] != input->xy[0]) || (xy_new[1] != input->xy[1])) { + input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(), + GHOST_kEventCursorMove, + win, + wl_fixed_to_int(scale * xy_new[0]), + wl_fixed_to_int(scale * xy_new[1]), + GHOST_TABLET_DATA_NONE)); + } + input->xy[0] = xy_new[0]; + input->xy[1] = xy_new[1]; + + zwp_locked_pointer_v1_set_cursor_position_hint( + input->locked_pointer, xy_new[0], xy_new[1]); + wl_surface_commit(surface); } - input->xy[0] = xy_new[0]; - input->xy[1] = xy_new[1]; - - zwp_locked_pointer_v1_set_cursor_position_hint( - input->locked_pointer, xy_new[0], xy_new[1]); - wl_surface_commit(surface); } zwp_locked_pointer_v1_destroy(input->locked_pointer); -- cgit v1.2.3 From e550e400cd9c5fa549e9b69b191a296803dcb31b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 15 Jun 2022 19:25:20 +1000 Subject: Cleanup: internalize struct members for internal wayland types Missed from 9978689595f87a6b4d8244ee3d014c8fb239e38d. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 4ecaf2bed44..5fe1b68543a 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -120,17 +120,17 @@ struct data_source_t { }; struct key_repeat_payload_t { - GHOST_SystemWayland *system; - GHOST_IWindow *window; - GHOST_TKey key; - GHOST_TEventKeyData key_data; + GHOST_SystemWayland *system = nullptr; + GHOST_IWindow *window = nullptr; + GHOST_TKey key = GHOST_kKeyUnknown; + GHOST_TEventKeyData key_data = {GHOST_kKeyUnknown}; }; struct input_t { - GHOST_SystemWayland *system; + GHOST_SystemWayland *system = nullptr; std::string name; - struct wl_seat *wl_seat; + struct wl_seat *wl_seat = nullptr; struct wl_pointer *wl_pointer = nullptr; struct wl_keyboard *wl_keyboard = nullptr; struct zwp_tablet_seat_v2 *tablet_seat = nullptr; @@ -138,11 +138,11 @@ struct input_t { /** All currently active tablet tools (needed for changing the cursor). */ std::unordered_set tablet_tools; - uint32_t pointer_serial; - uint32_t tablet_serial; + uint32_t pointer_serial = 0; + uint32_t tablet_serial = 0; /** Use to check if the last cursor input was tablet or pointer. */ - uint32_t cursor_serial; + uint32_t cursor_serial = 0; /** * High precision mouse coordinates (pointer or tablet). @@ -156,7 +156,7 @@ struct input_t { * }; * \endocde */ - wl_fixed_t xy[2]; + wl_fixed_t xy[2] = {0, 0}; GHOST_Buttons buttons = GHOST_Buttons(); struct cursor_t cursor; @@ -168,9 +168,9 @@ struct input_t { struct xkb_state *xkb_state = nullptr; struct { /** Key repetition in character per second. */ - int32_t rate; + int32_t rate = 0; /** Time (milliseconds) after which to start repeating keys. */ - int32_t delay; + int32_t delay = 0; /** Timer for key repeats. */ GHOST_ITimerTask *timer = nullptr; } key_repeat; @@ -193,7 +193,7 @@ struct input_t { std::mutex data_source_mutex; /** Last device that was active. */ - uint32_t data_source_serial; + uint32_t data_source_serial = 0; }; struct display_t { -- cgit v1.2.3 From 7cc8f2743e0d21ceb4dc21af0ffbcbed89222428 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 15 Jun 2022 19:32:17 +1000 Subject: Cleanup: remove redundant key entry from key_repeat_payload_t --- intern/ghost/intern/GHOST_SystemWayland.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 5fe1b68543a..b59adef1724 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -122,7 +122,6 @@ struct data_source_t { struct key_repeat_payload_t { GHOST_SystemWayland *system = nullptr; GHOST_IWindow *window = nullptr; - GHOST_TKey key = GHOST_kKeyUnknown; GHOST_TEventKeyData key_data = {GHOST_kKeyUnknown}; }; @@ -1677,7 +1676,6 @@ static void keyboard_handle_key(void *data, if (sym == XKB_KEY_NoSymbol) { return; } - const GHOST_TKey gkey = xkb_map_gkey(sym); /* Delete previous timer. */ if (xkb_keymap_key_repeats(xkb_state_get_keymap(input->xkb_state), key + 8) && @@ -1687,7 +1685,9 @@ static void keyboard_handle_key(void *data, input->key_repeat.timer = nullptr; } - GHOST_TEventKeyData key_data; + GHOST_TEventKeyData key_data = { + .key = xkb_map_gkey(sym), + }; if (etype == GHOST_kEventKeyDown) { xkb_state_key_get_utf8( @@ -1702,7 +1702,7 @@ static void keyboard_handle_key(void *data, GHOST_IWindow *win = static_cast( wl_surface_get_user_data(input->focus_keyboard)); input->system->pushEvent(new GHOST_EventKey( - input->system->getMilliSeconds(), etype, win, gkey, '\0', key_data.utf8_buf, false)); + input->system->getMilliSeconds(), etype, win, key_data.key, '\0', key_data.utf8_buf, false)); /* Start timer for repeating key, if applicable. */ if (input->key_repeat.rate > 0 && @@ -1712,7 +1712,6 @@ static void keyboard_handle_key(void *data, key_repeat_payload_t *payload = new key_repeat_payload_t({ .system = input->system, .window = win, - .key = gkey, .key_data = key_data, }); @@ -1722,7 +1721,7 @@ static void keyboard_handle_key(void *data, payload->system->pushEvent(new GHOST_EventKey(payload->system->getMilliSeconds(), GHOST_kEventKeyDown, payload->window, - payload->key, + payload->key_data.key, '\0', payload->key_data.utf8_buf, true)); -- cgit v1.2.3 From 409c62aa6182a691cd0fa4734b3a4d6192d9bf64 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 16 Jun 2022 12:29:20 +1000 Subject: Fix missing free for drag & drop data with GHOST/Wayland --- intern/ghost/intern/GHOST_SystemWayland.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index b59adef1724..15aa379c531 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -270,6 +270,10 @@ static void display_destroy(display_t *d) } delete input->data_source; } + if (input->data_offer_dnd) { + wl_data_offer_destroy(input->data_offer_dnd->id); + delete input->data_offer_dnd; + } if (input->data_offer_copy_paste) { wl_data_offer_destroy(input->data_offer_copy_paste->id); delete input->data_offer_copy_paste; -- cgit v1.2.3 From 1fed24de5a38c2133439e78cedc27d265962f90a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 16 Jun 2022 12:29:22 +1000 Subject: GHOST/Wayland: acquire locks before freeing data on exit --- intern/ghost/intern/GHOST_SystemWayland.cpp | 37 ++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 15aa379c531..cf5ba550e55 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -263,21 +263,36 @@ static void display_destroy(display_t *d) } for (input_t *input : d->inputs) { - if (input->data_source) { - free(input->data_source->buffer_out); - if (input->data_source->data_source) { - wl_data_source_destroy(input->data_source->data_source); + + /* First handle members that require locking. + * While highly unlikely, it's possible they are being used while this function runs. */ + { + std::lock_guard lock{input->data_source_mutex}; + if (input->data_source) { + free(input->data_source->buffer_out); + if (input->data_source->data_source) { + wl_data_source_destroy(input->data_source->data_source); + } + delete input->data_source; } - delete input->data_source; } - if (input->data_offer_dnd) { - wl_data_offer_destroy(input->data_offer_dnd->id); - delete input->data_offer_dnd; + + { + std::lock_guard lock{input->data_offer_dnd_mutex}; + if (input->data_offer_dnd) { + wl_data_offer_destroy(input->data_offer_dnd->id); + delete input->data_offer_dnd; + } } - if (input->data_offer_copy_paste) { - wl_data_offer_destroy(input->data_offer_copy_paste->id); - delete input->data_offer_copy_paste; + + { + std::lock_guard lock{input->data_offer_copy_paste_mutex}; + if (input->data_offer_copy_paste) { + wl_data_offer_destroy(input->data_offer_copy_paste->id); + delete input->data_offer_copy_paste; + } } + if (input->data_device) { wl_data_device_release(input->data_device); } -- cgit v1.2.3 From a17f74ab341b026387fef6b741e3c0901780526c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 16 Jun 2022 14:55:37 +1000 Subject: Fix memory leak plugging in new keyboards in wayland --- intern/ghost/intern/GHOST_SystemWayland.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index cf5ba550e55..93d85f33dda 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1607,8 +1607,13 @@ static void keyboard_handle_keymap( return; } - input->xkb_state = xkb_state_new(keymap); - + struct xkb_state *xkb_state_next = xkb_state_new(keymap); + if (xkb_state_next) { + if (input->xkb_state) { + xkb_state_unref(input->xkb_state); + } + input->xkb_state = xkb_state_next; + } xkb_keymap_unref(keymap); } -- cgit v1.2.3 From 65b1b1cd349f3bd813392e76eab5b610efba7428 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 16 Jun 2022 15:16:04 +1000 Subject: GHOST/Wayland: workaround inability to access window position Wayland doesn't support accessing the position making functionality that would map events to other windows fail, sometimes considering windows overlapping when they weren't (as all window positions were zeroed). Disable dragging between windows when accessing the window the position isn't supported. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 93d85f33dda..d8fbe875f67 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -2682,6 +2682,14 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(bool visible) bool GHOST_SystemWayland::supportsCursorWarp() { + /* WAYLAND doesn't support setting the cursor position directly, + * this is an intentional choice, forcing us to use a software cursor in this case. */ + return false; +} + +bool GHOST_SystemWayland::supportsWindowPosition() +{ + /* WAYLAND doesn't support accessing the window position. */ return false; } -- cgit v1.2.3 From 62346abc022c2c5b39e4535e7b5786c045a44457 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 17 Jun 2022 07:33:06 +1000 Subject: Cleanup: spelling in comments --- intern/ghost/intern/GHOST_SystemWayland.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index d8fbe875f67..4b5fa2bf3fb 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -153,7 +153,7 @@ struct input_t { * wl_fixed_to_int(scale * input->xy[0]), * wl_fixed_to_int(scale * input->xy[1]), * }; - * \endocde + * \endcode */ wl_fixed_t xy[2] = {0, 0}; GHOST_Buttons buttons = GHOST_Buttons(); @@ -1860,14 +1860,12 @@ static void xdg_output_handle_logical_size(void *data, if (output->size_logical[0] != 0 && output->size_logical[1] != 0) { /* Original comment from SDL. */ - /* FIXME: GNOME has a bug where the logical size does not account for + /* FIXME(@flibit): GNOME has a bug where the logical size does not account for * scale, resulting in bogus viewport sizes. * * Until this is fixed, validate that _some_ kind of scaling is being * done (we can't match exactly because fractional scaling can't be - * detected otherwise), then override if necessary. - * -flibit - */ + * detected otherwise), then override if necessary. */ if ((output->size_logical[0] == width) && (output->scale_fractional == wl_fixed_from_int(1))) { GHOST_PRINT("xdg_output scale did not match, overriding with wl_output scale"); return; -- cgit v1.2.3 From 9830603620762b5784983dddc076bc7945dc1e16 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 17 Jun 2022 17:35:27 +1000 Subject: GHOST/Wayland: skip cursor surface operations when hiding the cursor Also set the buffer scale before setting the cursor (matching SDL). --- intern/ghost/intern/GHOST_SystemWayland.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp') diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 4b5fa2bf3fb..2b0abd2cc41 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -2476,8 +2476,12 @@ static void set_cursor_buffer(input_t *input, wl_buffer *buffer) const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / c->scale; const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / c->scale; - wl_surface_attach(c->wl_surface, buffer, 0, 0); - wl_surface_damage(c->wl_surface, 0, 0, image_size_x, image_size_y); + if (buffer) { + wl_surface_set_buffer_scale(c->wl_surface, c->scale); + wl_surface_attach(c->wl_surface, buffer, 0, 0); + wl_surface_damage(c->wl_surface, 0, 0, image_size_x, image_size_y); + wl_surface_commit(c->wl_surface); + } wl_pointer_set_cursor(input->wl_pointer, input->pointer_serial, @@ -2485,25 +2489,25 @@ static void set_cursor_buffer(input_t *input, wl_buffer *buffer) hotspot_x, hotspot_y); - wl_surface_commit(c->wl_surface); - /* Set the cursor for all tablet tools as well. */ for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : input->tablet_tools) { tablet_tool_input_t *tool_input = static_cast( zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2)); - /* FIXME: for some reason cursor scale is applied twice (when the scale isn't 1x), - * this happens both in gnome-shell & KDE. Setting the surface scale here doesn't help. */ - // wl_surface_set_buffer_scale(tool_input->cursor_surface, 1); - wl_surface_attach(tool_input->cursor_surface, buffer, 0, 0); - wl_surface_damage(tool_input->cursor_surface, 0, 0, image_size_x, image_size_y); + + if (buffer) { + /* FIXME: for some reason cursor scale is applied twice (when the scale isn't 1x), + * this happens both in gnome-shell & KDE. Setting the surface scale here doesn't help. */ + wl_surface_set_buffer_scale(tool_input->cursor_surface, c->scale); + wl_surface_attach(tool_input->cursor_surface, buffer, 0, 0); + wl_surface_damage(tool_input->cursor_surface, 0, 0, image_size_x, image_size_y); + wl_surface_commit(tool_input->cursor_surface); + } zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2, input->tablet_serial, c->visible ? tool_input->cursor_surface : nullptr, hotspot_x, hotspot_y); - - wl_surface_commit(tool_input->cursor_surface); } } -- cgit v1.2.3