[mutter] pointer/keyboard: Support more than one focused resource



commit 339a78718dad817bbdfc7ba7056fc0371c89d9aa
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Wed Apr 16 15:11:10 2014 -0400

    pointer/keyboard: Support more than one focused resource
    
    Sophisticated clients, like those using ClutterGtk, will have more
    than one focused resource per client, as both Clutter and GDK will
    ask for a wl_pointer / wl_keyboard. Support this naturally using
    the same "hack" as Weston: multiple resource lists, where we move
    elements from one to the other.

 src/wayland/meta-wayland-keyboard.c |  102 +++++++++++++++++++++++------------
 src/wayland/meta-wayland-keyboard.h |    2 +-
 src/wayland/meta-wayland-pointer.c  |   80 ++++++++++++++++++---------
 src/wayland/meta-wayland-pointer.h  |    2 +-
 src/wayland/meta-wayland-seat.c     |   21 ++++---
 5 files changed, 135 insertions(+), 72 deletions(-)
---
diff --git a/src/wayland/meta-wayland-keyboard.c b/src/wayland/meta-wayland-keyboard.c
index cb227a9..08e0934 100644
--- a/src/wayland/meta-wayland-keyboard.c
+++ b/src/wayland/meta-wayland-keyboard.c
@@ -211,7 +211,6 @@ keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
   MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_surface_listener);
 
   keyboard->focus_surface = NULL;
-  keyboard->focus_resource = NULL;
 }
 
 static gboolean
