[mutter/wayland] pointer/keyboard: Make sure not to get stale on client resources as well



commit a364c2a96bf77d42608b9a2ab1352efc46251785
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Tue Feb 18 18:00:26 2014 -0500

    pointer/keyboard: Make sure not to get stale on client resources as well
    
    Both the pointer/keyboard resource and surface resource can be destroyed
    at any point in the destruction process, so we need to have destroy
    listeners on both. To make the code easier to follow, rename ->focus
    to ->focus_surface at the same time, and rearrange the code so that
    the two of them are always grouped together.

 src/wayland/meta-wayland-keyboard.c |   65 +++++++++++++++++++++++-----------
 src/wayland/meta-wayland-keyboard.h |    6 ++-
 src/wayland/meta-wayland-pointer.c  |   49 ++++++++++++++++++--------
 src/wayland/meta-wayland-pointer.h  |    6 ++-
 src/wayland/meta-wayland-seat.c     |   18 +++++-----
 src/wayland/meta-wayland-surface.c  |    4 +-
 6 files changed, 96 insertions(+), 52 deletions(-)
---
diff --git a/src/wayland/meta-wayland-keyboard.c b/src/wayland/meta-wayland-keyboard.c
index 566a596..2159cce 100644
--- a/src/wayland/meta-wayland-keyboard.c
+++ b/src/wayland/meta-wayland-keyboard.c
@@ -226,12 +226,24 @@ err_keymap_str:
 }
 
 static void
+release_focus (MetaWaylandKeyboard *keyboard)
+{
+  keyboard->focus_resource = NULL;
+  keyboard->focus_surface = NULL;
+}
+
+static void
 keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
 {
   MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_surface_listener);
+  release_focus (keyboard);
+}
 
-  keyboard->focus_resource = NULL;
-  keyboard->focus = NULL;
+static void
+keyboard_handle_focus_resource_destroy (struct wl_listener *listener, void *data)
+{
+  MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_resource_listener);
+  release_focus (keyboard);
 }
 
 static gboolean
@@ -287,10 +299,9 @@ default_grab_modifiers (MetaWaylandKeyboardGrab *grab, uint32_t serial,
   wl_keyboard_send_modifiers (resource, serial, mods_depressed,
                               mods_latched, mods_locked, group);
 
-  if (pointer && pointer->focus && pointer->focus != keyboard->focus)
+  if (pointer && pointer->focus_surface && pointer->focus_surface != keyboard->focus_surface)
     {
-      pr = find_resource_for_surface (&keyboard->resource_list,
-                                      pointer->focus);
+      pr = find_resource_for_surface (&keyboard->resource_list, pointer->focus_surface);
       if (pr)
         {
           wl_keyboard_send_modifiers (pr, serial,
@@ -342,7 +353,10 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
 
   wl_list_init (&keyboard->resource_list);
   wl_array_init (&keyboard->keys);
+
   keyboard->focus_surface_listener.notify = keyboard_handle_focus_surface_destroy;
+  keyboard->focus_resource_listener.notify = keyboard_handle_focus_resource_destroy;
+
   keyboard->default_grab.interface = &default_keyboard_grab_interface;
   keyboard->default_grab.keyboard = keyboard;
   keyboard->grab = &keyboard->default_grab;
@@ -513,19 +527,27 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
   struct wl_resource *resource;
   uint32_t serial;
 
-  if (keyboard->focus == surface && keyboard->focus_resource != NULL)
+  if (keyboard->focus_surface == surface && keyboard->focus_resource != NULL)
     return;
 
   resource = keyboard->focus_resource;
-  if (keyboard->focus_resource && keyboard->focus->resource)
+  if (resource)
     {
-      struct wl_client *client = wl_resource_get_client (resource);
-      struct wl_display *display = wl_client_get_display (client);
-      serial = wl_display_next_serial (display);
-      wl_keyboard_send_leave (resource, serial, keyboard->focus->resource);
+      if (keyboard->focus_surface->resource)
+        {
+          struct wl_client *client = wl_resource_get_client (resource);
+          struct wl_display *display = wl_client_get_display (client);
+          serial = wl_display_next_serial (display);
+          wl_keyboard_send_leave (resource, serial, keyboard->focus_surface->resource);
+
+          meta_wayland_surface_focused_unset (keyboard->focus_surface);
+        }
+
+      wl_list_remove (&keyboard->focus_resource_listener.link);
       wl_list_remove (&keyboard->focus_surface_listener.link);
 
-      meta_wayland_surface_focused_unset (keyboard->focus);
+      keyboard->focus_resource = NULL;
+      keyboard->focus_surface = NULL;
     }
 
   resource = find_resource_for_surface (&keyboard->resource_list, surface);
@@ -558,14 +580,17 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
          wl_keyboard_send_enter (resource, serial, surface->resource,
                                  &keyboard->keys);
        }
-      wl_resource_add_destroy_listener (surface->resource, &keyboard->focus_surface_listener);
-      keyboard->focus_serial = serial;
 
       meta_wayland_surface_focused_set (surface);
-    }
 
-  keyboard->focus_resource = resource;
-  keyboard->focus = surface;
+      keyboard->focus_resource = resource;
+      keyboard->focus_surface = surface;
+
+      wl_resource_add_destroy_listener (keyboard->focus_resource, &keyboard->focus_resource_listener);
+      wl_resource_add_destroy_listener (keyboard->focus_surface->resource, 
&keyboard->focus_surface_listener);
+
+      keyboard->focus_serial = serial;
+    }
 }
 
 void
