clients/window: Fix animated cursors

Since commit 992ee045f1 we create a new surface when we update the cursor
image. This broke animated cursors by discarding any existing frame
callback used for timing, and moving the setup for frame callbacks to
after the commit on the pointer surface.

To fix this we need another surface commit for the frame callbacks, but
this alone is not enough to fix the regression, as a lingering kludge
intended to fix problems when reusing the pointer surface is no longer
working as intended.

Since we no longer re-use the same surface, we can delete the old surface
on pointer exit, along with any callbacks set on it. Then a frame callback
will be recreated naturally. This lets us remove the now broken kludge
from the past and restore animated cursor functionality.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
This commit is contained in:
Derek Foreman 2022-01-12 16:06:17 -06:00 committed by Simon Ser
parent 3759ad1538
commit f079f43658

View File

@ -353,7 +353,6 @@ struct input {
struct wl_surface *pointer_surface; struct wl_surface *pointer_surface;
uint32_t modifiers; uint32_t modifiers;
uint32_t pointer_enter_serial; uint32_t pointer_enter_serial;
uint32_t cursor_serial;
float sx, sy; float sx, sy;
struct wl_list link; struct wl_list link;
@ -2747,6 +2746,12 @@ input_remove_pointer_focus(struct input *input)
input->pointer_focus = NULL; input->pointer_focus = NULL;
input->current_cursor = CURSOR_UNSET; input->current_cursor = CURSOR_UNSET;
cancel_pointer_image_update(input); cancel_pointer_image_update(input);
wl_surface_destroy(input->pointer_surface);
input->pointer_surface = NULL;
if (input->cursor_frame_cb) {
wl_callback_destroy(input->cursor_frame_cb);
input->cursor_frame_cb = NULL;
}
} }
static void static void
@ -3876,6 +3881,7 @@ schedule_pointer_image_update(struct input *input,
wl_callback_add_listener(input->cursor_frame_cb, wl_callback_add_listener(input->cursor_frame_cb,
&pointer_surface_listener, input); &pointer_surface_listener, input);
wl_surface_commit(input->pointer_surface);
} }
static void static void
@ -3959,30 +3965,15 @@ static const struct wl_callback_listener pointer_surface_listener = {
void void
input_set_pointer_image(struct input *input, int pointer) input_set_pointer_image(struct input *input, int pointer)
{ {
int force = 0;
if (!input->pointer) if (!input->pointer)
return; return;
if (input->pointer_enter_serial > input->cursor_serial) if (pointer == input->current_cursor)
force = 1;
if (!force && pointer == input->current_cursor)
return; return;
input->current_cursor = pointer; input->current_cursor = pointer;
input->cursor_serial = input->pointer_enter_serial;
if (!input->cursor_frame_cb) if (!input->cursor_frame_cb)
pointer_surface_frame_callback(input, NULL, 0); pointer_surface_frame_callback(input, NULL, 0);
else if (force && !input_set_pointer_special(input)) {
/* The current frame callback may be stuck if, for instance,
* the set cursor request was processed by the server after
* this client lost the focus. In this case the cursor surface
* might not be mapped and the frame callback wouldn't ever
* complete. Send a set_cursor and attach to try to map the
* cursor surface again so that the callback will finish */
input_set_pointer_image_index(input, 0);
}
} }
struct wl_data_device * struct wl_data_device *