[mutter] wayland: Add focus management to pads



commit c1d157e13692a521375dce3b47bd6b9257247cfc
Author: Carlos Garnacho <carlosg gnome org>
Date:   Tue May 10 17:29:57 2016 +0200

    wayland: Add focus management to pads
    
    All pads will share the same focus than the keyboard, so this means that:
    - The focus changes in-sync for keyboard and all pad devices, and
    - Newly plugged pads will be immediately focused on that same surface

 src/wayland/meta-wayland-seat.c        |   15 ++++--
 src/wayland/meta-wayland-tablet-pad.c  |   88 ++++++++++++++++++++++++++++++++
 src/wayland/meta-wayland-tablet-seat.c |   35 +++++++++++++
 src/wayland/meta-wayland-tablet-seat.h |    3 +
 4 files changed, 137 insertions(+), 4 deletions(-)
---
diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
index 9a7fa2e..a235a81 100644
--- a/src/wayland/meta-wayland-seat.c
+++ b/src/wayland/meta-wayland-seat.c
@@ -26,6 +26,7 @@
 #include "meta-wayland-private.h"
 #include "meta-wayland-versions.h"
 #include "meta-wayland-data-device.h"
+#include "meta-wayland-tablet-seat.h"
 
 #define CAPABILITY_ENABLED(prev, cur, capability) ((cur & (capability)) && !(prev & (capability)))
 #define CAPABILITY_DISABLED(prev, cur, capability) ((prev & (capability)) && !(cur & (capability)))
@@ -369,11 +370,17 @@ void
 meta_wayland_seat_set_input_focus (MetaWaylandSeat    *seat,
                                    MetaWaylandSurface *surface)
 {
-  if ((seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD) == 0)
-    return;
+  MetaWaylandTabletSeat *tablet_seat;
+  MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
+
+  if ((seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD) != 0)
+    {
+      meta_wayland_keyboard_set_focus (&seat->keyboard, surface);
+      meta_wayland_data_device_set_keyboard_focus (&seat->data_device);
+    }
 
-  meta_wayland_keyboard_set_focus (&seat->keyboard, surface);
-  meta_wayland_data_device_set_keyboard_focus (&seat->data_device);
+  tablet_seat = meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat);
+  meta_wayland_tablet_seat_set_pad_focus (tablet_seat, surface);
 }
 
 gboolean
diff --git a/src/wayland/meta-wayland-tablet-pad.c b/src/wayland/meta-wayland-tablet-pad.c
index c83169f..0b4a228 100644
--- a/src/wayland/meta-wayland-tablet-pad.c
+++ b/src/wayland/meta-wayland-tablet-pad.c
@@ -32,6 +32,8 @@
 
 #include "meta-surface-actor-wayland.h"
 #include "meta-wayland-private.h"
+#include "meta-wayland-tablet-seat.h"
+#include "meta-wayland-tablet.h"
 #include "meta-wayland-tablet-pad.h"
 #include "meta-wayland-tablet-pad-group.h"
 #include "meta-wayland-tablet-pad-ring.h"
@@ -295,8 +297,94 @@ meta_wayland_tablet_pad_update_groups_focus (MetaWaylandTabletPad *pad)
     meta_wayland_tablet_pad_group_sync_focus (l->data);
 }
 
+static void
+meta_wayland_tablet_pad_broadcast_enter (MetaWaylandTabletPad *pad,
+                                         uint32_t              serial,
+                                         MetaWaylandTablet    *tablet,
+                                         MetaWaylandSurface   *surface)
+{
+  struct wl_resource *resource, *tablet_resource;
+  struct wl_client *client;
+
+  client = wl_resource_get_client (pad->focus_surface->resource);
+  tablet_resource = meta_wayland_tablet_lookup_resource (tablet, client);
+
+  wl_resource_for_each (resource, &pad->focus_resource_list)
+    {
+      zwp_tablet_pad_v2_send_enter (resource, serial,
+                                    tablet_resource,
+                                    surface->resource);
+    }
+}
+
+static void
+meta_wayland_tablet_pad_broadcast_leave (MetaWaylandTabletPad *pad,
+                                         uint32_t              serial,
+                                         MetaWaylandSurface   *surface)
+{
+  struct wl_resource *resource;
+
+  wl_resource_for_each (resource, &pad->focus_resource_list)
+    {
+      zwp_tablet_pad_v2_send_leave (resource, serial,
+                                    surface->resource);
+    }
+}
+
 void
 meta_wayland_tablet_pad_set_focus (MetaWaylandTabletPad *pad,
                                    MetaWaylandSurface   *surface)
 {
+  MetaWaylandTablet *tablet;
+
+  if (pad->focus_surface == surface)
+    return;
+
+  g_hash_table_remove_all (pad->feedback);
+
+  if (pad->focus_surface != NULL)
+    {
+      struct wl_client *client = wl_resource_get_client (pad->focus_surface->resource);
+      struct wl_list *focus_resources = &pad->focus_resource_list;
+
+      if (!wl_list_empty (focus_resources))
+        {
+          struct wl_display *display = wl_client_get_display (client);
+          uint32_t serial = wl_display_next_serial (display);
+
+          meta_wayland_tablet_pad_broadcast_leave (pad, serial,
+                                                   pad->focus_surface);
+          move_resources (&pad->resource_list, &pad->focus_resource_list);
+        }
+
+      wl_list_remove (&pad->focus_surface_listener.link);
+      pad->focus_surface = NULL;
+    }
+
+  tablet = meta_wayland_tablet_seat_lookup_paired_tablet (pad->tablet_seat,
+                                                          pad);
+
+  if (tablet != NULL && surface != NULL)
+    {
+      struct wl_client *client;
+
+      pad->focus_surface = surface;
+      wl_resource_add_destroy_listener (pad->focus_surface->resource,
+                                        &pad->focus_surface_listener);
+
+      client = wl_resource_get_client (pad->focus_surface->resource);
+      move_resources_for_client (&pad->focus_resource_list,
+                                 &pad->resource_list, client);
+
+      if (!wl_list_empty (&pad->focus_resource_list))
+        {
+          struct wl_display *display = wl_client_get_display (client);
+
+          pad->focus_serial = wl_display_next_serial (display);
+          meta_wayland_tablet_pad_broadcast_enter (pad, pad->focus_serial,
+                                                   tablet, pad->focus_surface);
+        }
+    }
+
+  meta_wayland_tablet_pad_update_groups_focus (pad);
 }
