[mutter/wayland] cursor-tracker: Use a sync methodology for the cursor image



commit d96b053c9d5eb602407578481bbd3b9f1af47499
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Mon Nov 18 19:19:42 2013 -0500

    cursor-tracker: Use a sync methodology for the cursor image
    
    Rather than have MetaWaylandSeat do all the state management itself,
    put the split between the root cursor and the window cursor in the
    cursor tracker itself. We'll expand this to add a "grab" cursor in
    the next commit, allowing us to force a cursor on grab operations.

 src/core/meta-cursor-tracker-private.h |   16 +-
 src/core/meta-cursor-tracker.c         |  257 +++++++++++++++++++-------------
 src/wayland/meta-wayland-seat.c        |   26 +---
 3 files changed, 164 insertions(+), 135 deletions(-)
---
diff --git a/src/core/meta-cursor-tracker-private.h b/src/core/meta-cursor-tracker-private.h
index e18d315..ffa08df 100644
--- a/src/core/meta-cursor-tracker-private.h
+++ b/src/core/meta-cursor-tracker-private.h
@@ -31,18 +31,16 @@
 gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
                                            XEvent            *xevent);
 
-void     meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
-                                              MetaCursor         cursor);
-void     meta_cursor_tracker_revert_root     (MetaCursorTracker *tracker);
-void     meta_cursor_tracker_set_buffer      (MetaCursorTracker  *tracker,
-                                              struct wl_resource *buffer,
-                                              int                 hot_x,
-                                              int                 hot_y);
+void     meta_cursor_tracker_set_window_cursor   (MetaCursorTracker  *tracker,
+                                                  struct wl_resource *buffer,
+                                                  int                 hot_x,
+                                                  int                 hot_y);
+void     meta_cursor_tracker_unset_window_cursor (MetaCursorTracker  *tracker);
+void     meta_cursor_tracker_set_root_cursor     (MetaCursorTracker  *tracker,
+                                                  MetaCursor          cursor);
 
 void     meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
                                              int                new_x,
                                              int                new_y);
 void     meta_cursor_tracker_paint           (MetaCursorTracker *tracker);
-void     meta_cursor_tracker_queue_redraw    (MetaCursorTracker *tracker,
-                                             ClutterActor      *stage);
 #endif
diff --git a/src/core/meta-cursor-tracker.c b/src/core/meta-cursor-tracker.c
index cff5f3e..e4cf92f 100644
--- a/src/core/meta-cursor-tracker.c
+++ b/src/core/meta-cursor-tracker.c
@@ -68,11 +68,31 @@ struct _MetaCursorTracker {
   MetaScreen *screen;
 
   gboolean is_showing;
-  gboolean has_cursor;
   gboolean has_hw_cursor;
 
-  MetaCursorReference *sprite;
+  /* The cursor tracker stores the cursor for the window with
+   * pointer focus, and the cursor for the root window, which
+   * contains either the default arrow cursor or the 'busy'
+   * hourglass if we're launching an app.
+   *
+   * We choose the first one available -- if there's a window
+   * cursor, we choose that, otherwise we choose the root
+   * cursor.
+   *
+   * The displayed_cursor contains the chosen cursor.
+   */
+  MetaCursorReference *displayed_cursor;
+
+  /* Wayland clients can set a NULL buffer as their cursor 
+   * explicitly, which means that we shouldn't display anything.
+   * So, we can't simply store a NULL in window_cursor to
+   * determine an unset window cursor; we need an extra boolean.
+   */
+  gboolean has_window_cursor;
+  MetaCursorReference *window_cursor;
+
   MetaCursorReference *root_cursor;
+
   MetaCursorReference *default_cursors[META_CURSOR_LAST];
 
   int current_x, current_y;
@@ -98,9 +118,6 @@ enum {
 
 static guint signals[LAST_SIGNAL];
 
-static void meta_cursor_tracker_set_sprite (MetaCursorTracker   *tracker,
-                                            MetaCursorReference *sprite);
-
 static void meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
                                                         MetaCRTC          *crtc,
                                                         gboolean           has_hw_cursor);
@@ -354,7 +371,7 @@ meta_cursor_reference_from_buffer (MetaCursorTracker  *tracker,
   self->ref_count = 1;
   self->hot_x = hot_x;
   self->hot_y = hot_y;
- 
+
   backend = clutter_get_default_backend ();
   cogl_context = clutter_backend_get_cogl_context (backend);
 
@@ -520,8 +537,8 @@ meta_cursor_tracker_finalize (GObject *object)
   MetaCursorTracker *self = META_CURSOR_TRACKER (object);
   int i;
 
-  if (self->sprite)
-    meta_cursor_reference_unref (self->sprite);
+  if (self->displayed_cursor)
+    meta_cursor_reference_unref (self->displayed_cursor);
   if (self->root_cursor)
     meta_cursor_reference_unref (self->root_cursor);
 
@@ -646,6 +663,17 @@ meta_cursor_tracker_get_for_screen (MetaScreen *screen)
   return self;
 }
 
+static void
+set_window_cursor (MetaCursorTracker   *tracker,
+                   gboolean             has_cursor,
+                   MetaCursorReference *cursor)
+{
+  g_clear_pointer (&tracker->window_cursor, meta_cursor_reference_unref);
+  if (cursor)
+    tracker->window_cursor = meta_cursor_reference_ref (cursor);
+  tracker->has_window_cursor = has_cursor;
+}
+
 gboolean
 meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
                                    XEvent            *xevent)
