clients/window: atomically update pointer cursor
Currently, Weston clients update the pointer cursor by first issuing a wl_surface.commit request to update the buffer, then a wl_pointer.set_cursor request to update the hotspot. This causes an issue because buffer and hotspot aren't updated atomically: in-between the two requests, the buffer is new but the hotspot is old. To fix this issue, create a new surface each time the cursor is updated. Signed-off-by: Simon Ser <contact@emersion.fr>
This commit is contained in:
+14
-5
@@ -3785,6 +3785,8 @@ input_set_pointer_image_index(struct input *input, int index)
|
|||||||
struct wl_buffer *buffer;
|
struct wl_buffer *buffer;
|
||||||
struct wl_cursor *cursor;
|
struct wl_cursor *cursor;
|
||||||
struct wl_cursor_image *image;
|
struct wl_cursor_image *image;
|
||||||
|
struct wl_surface *prev_surface;
|
||||||
|
struct display *d = input->display;
|
||||||
|
|
||||||
if (!input->pointer)
|
if (!input->pointer)
|
||||||
return;
|
return;
|
||||||
@@ -3803,6 +3805,11 @@ input_set_pointer_image_index(struct input *input, int index)
|
|||||||
if (!buffer)
|
if (!buffer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Don't re-use the previous surface, otherwise the new buffer and the
|
||||||
|
* new hotspot aren't applied atomically. */
|
||||||
|
prev_surface = input->pointer_surface;
|
||||||
|
input->pointer_surface = wl_compositor_create_surface(d->compositor);
|
||||||
|
|
||||||
wl_surface_attach(input->pointer_surface, buffer, 0, 0);
|
wl_surface_attach(input->pointer_surface, buffer, 0, 0);
|
||||||
wl_surface_damage(input->pointer_surface, 0, 0,
|
wl_surface_damage(input->pointer_surface, 0, 0,
|
||||||
image->width, image->height);
|
image->width, image->height);
|
||||||
@@ -3810,6 +3817,9 @@ input_set_pointer_image_index(struct input *input, int index)
|
|||||||
wl_pointer_set_cursor(input->pointer, input->pointer_enter_serial,
|
wl_pointer_set_cursor(input->pointer, input->pointer_enter_serial,
|
||||||
input->pointer_surface,
|
input->pointer_surface,
|
||||||
image->hotspot_x, image->hotspot_y);
|
image->hotspot_x, image->hotspot_y);
|
||||||
|
|
||||||
|
if (prev_surface)
|
||||||
|
wl_surface_destroy(prev_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_callback_listener pointer_surface_listener;
|
static const struct wl_callback_listener pointer_surface_listener;
|
||||||
@@ -3914,11 +3924,11 @@ pointer_surface_frame_callback(void *data, struct wl_callback *callback,
|
|||||||
time - input->cursor_anim_start,
|
time - input->cursor_anim_start,
|
||||||
&duration);
|
&duration);
|
||||||
|
|
||||||
|
input_set_pointer_image_index(input, i);
|
||||||
|
|
||||||
if (cursor->image_count > 1)
|
if (cursor->image_count > 1)
|
||||||
schedule_pointer_image_update(input, cursor, duration,
|
schedule_pointer_image_update(input, cursor, duration,
|
||||||
force_frame);
|
force_frame);
|
||||||
|
|
||||||
input_set_pointer_image_index(input, i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -5899,8 +5909,6 @@ display_add_input(struct display *d, uint32_t id, int display_seat_version)
|
|||||||
input);
|
input);
|
||||||
}
|
}
|
||||||
|
|
||||||
input->pointer_surface = wl_compositor_create_surface(d->compositor);
|
|
||||||
|
|
||||||
toytimer_init(&input->cursor_timer, CLOCK_MONOTONIC, d,
|
toytimer_init(&input->cursor_timer, CLOCK_MONOTONIC, d,
|
||||||
cursor_timer_func);
|
cursor_timer_func);
|
||||||
|
|
||||||
@@ -5968,7 +5976,8 @@ input_destroy(struct input *input)
|
|||||||
|
|
||||||
fini_xkb(input);
|
fini_xkb(input);
|
||||||
|
|
||||||
wl_surface_destroy(input->pointer_surface);
|
if (input->pointer_surface)
|
||||||
|
wl_surface_destroy(input->pointer_surface);
|
||||||
|
|
||||||
wl_list_remove(&input->link);
|
wl_list_remove(&input->link);
|
||||||
wl_seat_destroy(input->seat);
|
wl_seat_destroy(input->seat);
|
||||||
|
|||||||
Reference in New Issue
Block a user