diff --git a/src/wayland/meta-wayland-tablet-seat.c b/src/wayland/meta-wayland-tablet-seat.c
index 7b9a07e..3bf42c5 100644
--- a/src/wayland/meta-wayland-tablet-seat.c
+++ b/src/wayland/meta-wayland-tablet-seat.c
@@ -36,6 +36,11 @@
 #include "meta-wayland-tablet-tool.h"
 #include "meta-wayland-tablet-pad.h"
 
+#ifdef HAVE_NATIVE_BACKEND
+#include <clutter/evdev/clutter-evdev.h>
+#include "backends/native/meta-backend-native.h"
+#endif
+
 static void
 unbind_resource (struct wl_resource *resource)
 {
@@ -199,13 +204,28 @@ static void
 meta_wayland_tablet_seat_device_added (MetaWaylandTabletSeat *tablet_seat,
                                        ClutterInputDevice    *device)
 {
+  MetaWaylandSurface *pad_focus = tablet_seat->seat->keyboard.focus_surface;
+
   if (is_tablet_device (device))
     {
       MetaWaylandTablet *tablet;
+      GList *pads, *l;
 
       tablet = meta_wayland_tablet_new (device, tablet_seat);
       g_hash_table_insert (tablet_seat->tablets, device, tablet);
       broadcast_tablet_added (tablet_seat, device);
+
+      /* Because the insertion order is undefined, there might be already
+       * pads that are logically paired to this tablet. Look those up and
+       * refocus them.
+       */
+      pads = meta_wayland_tablet_seat_lookup_paired_pads (tablet_seat,
+                                                          tablet);
+
+      for (l = pads; l; l = l->next)
+        meta_wayland_tablet_pad_set_focus (l->data, pad_focus);
+
+      g_list_free (pads);
     }
   else if (is_pad_device (device))
     {
@@ -214,6 +234,8 @@ meta_wayland_tablet_seat_device_added (MetaWaylandTabletSeat *tablet_seat,
       pad = meta_wayland_tablet_pad_new (device, tablet_seat);
       g_hash_table_insert (tablet_seat->pads, device, pad);
       broadcast_pad_added (tablet_seat, device);
+
+      meta_wayland_tablet_pad_set_focus (pad, pad_focus);
     }
 }
 
@@ -524,3 +546,16 @@ meta_wayland_tablet_seat_lookup_paired_pads (MetaWaylandTabletSeat *tablet_seat,
 
   return pads;
 }
+
+void
+meta_wayland_tablet_seat_set_pad_focus (MetaWaylandTabletSeat *tablet_seat,
+                                        MetaWaylandSurface    *surface)
+{
+  MetaWaylandTabletPad *pad;
+  GHashTableIter iter;
+
+  g_hash_table_iter_init (&iter, tablet_seat->pads);
+
+  while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &pad))
+    meta_wayland_tablet_pad_set_focus (pad, surface);
+}
diff --git a/src/wayland/meta-wayland-tablet-seat.h b/src/wayland/meta-wayland-tablet-seat.h
index 98ce4a9..e923f93 100644
--- a/src/wayland/meta-wayland-tablet-seat.h
+++ b/src/wayland/meta-wayland-tablet-seat.h
@@ -69,6 +69,9 @@ void                   meta_wayland_tablet_seat_notify_tool         (MetaWayland
                                                                      MetaWaylandTabletTool *tool,
                                                                      struct wl_client      *client);
 
+void                   meta_wayland_tablet_seat_set_pad_focus       (MetaWaylandTabletSeat *tablet_seat,
+                                                                     MetaWaylandSurface    *surface);
+
 MetaWaylandTablet     *meta_wayland_tablet_seat_lookup_paired_tablet (MetaWaylandTabletSeat *tablet_seat,
                                                                       MetaWaylandTabletPad  *pad);
 GList                 *meta_wayland_tablet_seat_lookup_paired_pads   (MetaWaylandTabletSeat *tablet_seat,


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