@@ -591,8 +616,6 @@ meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
   xkb_context_unref (keyboard->xkb_context);
 
   /* XXX: What about keyboard->resource_list? */
-  if (keyboard->focus_resource)
-    wl_list_remove (&keyboard->focus_surface_listener.link);
   wl_array_release (&keyboard->keys);
 }
 
@@ -611,7 +634,7 @@ meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard,
   if (keyboard->grab != &keyboard->default_grab)
     return FALSE;
 
-  if (keyboard->focus)
+  if (keyboard->focus_surface)
     {
       /* Fake key release events for the focused app */
       serial = wl_display_next_serial (keyboard->display);
@@ -653,7 +676,7 @@ meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard,
   meta_wayland_keyboard_end_grab (keyboard);
   g_slice_free (MetaWaylandKeyboardGrab, grab);
 
-  if (keyboard->focus)
+  if (keyboard->focus_surface)
     {
       /* Fake key press events for the focused app */
       serial = wl_display_next_serial (keyboard->display);
diff --git a/src/wayland/meta-wayland-keyboard.h b/src/wayland/meta-wayland-keyboard.h
index fd87c86..b51d3c0 100644
--- a/src/wayland/meta-wayland-keyboard.h
+++ b/src/wayland/meta-wayland-keyboard.h
@@ -92,9 +92,11 @@ typedef struct
 struct _MetaWaylandKeyboard
 {
   struct wl_list resource_list;
-  MetaWaylandSurface *focus;
-  struct wl_resource *focus_resource;
+
+  MetaWaylandSurface *focus_surface;
   struct wl_listener focus_surface_listener;
+  struct wl_resource *focus_resource;
+  struct wl_listener focus_resource_listener;
   uint32_t focus_serial;
 
   MetaWaylandKeyboardGrab *grab;
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 59ed093..035ceab 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -64,12 +64,24 @@ meta_wayland_pointer_get_seat (MetaWaylandPointer *pointer)
 }
 
 static void
+release_focus (MetaWaylandPointer *pointer)
+{
+  pointer->focus_resource = NULL;
+  pointer->focus_surface = NULL;
+}
+
+static void
 pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
 {
   MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener);
+  release_focus (pointer);
+}
 
-  pointer->focus_resource = NULL;
-  pointer->focus = NULL;
+static void
+pointer_handle_focus_resource_destroy (struct wl_listener *listener, void *data)
+{
+  MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_resource_listener);
+  release_focus (pointer);
 }
 
 static void
@@ -97,7 +109,7 @@ default_grab_motion (MetaWaylandPointerGrab *grab,
       wl_fixed_t sx, sy;
 
       meta_wayland_pointer_get_relative_coordinates (grab->pointer,
-                                                    grab->pointer->focus,
+                                                    grab->pointer->focus_surface,
                                                     &sx, &sy);
       wl_pointer_send_motion (resource, clutter_event_get_time (event), sx, sy);
     }
@@ -265,7 +277,10 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer)
 
   memset (pointer, 0, sizeof *pointer);
   wl_list_init (&pointer->resource_list);
+
   pointer->focus_surface_listener.notify = pointer_handle_focus_surface_destroy;
+  pointer->focus_resource_listener.notify = pointer_handle_focus_resource_destroy;
+
   pointer->default_grab.interface = &default_pointer_grab_interface;
   pointer->default_grab.pointer = pointer;
   pointer->grab = &pointer->default_grab;
@@ -292,12 +307,7 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer)
 void
 meta_wayland_pointer_release (MetaWaylandPointer *pointer)
 {
-  /* XXX: What about pointer->resource_list? */
-  if (pointer->focus_resource)
-    wl_list_remove (&pointer->focus_surface_listener.link);
-
-  pointer->focus = NULL;
-  pointer->focus_resource = NULL;
+  release_focus (pointer);
 }
 
 static struct wl_resource *
@@ -323,21 +333,25 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
   struct wl_resource *resource, *kr;
   uint32_t serial;
 
-  if (pointer->focus == surface && pointer->focus_resource != NULL)
+  if (pointer->focus_surface == surface && pointer->focus_resource != NULL)
     return;
 
   resource = pointer->focus_resource;
   if (resource)
     {
-      if (pointer->focus->resource)
+      if (pointer->focus_surface->resource)
         {
           struct wl_client *client = wl_resource_get_client (resource);
           struct wl_display *display = wl_client_get_display (client);
           serial = wl_display_next_serial (display);
-          wl_pointer_send_leave (resource, serial, pointer->focus->resource);
+          wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource);
         }
 
       wl_list_remove (&pointer->focus_surface_listener.link);
