[mutter/wip/tablet-protocol: 13/15] wayland: Handle wl_tablet cursor updates



commit 345dd48758f10df560376787dcf254fb9dda1965
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu Feb 5 12:10:03 2015 +0100

    wayland: Handle wl_tablet cursor updates
    
    The cursor is now properly changed on wl_tablet.set_cursor, unset if the
    surface is destroyed, and shown/hidden on tool proximity.

 src/wayland/meta-wayland-tablet.c |  104 +++++++++++++++++++++++++++++++++++++
 src/wayland/meta-wayland-tablet.h |    2 +
 2 files changed, 106 insertions(+), 0 deletions(-)
---
diff --git a/src/wayland/meta-wayland-tablet.c b/src/wayland/meta-wayland-tablet.c
index 81dcbaf..8aaf9ac 100644
--- a/src/wayland/meta-wayland-tablet.c
+++ b/src/wayland/meta-wayland-tablet.c
@@ -30,11 +30,14 @@
 #include <wayland-server.h>
 #include "wayland-tablet-server-protocol.h"
 
+#include "meta-wayland-buffer.h"
 #include "meta-surface-actor-wayland.h"
 #include "meta-wayland-private.h"
 #include "meta-wayland-tablet.h"
 #include "meta-wayland-tablet-tool.h"
 
+static void meta_wayland_tablet_set_cursor_surface (MetaWaylandTablet  *tablet,
+                                                    MetaWaylandSurface *surface);
 static void meta_wayland_tablet_set_focus          (MetaWaylandTablet  *tablet,
                                                     MetaWaylandSurface *surface);
 
@@ -77,6 +80,16 @@ tablet_handle_focus_surface_destroy (struct wl_listener *listener,
   meta_wayland_tablet_set_focus (tablet, NULL);
 }
 
+static void
+tablet_handle_cursor_surface_destroy (struct wl_listener *listener,
+                                      void               *data)
+{
+  MetaWaylandTablet *tablet;
+
+  tablet = wl_container_of (listener, tablet, cursor_surface_destroy_listener);
+  meta_wayland_tablet_set_cursor_surface (tablet, NULL);
+}
+
 MetaWaylandTablet *
 meta_wayland_tablet_new (ClutterInputDevice       *device,
                          MetaWaylandTabletManager *manager)
@@ -90,9 +103,12 @@ meta_wayland_tablet_new (ClutterInputDevice       *device,
   tablet->manager = manager;
 
   tablet->focus_surface_destroy_listener.notify = tablet_handle_focus_surface_destroy;
+  tablet->cursor_surface_destroy_listener.notify = tablet_handle_cursor_surface_destroy;
 
   tablet->cursor_renderer = meta_cursor_renderer_new ();
   meta_cursor_renderer_set_cursor (tablet->cursor_renderer, NULL);
+  tablet->tools = g_hash_table_new_full (NULL, NULL, NULL,
+                                         (GDestroyNotify) meta_wayland_tablet_tool_free);
 
   return tablet;
 }
@@ -103,6 +119,7 @@ meta_wayland_tablet_free (MetaWaylandTablet *tablet)
   struct wl_resource *resource, *next;
 
   meta_wayland_tablet_set_focus (tablet, NULL);
+  meta_wayland_tablet_set_cursor_surface (tablet, NULL);
   g_hash_table_destroy (tablet->tools);
 
   wl_resource_for_each_safe (resource, next, &tablet->resource_list)
@@ -115,6 +132,53 @@ meta_wayland_tablet_free (MetaWaylandTablet *tablet)
   g_slice_free (MetaWaylandTablet, tablet);
 }
 
