[mutter] seat: Listen for ClutterDeviceManager signals in order to update capabilities



commit ac448bd42be8cf8e46cadd7e1a209491e33b1693
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Jul 23 15:33:03 2014 +0200

    seat: Listen for ClutterDeviceManager signals in order to update capabilities
    
    The capability flags are determined from the device types of the slave devices
    that are currently attached. This also happens whenever a device is added or
    removed, so the capabilities are kept up to date, and clients know about these.
    
    On VT switch, all slave devices are temporarily removed, so the cascade of
    signals will make the seat end up with capabililities=0 while input is suspended.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=733563

 src/wayland/meta-wayland-seat.c |  134 ++++++++++++++++++++++++++++++++++++---
 src/wayland/meta-wayland-seat.h |    3 +
 2 files changed, 127 insertions(+), 10 deletions(-)
---
diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
index 3f12cca..9aaf516 100644
--- a/src/wayland/meta-wayland-seat.c
+++ b/src/wayland/meta-wayland-seat.c
@@ -27,6 +27,9 @@
 #include "meta-wayland-versions.h"
 #include "meta-wayland-data-device.h"
 
+#define CAPABILITY_ENABLED(prev, cur, capability) ((cur & (capability)) && !(prev & (capability)))
+#define CAPABILITY_DISABLED(prev, cur, capability) ((prev & (capability)) && !(cur & (capability)))
+
 static void
 unbind_resource (struct wl_resource *resource)
 {
@@ -86,27 +89,136 @@ bind_seat (struct wl_client *client,
   wl_resource_set_implementation (resource, &seat_interface, seat, unbind_resource);
   wl_list_insert (&seat->base_resource_list, wl_resource_get_link (resource));
 
-  wl_seat_send_capabilities (resource,
-                             WL_SEAT_CAPABILITY_POINTER |
-                             WL_SEAT_CAPABILITY_KEYBOARD |
-                             WL_SEAT_CAPABILITY_TOUCH);
+  wl_seat_send_capabilities (resource, seat->capabilities);
 
   if (version >= WL_SEAT_NAME_SINCE_VERSION)
     wl_seat_send_name (resource, "seat0");
 }
 
+static uint32_t
+lookup_device_capabilities (ClutterDeviceManager *device_manager)
+{
+  const GSList *devices, *l;
+  uint32_t capabilities = 0;
+
+  devices = clutter_device_manager_peek_devices (device_manager);
+
+  for (l = devices; l; l = l->next)
+    {
+      ClutterInputDeviceType device_type;
+
+      /* Only look for physical devices, master devices have rather generic
+       * keyboard/pointer device types, which is not truly representative of
+       * the slave devices connected to them.
+       */
+      if (clutter_input_device_get_device_mode (l->data) == CLUTTER_INPUT_MODE_MASTER)
+        continue;
+
+      device_type = clutter_input_device_get_device_type (l->data);
+
+      switch (device_type)
+        {
+        case CLUTTER_POINTER_DEVICE:
+          capabilities |= WL_SEAT_CAPABILITY_POINTER;
+          break;
+        case CLUTTER_KEYBOARD_DEVICE:
+          capabilities |= WL_SEAT_CAPABILITY_KEYBOARD;
+          break;
+        case CLUTTER_TOUCHSCREEN_DEVICE:
+          capabilities |= WL_SEAT_CAPABILITY_TOUCH;
+          break;
+        default:
+          g_debug ("Ignoring device '%s' with unhandled type %d",
+                   clutter_input_device_get_device_name (l->data),
+                   device_type);
+          break;
+        }
+    }
+
+  return capabilities;
+}
+
+static void
+meta_wayland_seat_set_capabilities (MetaWaylandSeat *seat,
+                                    uint32_t         flags)
+{
+  struct wl_resource *resource;
+  uint32_t prev_flags;
+
+  prev_flags = seat->capabilities;
+
+  if (prev_flags == flags)
+    return;
+
+  seat->capabilities = flags;
+
+  if (CAPABILITY_ENABLED (prev_flags, flags, WL_SEAT_CAPABILITY_POINTER))
+    meta_wayland_pointer_init (&seat->pointer, seat->wl_display);
+  else if (CAPABILITY_DISABLED (prev_flags, flags, WL_SEAT_CAPABILITY_POINTER))
+    meta_wayland_pointer_release (&seat->pointer);
+
+  if (CAPABILITY_ENABLED (prev_flags, flags, WL_SEAT_CAPABILITY_KEYBOARD))
+    {
+      MetaDisplay *display;
+
+      meta_wayland_keyboard_init (&seat->keyboard, seat->wl_display);
+      display = meta_get_display ();
+
+      /* Post-initialization, ensure the input focus is in sync */
+      if (display)
+        meta_display_sync_wayland_input_focus (display);
+    }
+  else if (CAPABILITY_DISABLED (prev_flags, flags, WL_SEAT_CAPABILITY_KEYBOARD))
+    meta_wayland_keyboard_release (&seat->keyboard);
+
+  if (CAPABILITY_ENABLED (prev_flags, flags, WL_SEAT_CAPABILITY_TOUCH))
+    meta_wayland_touch_init (&seat->touch, seat->wl_display);
+  else if (CAPABILITY_DISABLED (prev_flags, flags, WL_SEAT_CAPABILITY_TOUCH))
+    meta_wayland_touch_release (&seat->touch);
+
+  /* Broadcast capability changes */
+  wl_resource_for_each (resource, &seat->base_resource_list)
+    {
+      wl_seat_send_capabilities (resource, flags);
+    }
+}
+
+static void
+meta_wayland_seat_update_capabilities (MetaWaylandSeat      *seat,
+                                       ClutterDeviceManager *device_manager)
+{
+  uint32_t capabilities;
+
+  capabilities = lookup_device_capabilities (device_manager);
+  meta_wayland_seat_set_capabilities (seat, capabilities);
+}
+
+static void
+meta_wayland_seat_devices_updated (ClutterDeviceManager *device_manager,
+                                   ClutterInputDevice   *input_device,
+                                   MetaWaylandSeat      *seat)
+{
+  meta_wayland_seat_update_capabilities (seat, device_manager);
+}
+
 static MetaWaylandSeat *
 meta_wayland_seat_new (struct wl_display *display)
 {
   MetaWaylandSeat *seat = g_new0 (MetaWaylandSeat, 1);
+  ClutterDeviceManager *device_manager;
 
   wl_list_init (&seat->base_resource_list);
+  seat->wl_display = display;
 
-  meta_wayland_pointer_init (&seat->pointer, display);
-  meta_wayland_keyboard_init (&seat->keyboard, display);
-  meta_wayland_touch_init (&seat->touch, display);
   meta_wayland_data_device_init (&seat->data_device);
 
+  device_manager = clutter_device_manager_get_default ();
+  meta_wayland_seat_update_capabilities (seat, device_manager);
+  g_signal_connect (device_manager, "device-added",
+                    G_CALLBACK (meta_wayland_seat_devices_updated), seat);
+  g_signal_connect (device_manager, "device-removed",
+                    G_CALLBACK (meta_wayland_seat_devices_updated), seat);
+
   wl_global_create (display, &wl_seat_interface, META_WL_SEAT_VERSION, seat, bind_seat);
 
   return seat;
@@ -121,9 +233,11 @@ meta_wayland_seat_init (MetaWaylandCompositor *compositor)
 void
 meta_wayland_seat_free (MetaWaylandSeat *seat)
 {
-  meta_wayland_pointer_release (&seat->pointer);
-  meta_wayland_keyboard_release (&seat->keyboard);
-  meta_wayland_touch_release (&seat->touch);
+  ClutterDeviceManager *device_manager;
+
+  device_manager = clutter_device_manager_get_default ();
+  g_signal_handlers_disconnect_by_data (device_manager, seat);
+  meta_wayland_seat_set_capabilities (seat, 0);
 
   g_slice_free (MetaWaylandSeat, seat);
 }
diff --git a/src/wayland/meta-wayland-seat.h b/src/wayland/meta-wayland-seat.h
index e9b52fb..ee8e3d7 100644
--- a/src/wayland/meta-wayland-seat.h
+++ b/src/wayland/meta-wayland-seat.h
@@ -34,11 +34,14 @@
 struct _MetaWaylandSeat
 {
   struct wl_list base_resource_list;
+  struct wl_display *wl_display;
 
   MetaWaylandPointer pointer;
   MetaWaylandKeyboard keyboard;
   MetaWaylandTouch touch;
   MetaWaylandDataDevice data_device;
+
+  guint capabilities;
 };
 
 void meta_wayland_seat_init (MetaWaylandCompositor *compositor);


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