[mutter/wip/tablet-protocol: 96/100] wayland: Implement wl_tablet_tool.set_cursor



commit ea69647921a0f8c92d6f1122d620ae148a2d7c94
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Oct 28 12:55:58 2015 +0100

    wayland: Implement wl_tablet_tool.set_cursor
    
    Each tool has its own MetaCursorRenderer instance, which is created/destroyed
    upon proximity, and possibly updated through focus and set_cursor calls in
    between.

 src/wayland/meta-wayland-tablet-tool.c |  107 ++++++++++++++++++++++++++++++++
 src/wayland/meta-wayland-tablet-tool.h |    4 +
 2 files changed, 111 insertions(+), 0 deletions(-)
---
diff --git a/src/wayland/meta-wayland-tablet-tool.c b/src/wayland/meta-wayland-tablet-tool.c
index bf5d2e8..1ae55bb 100644
--- a/src/wayland/meta-wayland-tablet-tool.c
+++ b/src/wayland/meta-wayland-tablet-tool.c
@@ -30,6 +30,7 @@
 #include <wayland-server.h>
 #include "tablet-unstable-v1-server-protocol.h"
 #include "meta-wayland-private.h"
+#include "meta-wayland-surface-role-cursor.h"
 #include "meta-surface-actor-wayland.h"
 #include "meta-wayland-tablet.h"
 #include "meta-wayland-tablet-seat.h"
@@ -68,6 +69,53 @@ move_resources_for_client (struct wl_list   *destination,
     }
 }
 
+static void
+meta_wayland_tablet_tool_update_cursor_surface (MetaWaylandTabletTool *tool)
+{
+  MetaCursorSprite *cursor = NULL;
+
+  if (tool->cursor_renderer == NULL)
+    return;
+
+  if (tool->current && tool->current_tablet)
+    {
+      if (tool->cursor_surface && tool->cursor_surface->buffer)
+        {
+          MetaWaylandSurfaceRoleCursor *cursor_role =
+            META_WAYLAND_SURFACE_ROLE_CURSOR (tool->cursor_surface->role);
+
+          cursor = meta_wayland_surface_role_cursor_get_sprite (cursor_role);
+        }
+      else
+        cursor = NULL;
+    }
+  else if (tool->current_tablet)
+    cursor = meta_cursor_sprite_from_theme (META_CURSOR_CROSSHAIR);
+  else
+    cursor = NULL;
+
+  meta_cursor_renderer_set_cursor (tool->cursor_renderer, cursor);
+}
+
+static void
+meta_wayland_tablet_tool_set_cursor_surface (MetaWaylandTabletTool *tool,
+                                             MetaWaylandSurface    *surface)
+{
+  if (tool->cursor_surface == surface)
+    return;
+
+  if (tool->cursor_surface)
+    wl_list_remove (&tool->cursor_surface_destroy_listener.link);
+
+  tool->cursor_surface = surface;
+
+  if (tool->cursor_surface)
+    wl_resource_add_destroy_listener (tool->cursor_surface->resource,
+                                      &tool->cursor_surface_destroy_listener);
+
+  meta_wayland_tablet_tool_update_cursor_surface (tool);
+}
+
 static guint32
 input_device_get_capabilities (ClutterInputDevice *device)
 {
@@ -190,6 +238,8 @@ meta_wayland_tablet_tool_set_focus (MetaWaylandTabletTool *tool,
           broadcast_frame (tool, event);
         }
     }
+
+  meta_wayland_tablet_tool_update_cursor_surface (tool);
 }
 
 static void
@@ -202,6 +252,16 @@ tablet_tool_handle_focus_surface_destroy (struct wl_listener *listener,
   meta_wayland_tablet_tool_set_focus (tool, NULL, NULL);
 }
 