@@ -662,7 +690,7 @@ meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
   if (notify_event->subtype != XFixesDisplayCursorNotify)
     return FALSE;
 
-  g_clear_pointer (&tracker->sprite, meta_cursor_reference_unref);
+  set_window_cursor (tracker, FALSE, NULL);
   g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
 
   return TRUE;
@@ -677,7 +705,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
   gboolean free_cursor_data;
   CoglContext *ctx;
 
-  if (tracker->sprite)
+  if (tracker->has_window_cursor)
     return;
 
   cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
@@ -725,9 +753,11 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
 
   if (sprite != NULL)
     {
-      tracker->sprite = meta_cursor_reference_take_texture (sprite);
-      tracker->sprite->hot_x = cursor_image->xhot;
-      tracker->sprite->hot_y = cursor_image->yhot;
+      MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite);
+      cursor->hot_x = cursor_image->xhot;
+      cursor->hot_y = cursor_image->yhot;
+
+      set_window_cursor (tracker, TRUE, cursor);
     }
   XFree (cursor_image);
 }
@@ -745,8 +775,8 @@ meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
   if (!meta_is_wayland_compositor ())
     ensure_xfixes_cursor (tracker);
 
-  if (tracker->sprite)
-    return COGL_TEXTURE (tracker->sprite->texture);
+  if (tracker->displayed_cursor)
+    return COGL_TEXTURE (tracker->displayed_cursor->texture);
   else
     return NULL;
 }
@@ -768,12 +798,13 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
   if (!meta_is_wayland_compositor ())
     ensure_xfixes_cursor (tracker);
 
-  if (tracker->sprite)
+  if (tracker->displayed_cursor)
     {
+      MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
       if (x)
-        *x = tracker->sprite->hot_x;
+        *x = displayed_cursor->hot_x;
       if (y)
-        *y = tracker->sprite->hot_y;
+        *y = displayed_cursor->hot_y;
     }
   else
     {
@@ -799,6 +830,28 @@ ensure_wayland_cursor (MetaCursorTracker *tracker,
 }
 
 void
+meta_cursor_tracker_set_window_cursor (MetaCursorTracker  *tracker,
+                                       struct wl_resource *buffer,
+                                       int                 hot_x,
+                                       int                 hot_y)
+{
+  MetaCursorReference *cursor;
+
+  if (buffer)
+    cursor = meta_cursor_reference_from_buffer (tracker, buffer, hot_x, hot_y);
+  else
+    cursor = NULL;
+
+  set_window_cursor (tracker, TRUE, cursor);
+}
+
+void
+meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker)
+{
+  set_window_cursor (tracker, FALSE, NULL);
+}
+
+void
 meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
                                      MetaCursor         cursor)
 {
@@ -824,12 +877,6 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
     }
 }
 
-void
-meta_cursor_tracker_revert_root (MetaCursorTracker *tracker)
-{
-  meta_cursor_tracker_set_sprite (tracker, tracker->root_cursor);
-}
-
 static void
 update_hw_cursor (MetaCursorTracker *tracker)
 {
@@ -838,7 +885,7 @@ update_hw_cursor (MetaCursorTracker *tracker)
   unsigned int i, n_crtcs;
   gboolean enabled;
 
-  enabled = tracker->has_cursor && tracker->sprite->bo != NULL;
+  enabled = tracker->displayed_cursor && tracker->displayed_cursor->bo != NULL;
   tracker->has_hw_cursor = enabled;
 
   monitors = meta_monitor_manager_get ();
@@ -884,67 +931,85 @@ move_hw_cursor (MetaCursorTracker *tracker)
     }
 }
 
