diff options
author | Campbell Barton <campbell@blender.org> | 2022-07-09 15:27:34 +0300 |
---|---|---|
committer | Campbell Barton <campbell@blender.org> | 2022-07-09 15:46:53 +0300 |
commit | 443690604f4ed5bdcf05cca40c8d6f1f88a1c29a (patch) | |
tree | e9f3f129112b4df4dc9ac4e7a296e2e88741d10d /intern | |
parent | 1de14061cbe33dd39ee48c65b609d550cac157ca (diff) |
Fix cursor display size with tablet input in GHOST/Wayland
The scale for tablet cursor surfaces was never set, making them display
larger. Now the outputs scale is set for mouse & tablet cursors.
Diffstat (limited to 'intern')
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWayland.cpp | 191 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWayland.h | 6 |
2 files changed, 133 insertions, 64 deletions
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 4b390615435..876f77732c2 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -146,10 +146,7 @@ struct cursor_t { size_t custom_data_size = 0; int size = 0; std::string theme_name; - /** Outputs on which the cursor is visible. */ - std::unordered_set<const output_t *> outputs; - int theme_scale = 1; int custom_scale = 1; }; @@ -231,6 +228,11 @@ struct input_state_pointer_t { */ wl_fixed_t xy[2] = {0, 0}; + /** Outputs on which the cursor is visible. */ + std::unordered_set<const output_t *> outputs; + + int theme_scale = 1; + /** The serial of the last used pointer or tablet. */ uint32_t serial = 0; @@ -396,6 +398,19 @@ static input_state_pointer_t *input_state_pointer_active(input_t *input) return nullptr; } +static input_state_pointer_t *input_state_pointer_from_cursor_surface(input_t *input, + const wl_surface *wl_surface) +{ + if (ghost_wl_surface_own_cursor_pointer(wl_surface)) { + return &input->pointer; + } + if (ghost_wl_surface_own_cursor_tablet(wl_surface)) { + return &input->tablet; + } + GHOST_ASSERT(0, "Surface found without pointer/tablet tag"); + return nullptr; +} + static void display_destroy(display_t *d) { if (d->data_device_manager) { @@ -1358,19 +1373,22 @@ static const struct wl_buffer_listener cursor_buffer_listener = { static CLG_LogRef LOG_WL_CURSOR_SURFACE = {"ghost.wl.handle.cursor_surface"}; #define LOG (&LOG_WL_CURSOR_SURFACE) -static bool update_cursor_scale(cursor_t &cursor, wl_shm *shm) +static bool update_cursor_scale(cursor_t &cursor, + wl_shm *shm, + input_state_pointer_t *input_state, + wl_surface *cursor_surface) { int scale = 0; - for (const output_t *output : cursor.outputs) { + for (const output_t *output : input_state->outputs) { if (output->scale > scale) { scale = output->scale; } } - if (scale > 0 && cursor.theme_scale != scale) { - cursor.theme_scale = scale; + if (scale > 0 && input_state->theme_scale != scale) { + input_state->theme_scale = scale; if (!cursor.is_custom) { - wl_surface_set_buffer_scale(cursor.wl_surface, scale); + wl_surface_set_buffer_scale(cursor_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); @@ -1380,7 +1398,7 @@ static bool update_cursor_scale(cursor_t &cursor, wl_shm *shm) } static void cursor_surface_handle_enter(void *data, - struct wl_surface * /*wl_surface*/, + struct wl_surface *wl_surface, struct wl_output *output) { if (!ghost_wl_output_own(output)) { @@ -1390,13 +1408,14 @@ static void cursor_surface_handle_enter(void *data, CLOG_INFO(LOG, 2, "handle_enter"); input_t *input = static_cast<input_t *>(data); + input_state_pointer_t *input_state = input_state_pointer_from_cursor_surface(input, wl_surface); const output_t *reg_output = ghost_wl_output_user_data(output); - input->cursor.outputs.insert(reg_output); - update_cursor_scale(input->cursor, input->system->shm()); + input_state->outputs.insert(reg_output); + update_cursor_scale(input->cursor, input->system->shm(), input_state, wl_surface); } static void cursor_surface_handle_leave(void *data, - struct wl_surface * /*wl_surface*/, + struct wl_surface *wl_surface, struct wl_output *output) { if (!(output && ghost_wl_output_own(output))) { @@ -1406,9 +1425,10 @@ static void cursor_surface_handle_leave(void *data, CLOG_INFO(LOG, 2, "handle_leave"); input_t *input = static_cast<input_t *>(data); + input_state_pointer_t *input_state = input_state_pointer_from_cursor_surface(input, wl_surface); const output_t *reg_output = ghost_wl_output_user_data(output); - input->cursor.outputs.erase(reg_output); - update_cursor_scale(input->cursor, input->system->shm()); + input_state->outputs.erase(reg_output); + update_cursor_scale(input->cursor, input->system->shm(), input_state, wl_surface); } static const struct wl_surface_listener cursor_surface_listener = { @@ -1952,6 +1972,8 @@ static void tablet_seat_handle_tool_added(void *data, /* Every tool has it's own cursor surface. */ tool_input->cursor_surface = wl_compositor_create_surface(input->system->compositor()); + ghost_wl_surface_tag_cursor_tablet(tool_input->cursor_surface); + wl_surface_add_listener(tool_input->cursor_surface, &cursor_surface_listener, (void *)input); zwp_tablet_tool_v2_add_listener(id, &tablet_tool_listner, tool_input); @@ -2360,7 +2382,9 @@ static void seat_handle_capabilities(void *data, input->cursor.size = default_cursor_size; } wl_pointer_add_listener(input->wl_pointer, &pointer_listener, data); + wl_surface_add_listener(input->cursor.wl_surface, &cursor_surface_listener, data); + ghost_wl_surface_tag_cursor_pointer(input->cursor.wl_surface); } if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { @@ -3211,19 +3235,30 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title, static void cursor_buffer_show(const input_t *input) { const cursor_t *c = &input->cursor; - const int scale = c->is_custom ? c->custom_scale : c->theme_scale; - const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale; - const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale; - wl_pointer_set_cursor( - input->wl_pointer, input->pointer.serial, c->wl_surface, hotspot_x, hotspot_y); - for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : input->tablet_tools) { - tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>( - zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2)); - zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2, - input->tablet.serial, - tool_input->cursor_surface, - hotspot_x, - hotspot_y); + + if (input->wl_pointer) { + const int scale = c->is_custom ? c->custom_scale : input->pointer.theme_scale; + const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale; + const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale; + if (input->wl_pointer) { + wl_pointer_set_cursor( + input->wl_pointer, input->pointer.serial, c->wl_surface, hotspot_x, hotspot_y); + } + } + + if (!input->tablet_tools.empty()) { + const int scale = c->is_custom ? c->custom_scale : input->tablet.theme_scale; + const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale; + const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale; + for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : input->tablet_tools) { + tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>( + zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2)); + zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2, + input->tablet.serial, + tool_input->cursor_surface, + hotspot_x, + hotspot_y); + } } } @@ -3241,52 +3276,58 @@ static void cursor_buffer_hide(const input_t *input) } } +static void cursor_buffer_set_surface_impl(const input_t *input, + wl_buffer *buffer, + struct wl_surface *wl_surface, + const int scale) +{ + const wl_cursor_image *wl_image = &input->cursor.wl_image; + const int32_t image_size_x = int32_t(wl_image->width); + const int32_t image_size_y = int32_t(wl_image->height); + GHOST_ASSERT((image_size_x % scale) == 0 && (image_size_y % scale) == 0, + "The size must be a multiple of the scale!"); + + wl_surface_set_buffer_scale(wl_surface, scale); + wl_surface_attach(wl_surface, buffer, 0, 0); + wl_surface_damage(wl_surface, 0, 0, image_size_x, image_size_y); + wl_surface_commit(wl_surface); +} + static void cursor_buffer_set(const input_t *input, wl_buffer *buffer) { const cursor_t *c = &input->cursor; - const int scale = c->is_custom ? c->custom_scale : c->theme_scale; - + const wl_cursor_image *wl_image = &input->cursor.wl_image; const bool visible = (c->visible && c->is_hardware); - const int32_t image_size_x = int32_t(c->wl_image.width); - const int32_t image_size_y = int32_t(c->wl_image.height); - /* This is a requirement of WAYLAND, when this isn't the case, * it causes Blender's window to close intermittently. */ - GHOST_ASSERT((image_size_x % scale) == 0 && (image_size_y % scale) == 0, - "The size must be a multiple of the scale!"); - - const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale; - const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale; - - wl_surface_set_buffer_scale(c->wl_surface, 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, - visible ? c->wl_surface : nullptr, - hotspot_x, - hotspot_y); + if (input->wl_pointer) { + const int scale = c->is_custom ? c->custom_scale : input->pointer.theme_scale; + const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale; + const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale; + cursor_buffer_set_surface_impl(input, buffer, c->wl_surface, scale); + wl_pointer_set_cursor(input->wl_pointer, + input->pointer.serial, + visible ? c->wl_surface : nullptr, + hotspot_x, + hotspot_y); + } /* 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<tablet_tool_input_t *>( - 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, 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, - visible ? tool_input->cursor_surface : nullptr, - hotspot_x, - hotspot_y); + if (!input->tablet_tools.empty()) { + const int scale = c->is_custom ? c->custom_scale : input->tablet.theme_scale; + const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale; + const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale; + for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : input->tablet_tools) { + tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>( + zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2)); + cursor_buffer_set_surface_impl(input, buffer, tool_input->cursor_surface, scale); + zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2, + input->tablet.serial, + visible ? tool_input->cursor_surface : nullptr, + hotspot_x, + hotspot_y); + } } } @@ -3585,6 +3626,8 @@ static input_grab_state_t input_grab_state_from_mode(const GHOST_TGrabCursorMode static const char *ghost_wl_output_tag_id = "GHOST-output"; static const char *ghost_wl_surface_tag_id = "GHOST-window"; +static const char *ghost_wl_surface_cursor_pointer_tag_id = "GHOST-cursor-pointer"; +static const char *ghost_wl_surface_cursor_tablet_tag_id = "GHOST-cursor-tablet"; bool ghost_wl_output_own(const struct wl_output *output) { @@ -3596,6 +3639,16 @@ bool ghost_wl_surface_own(const struct wl_surface *surface) return wl_proxy_get_tag((struct wl_proxy *)surface) == &ghost_wl_surface_tag_id; } +bool ghost_wl_surface_own_cursor_pointer(const struct wl_surface *surface) +{ + return wl_proxy_get_tag((struct wl_proxy *)surface) == &ghost_wl_surface_cursor_pointer_tag_id; +} + +bool ghost_wl_surface_own_cursor_tablet(const struct wl_surface *surface) +{ + return wl_proxy_get_tag((struct wl_proxy *)surface) == &ghost_wl_surface_cursor_tablet_tag_id; +} + void ghost_wl_output_tag(struct wl_output *output) { wl_proxy_set_tag((struct wl_proxy *)output, &ghost_wl_output_tag_id); @@ -3606,6 +3659,16 @@ void ghost_wl_surface_tag(struct wl_surface *surface) wl_proxy_set_tag((struct wl_proxy *)surface, &ghost_wl_surface_tag_id); } +void ghost_wl_surface_tag_cursor_pointer(struct wl_surface *surface) +{ + wl_proxy_set_tag((struct wl_proxy *)surface, &ghost_wl_surface_cursor_pointer_tag_id); +} + +void ghost_wl_surface_tag_cursor_tablet(struct wl_surface *surface) +{ + wl_proxy_set_tag((struct wl_proxy *)surface, &ghost_wl_surface_cursor_tablet_tag_id); +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index 0d51759aa2f..bdf5f2fc273 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -41,6 +41,12 @@ bool ghost_wl_surface_own(const struct wl_surface *surface); void ghost_wl_surface_tag(struct wl_surface *surface); GHOST_WindowWayland *ghost_wl_surface_user_data(struct wl_surface *surface); +bool ghost_wl_surface_own_cursor_pointer(const struct wl_surface *surface); +void ghost_wl_surface_tag_cursor_pointer(struct wl_surface *surface); + +bool ghost_wl_surface_own_cursor_tablet(const struct wl_surface *surface); +void ghost_wl_surface_tag_cursor_tablet(struct wl_surface *surface); + #ifdef WITH_GHOST_WAYLAND_DYNLOAD /** * Return true when all required WAYLAND libraries are present, |