+static void
+meta_wayland_tablet_update_cursor_surface (MetaWaylandTablet *tablet)
+{
+  MetaCursorSprite *cursor = NULL;
+
+  if (tablet->cursor_renderer == NULL)
+    return;
+
+  if (tablet->current && tablet->current_tool)
+    {
+      if (tablet->cursor_surface && tablet->cursor_surface->buffer)
+        {
+          MetaWaylandSurfaceRoleCursor *cursor_role =
+            META_WAYLAND_SURFACE_ROLE_CURSOR (tablet->cursor_surface->role);
+
+          cursor = meta_wayland_surface_role_cursor_get_sprite (cursor_role, NULL, NULL);
+        }
+      else
+        cursor = NULL;
+    }
+  else if (tablet->current_tool)
+    cursor = meta_cursor_sprite_from_theme (META_CURSOR_CROSSHAIR);
+  else
+    cursor = NULL;
+
+  meta_cursor_renderer_set_cursor (tablet->cursor_renderer, cursor);
+}
+
+static void
+meta_wayland_tablet_set_cursor_surface (MetaWaylandTablet  *tablet,
+                                        MetaWaylandSurface *surface)
+{
+  if (tablet->cursor_surface == surface)
+    return;
+
+  if (tablet->cursor_surface)
+    wl_list_remove (&tablet->cursor_surface_destroy_listener.link);
+
+  tablet->cursor_surface = surface;
+
+  if (tablet->cursor_surface)
+    wl_resource_add_destroy_listener (tablet->cursor_surface->resource,
+                                      &tablet->cursor_surface_destroy_listener);
+
+  meta_wayland_tablet_update_cursor_surface (tablet);
+}
+
 static struct wl_resource *
 meta_wayland_tablet_ensure_tool_resource_for_client (MetaWaylandTablet *tablet,
                                                      struct wl_client  *client)
@@ -199,6 +263,8 @@ meta_wayland_tablet_set_focus (MetaWaylandTablet  *tablet,
             }
         }
     }
+
+  meta_wayland_tablet_update_cursor_surface (tablet);
 }
 
 static void
@@ -258,6 +324,7 @@ repick_for_event (MetaWaylandTablet  *tablet,
     tablet->current = NULL;
 
   sync_focus_surface (tablet);
+  meta_wayland_tablet_update_cursor_surface (tablet);
 }
 
 static MetaWaylandTabletTool *
@@ -313,6 +380,7 @@ meta_wayland_tablet_update (MetaWaylandTablet  *tablet,
       }
     case CLUTTER_PROXIMITY_OUT:
       tablet->current_tool = NULL;
+      meta_wayland_tablet_update_cursor_surface (tablet);
       break;
     default:
       break;
@@ -374,6 +442,42 @@ tablet_set_cursor (struct wl_client   *client,
                    int32_t             hotspot_x,
                    int32_t             hotspot_y)
 {
+  MetaWaylandTablet *tablet = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface;
+
+  surface = (surface_resource ? wl_resource_get_user_data (surface_resource) : NULL);
+
+  if (tablet->focus_surface == NULL)
+    return;
+  if (wl_resource_get_client (tablet->focus_surface->resource) != client)
+    return;
+  if (tablet->proximity_serial - serial > G_MAXUINT32 / 2)
+    return;
+
+  if (surface &&
+      !meta_wayland_surface_assign_role (surface,
+                                         META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR))
+    {
+      wl_resource_post_error (resource, WL_POINTER_ERROR_ROLE,
+                              "wl_surface %d already has a different role",
+                              wl_resource_get_id (surface_resource));
+      return;
+    }
+
+  if (surface)
+    {
+      MetaWaylandSurfaceRoleCursor *cursor_role;
+      MetaCursorSprite *sprite;
+
+      cursor_role = META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role);
+      sprite = meta_cursor_sprite_new ();
+      meta_wayland_surface_role_cursor_set_renderer (cursor_role,
+                                                     tablet->cursor_renderer);
+      meta_wayland_surface_role_cursor_set_sprite (cursor_role, sprite,
+                                                   hotspot_x, hotspot_y);
+    }
+
+  meta_wayland_tablet_set_cursor_surface (tablet, surface);
 }
 
 static const struct wl_tablet_interface tablet_interface = {
diff --git a/src/wayland/meta-wayland-tablet.h b/src/wayland/meta-wayland-tablet.h
index 6e6230f..f76a94d 100644
--- a/src/wayland/meta-wayland-tablet.h
+++ b/src/wayland/meta-wayland-tablet.h
@@ -45,6 +45,8 @@ struct _MetaWaylandTablet
   struct wl_listener focus_surface_destroy_listener;
 
   MetaCursorRenderer *cursor_renderer;
+  MetaWaylandSurface *cursor_surface;
+  struct wl_listener cursor_surface_destroy_listener;
 
   MetaWaylandSurface *current;
   GSList *buttons;


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