mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-26 05:31:07 +00:00
wayland: Implement animatable cursors
Cursor animations are handled on a per-device basis, with GdkWaylandDevice updating the pointer surface for each frame. https://bugzilla.gnome.org/show_bug.cgi?id=696429
This commit is contained in:
parent
4801977d80
commit
b8ed3e9ef5
@ -182,6 +182,7 @@ gdk_wayland_cursor_get_image (GdkCursor *cursor)
|
|||||||
|
|
||||||
struct wl_buffer *
|
struct wl_buffer *
|
||||||
_gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
|
_gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
|
||||||
|
guint image_index,
|
||||||
int *x,
|
int *x,
|
||||||
int *y,
|
int *y,
|
||||||
int *w,
|
int *w,
|
||||||
@ -191,13 +192,25 @@ _gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
|
|||||||
|
|
||||||
if (wayland_cursor->wl_cursor)
|
if (wayland_cursor->wl_cursor)
|
||||||
{
|
{
|
||||||
*x = wayland_cursor->wl_cursor->images[0]->hotspot_x;
|
struct wl_cursor_image *image;
|
||||||
*y = wayland_cursor->wl_cursor->images[0]->hotspot_y;
|
|
||||||
|
|
||||||
*w = wayland_cursor->wl_cursor->images[0]->width;
|
if (image_index >= wayland_cursor->wl_cursor->image_count)
|
||||||
*h = wayland_cursor->wl_cursor->images[0]->height;
|
{
|
||||||
|
g_warning (G_STRLOC " out of bounds cursor image [%d / %d]",
|
||||||
|
image_index,
|
||||||
|
wayland_cursor->wl_cursor->image_count - 1);
|
||||||
|
image_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return wl_cursor_image_get_buffer(wayland_cursor->wl_cursor->images[0]);
|
image = wayland_cursor->wl_cursor->images[image_index];
|
||||||
|
|
||||||
|
*x = image->hotspot_x;
|
||||||
|
*y = image->hotspot_y;
|
||||||
|
|
||||||
|
*w = image->width;
|
||||||
|
*h = image->height;
|
||||||
|
|
||||||
|
return wl_cursor_image_get_buffer (image);
|
||||||
}
|
}
|
||||||
else /* From pixbuf */
|
else /* From pixbuf */
|
||||||
{
|
{
|
||||||
@ -211,6 +224,32 @@ _gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
_gdk_wayland_cursor_get_next_image_index (GdkCursor *cursor,
|
||||||
|
guint current_image_index,
|
||||||
|
guint *next_image_delay)
|
||||||
|
{
|
||||||
|
struct wl_cursor *wl_cursor = GDK_WAYLAND_CURSOR (cursor)->wl_cursor;
|
||||||
|
|
||||||
|
if (wl_cursor && wl_cursor->image_count > 1)
|
||||||
|
{
|
||||||
|
if (current_image_index >= wl_cursor->image_count)
|
||||||
|
{
|
||||||
|
g_warning (G_STRLOC " out of bounds cursor image [%d / %d]",
|
||||||
|
current_image_index, wl_cursor->image_count - 1);
|
||||||
|
current_image_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the time to next image */
|
||||||
|
if (next_image_delay)
|
||||||
|
*next_image_delay = wl_cursor->images[current_image_index]->delay;
|
||||||
|
|
||||||
|
return (current_image_index + 1) % wl_cursor->image_count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return current_image_index;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_gdk_wayland_cursor_class_init (GdkWaylandCursorClass *wayland_cursor_class)
|
_gdk_wayland_cursor_class_init (GdkWaylandCursorClass *wayland_cursor_class)
|
||||||
{
|
{
|
||||||
@ -335,11 +374,6 @@ _gdk_wayland_display_get_cursor_for_name (GdkDisplay *display,
|
|||||||
if (!set_cursor_from_theme (private, wayland_display->cursor_theme))
|
if (!set_cursor_from_theme (private, wayland_display->cursor_theme))
|
||||||
return GDK_CURSOR (private);
|
return GDK_CURSOR (private);
|
||||||
|
|
||||||
/* TODO: Do something clever so we can do animated cursors - move the
|
|
||||||
* wl_pointer_set_cursor to a function here so that we can do the magic to
|
|
||||||
* iterate through
|
|
||||||
*/
|
|
||||||
|
|
||||||
add_to_cache (wayland_display, private);
|
add_to_cache (wayland_display, private);
|
||||||
|
|
||||||
return GDK_CURSOR (private);
|
return GDK_CURSOR (private);
|
||||||
|
@ -71,6 +71,9 @@ struct _GdkWaylandDeviceData
|
|||||||
guint32 repeat_count;
|
guint32 repeat_count;
|
||||||
GSettings *keyboard_settings;
|
GSettings *keyboard_settings;
|
||||||
|
|
||||||
|
guint cursor_timeout_id;
|
||||||
|
guint cursor_image_index;
|
||||||
|
|
||||||
DataOffer *drag_offer;
|
DataOffer *drag_offer;
|
||||||
DataOffer *selection_offer;
|
DataOffer *selection_offer;
|
||||||
|
|
||||||
@ -144,14 +147,63 @@ gdk_wayland_device_get_state (GdkDevice *device,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_wayland_device_stop_window_cursor_animation (GdkWaylandDeviceData *wd)
|
||||||
|
{
|
||||||
|
if (wd->cursor_timeout_id > 0)
|
||||||
|
{
|
||||||
|
g_source_remove (wd->cursor_timeout_id);
|
||||||
|
wd->cursor_timeout_id = 0;
|
||||||
|
}
|
||||||
|
wd->cursor_image_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdk_wayland_device_update_window_cursor (GdkWaylandDeviceData *wd)
|
||||||
|
{
|
||||||
|
struct wl_buffer *buffer;
|
||||||
|
int x, y, w, h;
|
||||||
|
guint next_image_index, next_image_delay;
|
||||||
|
|
||||||
|
buffer = _gdk_wayland_cursor_get_buffer (wd->cursor, wd->cursor_image_index,
|
||||||
|
&x, &y, &w, &h);
|
||||||
|
wl_pointer_set_cursor (wd->wl_pointer,
|
||||||
|
wd->enter_serial,
|
||||||
|
wd->pointer_surface,
|
||||||
|
x, y);
|
||||||
|
wl_surface_attach (wd->pointer_surface, buffer, 0, 0);
|
||||||
|
wl_surface_damage (wd->pointer_surface, 0, 0, w, h);
|
||||||
|
wl_surface_commit (wd->pointer_surface);
|
||||||
|
|
||||||
|
next_image_index =
|
||||||
|
_gdk_wayland_cursor_get_next_image_index (wd->cursor,
|
||||||
|
wd->cursor_image_index,
|
||||||
|
&next_image_delay);
|
||||||
|
|
||||||
|
if (next_image_index != wd->cursor_image_index)
|
||||||
|
{
|
||||||
|
guint id;
|
||||||
|
|
||||||
|
/* Queue timeout for next frame */
|
||||||
|
id = g_timeout_add (next_image_delay,
|
||||||
|
(GSourceFunc)gdk_wayland_device_update_window_cursor,
|
||||||
|
wd);
|
||||||
|
|
||||||
|
wd->cursor_timeout_id = id;
|
||||||
|
wd->cursor_image_index = next_image_index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
wd->cursor_timeout_id = 0;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gdk_wayland_device_set_window_cursor (GdkDevice *device,
|
gdk_wayland_device_set_window_cursor (GdkDevice *device,
|
||||||
GdkWindow *window,
|
GdkWindow *window,
|
||||||
GdkCursor *cursor)
|
GdkCursor *cursor)
|
||||||
{
|
{
|
||||||
GdkWaylandDeviceData *wd = GDK_WAYLAND_DEVICE(device)->device;
|
GdkWaylandDeviceData *wd = GDK_WAYLAND_DEVICE(device)->device;
|
||||||
struct wl_buffer *buffer;
|
|
||||||
int x, y, w, h;
|
|
||||||
|
|
||||||
/* Setting the cursor to NULL means that we should use the default cursor */
|
/* Setting the cursor to NULL means that we should use the default cursor */
|
||||||
if (!cursor)
|
if (!cursor)
|
||||||
@ -164,19 +216,14 @@ gdk_wayland_device_set_window_cursor (GdkDevice *device,
|
|||||||
if (cursor == wd->cursor)
|
if (cursor == wd->cursor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
gdk_wayland_device_stop_window_cursor_animation (wd);
|
||||||
|
|
||||||
if (wd->cursor)
|
if (wd->cursor)
|
||||||
g_object_unref (wd->cursor);
|
g_object_unref (wd->cursor);
|
||||||
|
|
||||||
wd->cursor = g_object_ref (cursor);
|
wd->cursor = g_object_ref (cursor);
|
||||||
|
|
||||||
buffer = _gdk_wayland_cursor_get_buffer (wd->cursor, &x, &y, &w, &h);
|
gdk_wayland_device_update_window_cursor (wd);
|
||||||
wl_pointer_set_cursor (wd->wl_pointer,
|
|
||||||
wd->enter_serial,
|
|
||||||
wd->pointer_surface,
|
|
||||||
x, y);
|
|
||||||
wl_surface_attach (wd->pointer_surface, buffer, 0, 0);
|
|
||||||
wl_surface_damage (wd->pointer_surface, 0, 0, w, h);
|
|
||||||
wl_surface_commit (wd->pointer_surface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -622,6 +669,7 @@ pointer_handle_leave (void *data,
|
|||||||
g_object_unref(device->pointer_focus);
|
g_object_unref(device->pointer_focus);
|
||||||
if (device->cursor)
|
if (device->cursor)
|
||||||
{
|
{
|
||||||
|
gdk_wayland_device_stop_window_cursor_animation (device);
|
||||||
g_object_unref (device->cursor);
|
g_object_unref (device->cursor);
|
||||||
device->cursor = NULL;
|
device->cursor = NULL;
|
||||||
}
|
}
|
||||||
|
@ -78,10 +78,14 @@ gboolean _gdk_wayland_display_supports_cursor_alpha (GdkDisplay *display);
|
|||||||
gboolean _gdk_wayland_display_supports_cursor_color (GdkDisplay *display);
|
gboolean _gdk_wayland_display_supports_cursor_color (GdkDisplay *display);
|
||||||
|
|
||||||
struct wl_buffer *_gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
|
struct wl_buffer *_gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
|
||||||
int *x,
|
guint image_index,
|
||||||
int *y,
|
int *x,
|
||||||
|
int *y,
|
||||||
int *w,
|
int *w,
|
||||||
int *h);
|
int *h);
|
||||||
|
guint _gdk_wayland_cursor_get_next_image_index (GdkCursor *cursor,
|
||||||
|
guint current_image_index,
|
||||||
|
guint *next_image_delay);
|
||||||
|
|
||||||
GdkDragProtocol _gdk_wayland_window_get_drag_protocol (GdkWindow *window,
|
GdkDragProtocol _gdk_wayland_window_get_drag_protocol (GdkWindow *window,
|
||||||
GdkWindow **target);
|
GdkWindow **target);
|
||||||
|
Loading…
Reference in New Issue
Block a user