@@ -220,34 +219,47 @@ default_grab_key (MetaWaylandKeyboardGrab *grab,
 {
   MetaWaylandKeyboard *keyboard = grab->keyboard;
   struct wl_resource *resource;
-  uint32_t serial;
+  struct wl_list *l;
 
-  resource = keyboard->focus_resource;
-  if (resource)
+  l = &keyboard->focus_resource_list;
+  if (!wl_list_empty (l))
     {
       struct wl_client *client = wl_resource_get_client (keyboard->focus_surface->resource);
       struct wl_display *display = wl_client_get_display (client);
-      serial = wl_display_next_serial (display);
-      wl_keyboard_send_key (resource, serial, time, key, state);
+      uint32_t serial = wl_display_next_serial (display);
+
+      wl_resource_for_each (resource, l)
+        {
+          wl_keyboard_send_key (resource, serial, time, key, state);
+        }
+
+      return TRUE;
     }
 
-  return resource != NULL;
+  return FALSE;
 }
 
-static struct wl_resource *
-find_resource_for_surface (struct wl_list *list, MetaWaylandSurface *surface)
+static void
+move_resources (struct wl_list *destination, struct wl_list *source)
 {
-  struct wl_client *client;
-
-  if (!surface)
-    return NULL;
-
-  if (!surface->resource)
-    return NULL;
-
-  client = wl_resource_get_client (surface->resource);
+  wl_list_insert_list (destination, source);
+  wl_list_init (source);
+}
 
-  return wl_resource_find_for_client (list, client);
+static void
+move_resources_for_client (struct wl_list *destination,
+                          struct wl_list *source,
+                          struct wl_client *client)
+{
+  struct wl_resource *resource, *tmp;
+  wl_resource_for_each_safe (resource, tmp, source)
+    {
+      if (wl_resource_get_client (resource) == client)
+        {
+          wl_list_remove (wl_resource_get_link (resource));
+          wl_list_insert (destination, wl_resource_get_link (resource));
+        }
+    }
 }
 
 static void
@@ -256,10 +268,13 @@ default_grab_modifiers (MetaWaylandKeyboardGrab *grab, uint32_t serial,
                         uint32_t mods_locked, uint32_t group)
 {
   MetaWaylandKeyboard *keyboard = grab->keyboard;
+  struct wl_resource *resource;
+  struct wl_list *l;
 
-  if (keyboard->focus_resource)
+  l = &keyboard->focus_resource_list;
+  wl_resource_for_each (resource, l)
     {
-      wl_keyboard_send_modifiers (keyboard->focus_resource, serial, mods_depressed,
+      wl_keyboard_send_modifiers (resource, serial, mods_depressed,
                                   mods_latched, mods_locked, group);
     }
 }
@@ -278,6 +293,7 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
   keyboard->xkb_info.keymap_fd = -1;
 
   wl_list_init (&keyboard->resource_list);
+  wl_list_init (&keyboard->focus_resource_list);
   wl_array_init (&keyboard->keys);
 
   keyboard->focus_surface_listener.notify = keyboard_handle_focus_surface_destroy;
@@ -418,19 +434,27 @@ void
 meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
                                  MetaWaylandSurface *surface)
 {
-  if (keyboard->focus_surface == surface && keyboard->focus_resource != NULL)
+  if (keyboard->focus_surface == surface && !wl_list_empty (&keyboard->focus_resource_list))
     return;
 
   if (keyboard->focus_surface != NULL)
     {
-      if (keyboard->focus_resource)
+      struct wl_resource *resource;
+      struct wl_list *l;
+
+      l = &keyboard->focus_resource_list;
+      if (!wl_list_empty (l))
         {
           struct wl_client *client = wl_resource_get_client (keyboard->focus_surface->resource);
           struct wl_display *display = wl_client_get_display (client);
           uint32_t serial = wl_display_next_serial (display);
-          wl_keyboard_send_leave (keyboard->focus_resource, serial, keyboard->focus_surface->resource);
 
-          keyboard->focus_resource = NULL;
+          wl_resource_for_each (resource, l)
+            {
+              wl_keyboard_send_leave (resource, serial, keyboard->focus_surface->resource);
+            }
+
+          move_resources (&keyboard->resource_list, &keyboard->focus_resource_list);
         }
 
       wl_list_remove (&keyboard->focus_surface_listener.link);
@@ -439,24 +463,34 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
 
   if (surface != NULL)
     {
+      struct wl_resource *resource;
+      struct wl_list *l;
+
       keyboard->focus_surface = surface;
       wl_resource_add_destroy_listener (keyboard->focus_surface->resource, 
&keyboard->focus_surface_listener);
 
-      keyboard->focus_resource = find_resource_for_surface (&keyboard->resource_list, surface);
-      if (keyboard->focus_resource)
+      move_resources_for_client (&keyboard->focus_resource_list,
+                                 &keyboard->resource_list,
+                                 wl_resource_get_client (keyboard->focus_surface->resource));
+
+      l = &keyboard->focus_resource_list;
+      if (!wl_list_empty (l))
         {
           struct wl_client *client = wl_resource_get_client (keyboard->focus_surface->resource);
           struct wl_display *display = wl_client_get_display (client);
           struct xkb_state *state = keyboard->xkb_info.state;
           uint32_t serial = wl_display_next_serial (display);
 
-          wl_keyboard_send_modifiers (keyboard->focus_resource, serial,
-                                      xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
-                                      xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
-                                      xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
-                                      xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
-          wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource,
-                                  &keyboard->keys);
+          wl_resource_for_each (resource, l)
+            {
+              wl_keyboard_send_modifiers (resource, serial,
+                                          xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
+                                          xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
+                                          xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
+                                          xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
+              wl_keyboard_send_enter (resource, serial, keyboard->focus_surface->resource,
+                                      &keyboard->keys);
+            }
 
           keyboard->focus_serial = serial;
         }
diff --git a/src/wayland/meta-wayland-keyboard.h b/src/wayland/meta-wayland-keyboard.h
index f67d02f..38011c9 100644
--- a/src/wayland/meta-wayland-keyboard.h
+++ b/src/wayland/meta-wayland-keyboard.h
@@ -78,10 +78,10 @@ typedef struct
 struct _MetaWaylandKeyboard
 {
   struct wl_list resource_list;
+  struct wl_list focus_resource_list;
 
   MetaWaylandSurface *focus_surface;
   struct wl_listener focus_surface_listener;
-  struct wl_resource *focus_resource;
   uint32_t focus_serial;
 
   MetaWaylandKeyboardGrab *grab;
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 7ed2255..f5535a6 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -60,7 +60,6 @@ pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
   MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener);
 
   pointer->focus_surface = NULL;
-  pointer->focus_resource = NULL;
 }
 
 static void
@@ -81,9 +80,10 @@ default_grab_motion (MetaWaylandPointerGrab *grab,
 {
   MetaWaylandPointer *pointer = grab->pointer;
   struct wl_resource *resource;
+  struct wl_list *l;
 
-  resource = pointer->focus_resource;
-  if (resource)
+  l = &pointer->focus_resource_list;
+  wl_resource_for_each(resource, l)
     {
       wl_fixed_t sx, sy;
 
@@ -100,12 +100,13 @@ default_grab_button (MetaWaylandPointerGrab *grab,
 {
   MetaWaylandPointer *pointer = grab->pointer;
   struct wl_resource *resource;
+  struct wl_list *l;
   ClutterEventType event_type;
 
   event_type = clutter_event_type (event);
 
-  resource = pointer->focus_resource;
-  if (resource)
+  l = &grab->pointer->focus_resource_list;
+  wl_resource_for_each(resource, l)
     {
       struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource);
       struct wl_display *display = wl_client_get_display (client);
@@ -256,6 +257,7 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer)
 
   memset (pointer, 0, sizeof *pointer);
   wl_list_init (&pointer->resource_list);
+  wl_list_init (&pointer->focus_resource_list);
 
   pointer->focus_surface_listener.notify = pointer_handle_focus_surface_destroy;
 
@@ -288,37 +290,54 @@ meta_wayland_pointer_release (MetaWaylandPointer *pointer)
   /* Do nothing. */
 }
 
-static struct wl_resource *
-find_resource_for_surface (struct wl_list *list, MetaWaylandSurface *surface)
+static void
+move_resources (struct wl_list *destination, struct wl_list *source)
 {
-  struct wl_client *client;
-
-  if (!surface)
-    return NULL;
-
-  g_assert (surface->resource);
-  client = wl_resource_get_client (surface->resource);
+  wl_list_insert_list (destination, source);
+  wl_list_init (source);
+}
 
-  return wl_resource_find_for_client (list, client);
+static void
+move_resources_for_client (struct wl_list *destination,
+                          struct wl_list *source,
+                          struct wl_client *client)
+{
+  struct wl_resource *resource, *tmp;
+  wl_resource_for_each_safe (resource, tmp, source)
+    {
+      if (wl_resource_get_client (resource) == client)
+        {
+          wl_list_remove (wl_resource_get_link (resource));
+          wl_list_insert (destination, wl_resource_get_link (resource));
+        }
+    }
 }
 
 void
 meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
                                 MetaWaylandSurface *surface)
 {
-  if (pointer->focus_surface == surface && pointer->focus_resource != NULL)
+  if (pointer->focus_surface == surface && !wl_list_empty (&pointer->focus_resource_list))
     return;
 
   if (pointer->focus_surface)
     {
-      if (pointer->focus_resource)
+      struct wl_resource *resource;
+      struct wl_list *l;
+
+      l = &pointer->focus_resource_list;
+      if (!wl_list_empty (l))
         {
           struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource);
           struct wl_display *display = wl_client_get_display (client);
           uint32_t serial = wl_display_next_serial (display);
-          wl_pointer_send_leave (pointer->focus_resource, serial, pointer->focus_surface->resource);
 
-          pointer->focus_resource = NULL;
+          wl_resource_for_each (resource, l)
+            {
+              wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource);
+            }
+
+          move_resources (&pointer->resource_list, &pointer->focus_resource_list);
         }
 
       wl_list_remove (&pointer->focus_surface_listener.link);
@@ -327,6 +346,9 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
 
   if (surface != NULL)
     {
+      struct wl_resource *resource;
+      struct wl_list *l;
+
       pointer->focus_surface = surface;
       wl_resource_add_destroy_listener (pointer->focus_surface->resource, &pointer->focus_surface_listener);
 
@@ -336,19 +358,24 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
                                 wl_fixed_to_int (pointer->x),
                                 wl_fixed_to_int (pointer->y));
 
-      pointer->focus_resource = find_resource_for_surface (&pointer->resource_list, surface);
-      if (pointer->focus_resource)
+      move_resources_for_client (&pointer->focus_resource_list,
+                                 &pointer->resource_list,
+                                 wl_resource_get_client (pointer->focus_surface->resource));
+
+      l = &pointer->focus_resource_list;
+      if (!wl_list_empty (l))
         {
           struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource);
           struct wl_display *display = wl_client_get_display (client);
           uint32_t serial = wl_display_next_serial (display);
 
-          {
-            wl_fixed_t sx, sy;
+          wl_resource_for_each (resource, l)
+            {
+              wl_fixed_t sx, sy;
 
-            meta_wayland_pointer_get_relative_coordinates (pointer, pointer->focus_surface, &sx, &sy);
-            wl_pointer_send_enter (pointer->focus_resource, serial, pointer->focus_surface->resource, sx, 
sy);
-          }
+              meta_wayland_pointer_get_relative_coordinates (pointer, pointer->focus_surface, &sx, &sy);
+              wl_pointer_send_enter (resource, serial, pointer->focus_surface->resource, sx, sy);
+            }
 
           pointer->focus_serial = serial;
         }
@@ -419,7 +446,6 @@ static void
 popup_grab_button (MetaWaylandPointerGrab *grab,
                   const ClutterEvent     *event)
 {
-  MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)grab;
   MetaWaylandPointer *pointer = grab->pointer;
 
   if (pointer->focus_surface)
diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h
index 98b536c..43c82fb 100644
--- a/src/wayland/meta-wayland-pointer.h
+++ b/src/wayland/meta-wayland-pointer.h
@@ -45,10 +45,10 @@ struct _MetaWaylandPointerGrab
 struct _MetaWaylandPointer
 {
   struct wl_list resource_list;
+  struct wl_list focus_resource_list;
 
   MetaWaylandSurface *focus_surface;
   struct wl_listener focus_surface_listener;
-  struct wl_resource *focus_resource;
   guint32 focus_serial;
   guint32 click_serial;
 
diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
index 24280d3..3484d08 100644
--- a/src/wayland/meta-wayland-seat.c
+++ b/src/wayland/meta-wayland-seat.c
@@ -301,13 +301,12 @@ static void
 handle_scroll_event (MetaWaylandSeat    *seat,
                      const ClutterEvent *event)
 {
+  struct wl_resource *resource;
+  struct wl_list *l;
   wl_fixed_t x_value = 0, y_value = 0;
 
   notify_motion (seat, event);
 
-  if (!seat->pointer.focus_resource)
-    return;
-
   if (clutter_event_is_pointer_emulated (event))
     return;
 
@@ -342,12 +341,16 @@ handle_scroll_event (MetaWaylandSeat    *seat,
       return;
     }
 
-  if (x_value)
-    wl_pointer_send_axis (seat->pointer.focus_resource, clutter_event_get_time (event),
-                          WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value);
-  if (y_value)
-    wl_pointer_send_axis (seat->pointer.focus_resource, clutter_event_get_time (event),
-                          WL_POINTER_AXIS_VERTICAL_SCROLL, y_value);
+  l = &seat->pointer.focus_resource_list;
+  wl_resource_for_each (resource, l)
+    {
+      if (x_value)
+        wl_pointer_send_axis (resource, clutter_event_get_time (event),
+                              WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value);
+      if (y_value)
+        wl_pointer_send_axis (resource, clutter_event_get_time (event),
+                              WL_POINTER_AXIS_VERTICAL_SCROLL, y_value);
+    }
 }
 
 static int


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