-void
-meta_cursor_tracker_set_buffer (MetaCursorTracker  *tracker,
-                                struct wl_resource *buffer,
-                                int                 hot_x,
-                                int                 hot_y)
+static MetaCursorReference *
+get_displayed_cursor (MetaCursorTracker *tracker)
 {
-  MetaCursorReference *new_cursor;
+  if (!tracker->is_showing)
+    return NULL;
 
-  if (buffer)
-    {
-      new_cursor = meta_cursor_reference_from_buffer (tracker, buffer, hot_x, hot_y);
-      meta_cursor_tracker_set_sprite (tracker, new_cursor);
-      meta_cursor_reference_unref (new_cursor);
-    }
-  else
-    meta_cursor_tracker_set_sprite (tracker, NULL);
+  if (tracker->has_window_cursor)
+    return tracker->window_cursor;
+
+  return tracker->root_cursor;
 }
 
 static void
-meta_cursor_tracker_set_sprite (MetaCursorTracker   *tracker,
-                                MetaCursorReference *sprite)
+sync_displayed_cursor (MetaCursorTracker *tracker)
 {
-  g_assert (meta_is_wayland_compositor ());
+  MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker);
 
-  if (sprite == tracker->sprite)
+  if (tracker->displayed_cursor == displayed_cursor)
     return;
 
-  g_clear_pointer (&tracker->sprite, meta_cursor_reference_unref);
+  g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref);
+  if (displayed_cursor)
+    tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
 
-  if (sprite)
-    {
-      tracker->sprite = meta_cursor_reference_ref (sprite);
-      cogl_pipeline_set_layer_texture (tracker->pipeline, 0, COGL_TEXTURE (tracker->sprite->texture));
-    }
+  if (displayed_cursor)
+    cogl_pipeline_set_layer_texture (tracker->pipeline, 0, COGL_TEXTURE (displayed_cursor->texture));
   else
     cogl_pipeline_set_layer_texture (tracker->pipeline, 0, NULL);
 
-  tracker->has_cursor = tracker->sprite != NULL && tracker->is_showing;
   update_hw_cursor (tracker);
 
   g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
-
-  meta_cursor_tracker_update_position (tracker, tracker->current_x, tracker->current_y);
 }
 
-void
-meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
-                                     int                new_x,
-                                     int                new_y)
+static void
+meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker)
 {
+  MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
+  ClutterActor *stage = compositor->stage;
+  cairo_rectangle_int_t clip;
+
   g_assert (meta_is_wayland_compositor ());
 
-  tracker->current_x = new_x;
-  tracker->current_y = new_y;
+  if (tracker->previous_is_valid)
+    {
+      cairo_rectangle_int_t clip = {
+        .x = tracker->previous_rect.x,
+        .y = tracker->previous_rect.y,
+        .width = tracker->previous_rect.width,
+        .height = tracker->previous_rect.height
+      };
+      clutter_actor_queue_redraw_with_clip (stage, &clip);
+      tracker->previous_is_valid = FALSE;
+    }
+
+  if (tracker->has_hw_cursor || !tracker->displayed_cursor)
+    return;
+
+  clip.x = tracker->current_rect.x;
+  clip.y = tracker->current_rect.y;
+  clip.width = tracker->current_rect.width;
+  clip.height = tracker->current_rect.height;
+  clutter_actor_queue_redraw_with_clip (stage, &clip);
+}
+
+static void
+sync_cursor (MetaCursorTracker *tracker)
+{
+  MetaCursorReference *displayed_cursor;
+
+  sync_displayed_cursor (tracker);
+  displayed_cursor = tracker->displayed_cursor;
 
-  if (tracker->sprite)
+  if (displayed_cursor)
     {
-      tracker->current_rect.x = tracker->current_x - tracker->sprite->hot_x;
-      tracker->current_rect.y = tracker->current_y - tracker->sprite->hot_y;
-      tracker->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (tracker->sprite->texture));
-      tracker->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (tracker->sprite->texture));
+      tracker->current_rect.x = tracker->current_x - displayed_cursor->hot_x;
+      tracker->current_rect.y = tracker->current_y - displayed_cursor->hot_y;
+      tracker->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (displayed_cursor->texture));
+      tracker->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (displayed_cursor->texture));
     }
   else
     {
@@ -956,6 +1021,21 @@ meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
 
   if (tracker->has_hw_cursor)
     move_hw_cursor (tracker);
+  else
+    meta_cursor_tracker_queue_redraw (tracker);
+}
+
+void
+meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
+                                     int                new_x,
+                                     int                new_y)
+{
+  g_assert (meta_is_wayland_compositor ());
+
+  tracker->current_x = new_x;
+  tracker->current_y = new_y;
+
+  sync_cursor (tracker);
 }
 
 void
@@ -963,7 +1043,7 @@ meta_cursor_tracker_paint (MetaCursorTracker *tracker)
 {
   g_assert (meta_is_wayland_compositor ());
 
-  if (tracker->has_hw_cursor || !tracker->has_cursor)
+  if (tracker->has_hw_cursor || !tracker->displayed_cursor)
     return;
 
   cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
@@ -979,36 +1059,6 @@ meta_cursor_tracker_paint (MetaCursorTracker *tracker)
   tracker->previous_is_valid = TRUE;
 }
 
