[PATCH xwayland] xwayland: Throttle our cursor surface updates with a frame callback

Rui Matos tiagomatos at gmail.com
Mon May 25 12:15:12 PDT 2015


In some extreme cases with animated cursors at a high frame rate we
could end up filling the wl_display outgoing buffer and end up with
wl_display_flush() failing.

In any case, using the frame callback to throttle ourselves is the
right thing to do.

Signed-off-by: Rui Matos <tiagomatos at gmail.com>
---
 hw/xwayland/xwayland-cursor.c | 20 ++++++++++++++++++++
 hw/xwayland/xwayland-input.c  |  2 ++
 hw/xwayland/xwayland.h        |  1 +
 3 files changed, 23 insertions(+)

diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c
index 5a9d1fe..3ba5ad6 100644
--- a/hw/xwayland/xwayland-cursor.c
+++ b/hw/xwayland/xwayland-cursor.c
@@ -82,6 +82,19 @@ xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
     return xwl_shm_destroy_pixmap(pixmap);
 }
 
+static void
+frame_callback(void *data,
+               struct wl_callback *callback,
+               uint32_t time)
+{
+    struct xwl_seat *xwl_seat = data;
+    xwl_seat->cursor_frame_cb = NULL;
+}
+
+static const struct wl_callback_listener frame_listener = {
+    frame_callback
+};
+
 void
 xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
 {
@@ -98,6 +111,9 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
         return;
     }
 
+    if (xwl_seat->cursor_frame_cb)
+        return;
+
     cursor = xwl_seat->x_cursor;
     pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key);
     stride = cursor->bits->width * 4;
@@ -117,6 +133,10 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
     wl_surface_damage(xwl_seat->cursor, 0, 0,
                       xwl_seat->x_cursor->bits->width,
                       xwl_seat->x_cursor->bits->height);
+
+    xwl_seat->cursor_frame_cb = wl_surface_frame(xwl_seat->cursor);
+    wl_callback_add_listener(xwl_seat->cursor_frame_cb, &frame_listener, xwl_seat);
+
     wl_surface_commit(xwl_seat->cursor);
 }
 
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index 5230d8c..a3142f4 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -586,6 +586,8 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat)
     RemoveDevice(xwl_seat->keyboard, FALSE);
     wl_seat_destroy(xwl_seat->seat);
     wl_surface_destroy(xwl_seat->cursor);
+    if (xwl_seat->cursor_frame_cb)
+        wl_callback_destroy(xwl_seat->cursor_frame_cb);
     wl_array_release(&xwl_seat->keys);
     free(xwl_seat);
 }
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index bfffa71..92d6d6e 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -116,6 +116,7 @@ struct xwl_seat {
     struct wl_keyboard *wl_keyboard;
     struct wl_array keys;
     struct wl_surface *cursor;
+    struct wl_callback *cursor_frame_cb;
     struct xwl_window *focus_window;
     uint32_t id;
     uint32_t pointer_enter_serial;
-- 
2.4.0



More information about the wayland-devel mailing list