+      wl_list_remove (&pointer->focus_resource_listener.link);
+
+      pointer->focus_surface = NULL;
+      pointer->focus_resource = NULL;
     }
 
   resource = find_resource_for_surface (&pointer->resource_list, surface);
@@ -370,12 +384,15 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
                                 wl_fixed_to_int (pointer->x),
                                 wl_fixed_to_int (pointer->y));
       wl_pointer_send_enter (resource, serial, surface->resource, sx, sy);
-      wl_resource_add_destroy_listener (surface->resource, &pointer->focus_surface_listener);
+
+      pointer->focus_resource = resource;
+      pointer->focus_surface = surface;
+
+      wl_resource_add_destroy_listener (pointer->focus_resource, &pointer->focus_resource_listener);
+      wl_resource_add_destroy_listener (pointer->focus_surface->resource, &pointer->focus_surface_listener);
+
       pointer->focus_serial = serial;
     }
-
-  pointer->focus_resource = resource;
-  pointer->focus = surface;
 }
 
 void
diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h
index e5ee4c1..7fa9bf5 100644
--- a/src/wayland/meta-wayland-pointer.h
+++ b/src/wayland/meta-wayland-pointer.h
@@ -46,9 +46,11 @@ struct _MetaWaylandPointerGrab
 struct _MetaWaylandPointer
 {
   struct wl_list resource_list;
-  MetaWaylandSurface *focus;
-  struct wl_resource *focus_resource;
+
+  MetaWaylandSurface *focus_surface;
   struct wl_listener focus_surface_listener;
+  struct wl_resource *focus_resource;
+  struct wl_listener focus_resource_listener;
   guint32 focus_serial;
   guint32 click_serial;
 
diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
index 9e838f9..ff6f57d 100644
--- a/src/wayland/meta-wayland-seat.c
+++ b/src/wayland/meta-wayland-seat.c
@@ -95,9 +95,9 @@ pointer_set_cursor (struct wl_client *client,
 
   surface = (surface_resource ? wl_resource_get_user_data (surface_resource) : NULL);
 
-  if (seat->pointer.focus == NULL)
+  if (seat->pointer.focus_surface == NULL)
     return;
-  if (wl_resource_get_client (seat->pointer.focus->resource) != client)
+  if (wl_resource_get_client (seat->pointer.focus_surface->resource) != client)
     return;
   if (seat->pointer.focus_serial - serial > G_MAXUINT32 / 2)
     return;
@@ -125,9 +125,9 @@ seat_get_pointer (struct wl_client *client,
   wl_resource_set_implementation (cr, &pointer_interface, seat, unbind_resource);
   wl_list_insert (&seat->pointer.resource_list, wl_resource_get_link (cr));
 
-  if (seat->pointer.focus &&
-      wl_resource_get_client (seat->pointer.focus->resource) == client)
-    meta_wayland_pointer_set_focus (&seat->pointer, seat->pointer.focus);
+  if (seat->pointer.focus_surface &&
+      wl_resource_get_client (seat->pointer.focus_surface->resource) == client)
+    meta_wayland_pointer_set_focus (&seat->pointer, seat->pointer.focus_surface);
 }
 
 static void
@@ -148,10 +148,10 @@ seat_get_keyboard (struct wl_client *client,
                            seat->keyboard.xkb_info.keymap_fd,
                            seat->keyboard.xkb_info.keymap_size);
 
-  if (seat->keyboard.focus &&
-      wl_resource_get_client (seat->keyboard.focus->resource) == client)
+  if (seat->keyboard.focus_surface &&
+      wl_resource_get_client (seat->keyboard.focus_surface->resource) == client)
     {
-      meta_wayland_keyboard_set_focus (&seat->keyboard, seat->keyboard.focus);
+      meta_wayland_keyboard_set_focus (&seat->keyboard, seat->keyboard.focus_surface);
       meta_wayland_data_device_set_keyboard_focus (seat);
     }
 }
@@ -429,7 +429,7 @@ meta_wayland_seat_repick (MetaWaylandSeat    *seat,
     }
 
   pointer->current = surface;
-  if (surface != pointer->focus)
+  if (surface != pointer->focus_surface)
     {
       const MetaWaylandPointerGrabInterface *interface =
         pointer->grab->interface;
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 12bb3d0..192e6e3 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -826,7 +826,7 @@ xdg_surface_move (struct wl_client *client,
 
   if (seat->pointer.button_count == 0 ||
       seat->pointer.grab_serial != serial ||
-      seat->pointer.focus != surface)
+      seat->pointer.focus_surface != surface)
     return;
 
   begin_grab_op_on_surface (surface, seat, META_GRAB_OP_MOVING);
@@ -872,7 +872,7 @@ xdg_surface_resize (struct wl_client *client,
 
   if (seat->pointer.button_count == 0 ||
       seat->pointer.grab_serial != serial ||
-      seat->pointer.focus != surface)
+      seat->pointer.focus_surface != surface)
     return;
 
   begin_grab_op_on_surface (surface, seat, grab_op_for_edge (edges));


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