-void
-meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker,
-                                  ClutterActor      *stage)
-{
-  cairo_rectangle_int_t clip;
-
-  g_assert (meta_is_wayland_compositor ());
-
-  if (tracker->previous_is_valid)
-    {
-      cairo_rectangle_int_t clip = {
-        .x = tracker->previous_rect.x,
-        .y = tracker->previous_rect.y,
-        .width = tracker->previous_rect.width,
-        .height = tracker->previous_rect.height
-      };
-      clutter_actor_queue_redraw_with_clip (stage, &clip);
-      tracker->previous_is_valid = FALSE;
-    }
-
-  if (tracker->has_hw_cursor || !tracker->has_cursor)
-    return;
-
-  clip.x = tracker->current_rect.x;
-  clip.y = tracker->current_rect.y;
-  clip.width = tracker->current_rect.width;
-  clip.height = tracker->current_rect.height;
-  clutter_actor_queue_redraw_with_clip (stage, &clip);
-}
-
 static void
 meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
                                             MetaCRTC          *crtc,
@@ -1016,15 +1066,16 @@ meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
 {
   if (has)
     {
+      MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
       union gbm_bo_handle handle;
       int width, height;
       int hot_x, hot_y;
 
-      handle = gbm_bo_get_handle (tracker->sprite->bo);
-      width = gbm_bo_get_width (tracker->sprite->bo);
-      height = gbm_bo_get_height (tracker->sprite->bo);
-      hot_x = tracker->sprite->hot_x;
-      hot_y = tracker->sprite->hot_y;
+      handle = gbm_bo_get_handle (displayed_cursor->bo);
+      width = gbm_bo_get_width (displayed_cursor->bo);
+      height = gbm_bo_get_height (displayed_cursor->bo);
+      hot_x = displayed_cursor->hot_x;
+      hot_y = displayed_cursor->hot_y;
 
       drmModeSetCursor2 (tracker->drm_fd, crtc->crtc_id, handle.u32,
                          width, height, hot_x, hot_y);
@@ -1100,13 +1151,7 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
 
   if (meta_is_wayland_compositor ())
     {
-      MetaWaylandCompositor *compositor;
-
-      compositor = meta_wayland_compositor_get_default ();
-
-      tracker->has_cursor = tracker->sprite != NULL && visible;
-      update_hw_cursor (tracker);
-      meta_cursor_tracker_queue_redraw (tracker, compositor->stage);
+      sync_cursor (tracker);
     }
   else
     {
diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
index 0b9415a..377e7f2 100644
--- a/src/wayland/meta-wayland-seat.c
+++ b/src/wayland/meta-wayland-seat.c
@@ -51,14 +51,7 @@ static void
 pointer_unmap_sprite (MetaWaylandSeat *seat)
 {
   if (seat->cursor_tracker)
-    {
-      meta_cursor_tracker_set_buffer (seat->cursor_tracker,
-                                     NULL, 0, 0);
-
-      if (seat->current_stage)
-       meta_cursor_tracker_queue_redraw (seat->cursor_tracker,
-                                         CLUTTER_ACTOR (seat->current_stage));
-    }
+    meta_cursor_tracker_set_window_cursor (seat->cursor_tracker, NULL, 0, 0);
 
   if (seat->sprite)
     {
@@ -76,14 +69,10 @@ meta_wayland_seat_update_sprite (MetaWaylandSeat *seat)
     return;
 
   buffer = seat->sprite->buffer_ref.buffer->resource;
-  meta_cursor_tracker_set_buffer (seat->cursor_tracker,
-                                 buffer,
-                                 seat->hotspot_x,
-                                 seat->hotspot_y);
-
-  if (seat->current_stage)
-    meta_cursor_tracker_queue_redraw (seat->cursor_tracker,
-                                     CLUTTER_ACTOR (seat->current_stage));
+  meta_cursor_tracker_set_window_cursor (seat->cursor_tracker,
+                                         buffer,
+                                         seat->hotspot_x,
+                                         seat->hotspot_y);
 }
 
 static void
@@ -377,10 +366,7 @@ meta_wayland_seat_update_pointer (MetaWaylandSeat    *seat,
                                           wl_fixed_to_int (seat->pointer.y));
 
       if (seat->pointer.current == NULL)
-       meta_cursor_tracker_revert_root (seat->cursor_tracker);
-
-      meta_cursor_tracker_queue_redraw (seat->cursor_tracker,
-                                        CLUTTER_ACTOR (event->any.stage));
+       meta_cursor_tracker_unset_window_cursor (seat->cursor_tracker);
     }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]