[gtk+] wayland: Implement animatable cursors
- From: Kristian Høgsberg <krh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] wayland: Implement animatable cursors
- Date: Thu, 28 Mar 2013 14:34:43 +0000 (UTC)
commit b8ed3e9ef52bb45ff9a3836e50fd7b90936c2c97
Author: Chris Cummins <christopher e cummins intel com>
Date: Thu Mar 28 12:08:43 2013 +0000
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
gdk/wayland/gdkcursor-wayland.c | 54 ++++++++++++++++++++++++-----
gdk/wayland/gdkdevice-wayland.c | 68 ++++++++++++++++++++++++++++++++-----
gdk/wayland/gdkprivate-wayland.h | 8 +++-
3 files changed, 108 insertions(+), 22 deletions(-)
---
diff --git a/gdk/wayland/gdkcursor-wayland.c b/gdk/wayland/gdkcursor-wayland.c
index 8873813..fc51473 100644
--- a/gdk/wayland/gdkcursor-wayland.c
+++ b/gdk/wayland/gdkcursor-wayland.c
@@ -182,6 +182,7 @@ gdk_wayland_cursor_get_image (GdkCursor *cursor)
struct wl_buffer *
_gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
+ guint image_index,
int *x,
int *y,
int *w,
@@ -191,13 +192,25 @@ _gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
if (wayland_cursor->wl_cursor)
{
- *x = wayland_cursor->wl_cursor->images[0]->hotspot_x;
- *y = wayland_cursor->wl_cursor->images[0]->hotspot_y;
+ struct wl_cursor_image *image;
- *w = wayland_cursor->wl_cursor->images[0]->width;
- *h = wayland_cursor->wl_cursor->images[0]->height;
+ if (image_index >= wayland_cursor->wl_cursor->image_count)
+ {
+ 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 */
{
@@ -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
_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))
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);
return GDK_CURSOR (private);
diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c
index 4c8caec..74dd5d5 100644
--- a/gdk/wayland/gdkdevice-wayland.c
+++ b/gdk/wayland/gdkdevice-wayland.c
@@ -71,6 +71,9 @@ struct _GdkWaylandDeviceData
guint32 repeat_count;
GSettings *keyboard_settings;
+ guint cursor_timeout_id;
+ guint cursor_image_index;
+
DataOffer *drag_offer;
DataOffer *selection_offer;
@@ -145,13 +148,62 @@ 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
gdk_wayland_device_set_window_cursor (GdkDevice *device,
GdkWindow *window,
GdkCursor *cursor)
{
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 */
if (!cursor)
@@ -164,19 +216,14 @@ gdk_wayland_device_set_window_cursor (GdkDevice *device,
if (cursor == wd->cursor)
return;
+ gdk_wayland_device_stop_window_cursor_animation (wd);
+
if (wd->cursor)
g_object_unref (wd->cursor);
wd->cursor = g_object_ref (cursor);
- buffer = _gdk_wayland_cursor_get_buffer (wd->cursor, &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);
+ gdk_wayland_device_update_window_cursor (wd);
}
static void
@@ -622,6 +669,7 @@ pointer_handle_leave (void *data,
g_object_unref(device->pointer_focus);
if (device->cursor)
{
+ gdk_wayland_device_stop_window_cursor_animation (device);
g_object_unref (device->cursor);
device->cursor = NULL;
}
diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h
index 4dcc80c..8421043 100644
--- a/gdk/wayland/gdkprivate-wayland.h
+++ b/gdk/wayland/gdkprivate-wayland.h
@@ -78,10 +78,14 @@ gboolean _gdk_wayland_display_supports_cursor_alpha (GdkDisplay *display);
gboolean _gdk_wayland_display_supports_cursor_color (GdkDisplay *display);
struct wl_buffer *_gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
- int *x,
- int *y,
+ guint image_index,
+ int *x,
+ int *y,
int *w,
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,
GdkWindow **target);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]