+static void
+tablet_tool_handle_cursor_surface_destroy (struct wl_listener *listener,
+                                           void               *data)
+{
+  MetaWaylandTabletTool *tool;
+
+  tool = wl_container_of (listener, tool, cursor_surface_destroy_listener);
+  meta_wayland_tablet_tool_set_cursor_surface (tool, NULL);
+}
+
 MetaWaylandTabletTool *
 meta_wayland_tablet_tool_new (MetaWaylandTabletSeat  *seat,
                               ClutterInputDevice     *device,
@@ -217,6 +277,7 @@ meta_wayland_tablet_tool_new (MetaWaylandTabletSeat  *seat,
   wl_list_init (&tool->focus_resource_list);
 
   tool->focus_surface_destroy_listener.notify = tablet_tool_handle_focus_surface_destroy;
+  tool->cursor_surface_destroy_listener.notify = tablet_tool_handle_cursor_surface_destroy;
 
   return tool;
 }
@@ -227,6 +288,8 @@ meta_wayland_tablet_tool_free (MetaWaylandTabletTool *tool)
   struct wl_resource *resource, *next;
 
   meta_wayland_tablet_tool_set_focus (tool, NULL, NULL);
+  meta_wayland_tablet_tool_set_cursor_surface (tool, NULL);
+  g_clear_object (&tool->cursor_renderer);
 
   wl_resource_for_each_safe (resource, next, &tool->resource_list)
     {
@@ -245,6 +308,42 @@ tool_set_cursor (struct wl_client   *client,
                  int32_t             hotspot_x,
                  int32_t             hotspot_y)
 {
+  MetaWaylandTabletTool *tool = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface;
+
+  surface = (surface_resource ? wl_resource_get_user_data (surface_resource) : NULL);
+
+  if (tool->focus_surface == NULL)
+    return;
+  if (tool->cursor_renderer == NULL)
+    return;
+  if (wl_resource_get_client (tool->focus_surface->resource) != client)
+    return;
+  if (tool->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;
+
+      cursor_role = META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role);
+      meta_wayland_surface_role_cursor_set_renderer (cursor_role,
+                                                     tool->cursor_renderer);
+      meta_wayland_surface_role_cursor_set_hotspot (cursor_role,
+                                                    hotspot_x, hotspot_y);
+    }
+
+  meta_wayland_tablet_tool_set_cursor_surface (tool, surface);
 }
 
 static void
@@ -369,6 +468,7 @@ repick_for_event (MetaWaylandTabletTool *tool,
     tool->current = NULL;
 
   sync_focus_surface (tool, for_event);
+  meta_wayland_tablet_tool_update_cursor_surface (tool);
 }
 
 static void
@@ -574,10 +674,17 @@ meta_wayland_tablet_tool_update (MetaWaylandTabletTool *tool,
         repick_for_event (tool, event);
       break;
     case CLUTTER_PROXIMITY_IN:
+      if (!tool->cursor_renderer)
+        tool->cursor_renderer = meta_cursor_renderer_new ();
       tool->current_tablet =
         meta_wayland_tablet_seat_lookup_tablet (tool->seat,
                                                 clutter_event_get_source_device (event));
       break;
+    case CLUTTER_PROXIMITY_OUT:
+      tool->current_tablet = NULL;
+      meta_wayland_tablet_tool_update_cursor_surface (tool);
+      g_clear_object (&tool->cursor_renderer);
+      break;
     default:
       break;
     }
diff --git a/src/wayland/meta-wayland-tablet-tool.h b/src/wayland/meta-wayland-tablet-tool.h
index fbbe85a..da680e4 100644
--- a/src/wayland/meta-wayland-tablet-tool.h
+++ b/src/wayland/meta-wayland-tablet-tool.h
@@ -40,6 +40,10 @@ struct _MetaWaylandTabletTool
   MetaWaylandSurface *focus_surface;
   struct wl_listener focus_surface_destroy_listener;
 
+  MetaWaylandSurface *cursor_surface;
+  struct wl_listener cursor_surface_destroy_listener;
+  MetaCursorRenderer *cursor_renderer;
+
   MetaWaylandSurface *current;
   guint32 pressed_buttons;
 


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