[mutter/wayland] wayland: fix pointer focus for destroyed surfaces



commit ad4053ab84eceabdd3584e380c9037e20d8e8636
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Wed Aug 28 16:23:34 2013 +0200

    wayland: fix pointer focus for destroyed surfaces
    
    We had an assertion in meta_wayland_surface_free() that after
    a repick() we would not choose the freed surface, but that didn't
    consider surfaces destroyed while holding the implicit pointer
    grab (ie, because the user clicked on the X button). In that case,
    we need to bypass the grab infrastructure and explicitly unfocus
    the dead surface.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=706982

 src/wayland/meta-wayland-pointer.c |   18 ++++++++++++++++++
 src/wayland/meta-wayland-pointer.h |    4 ++++
 src/wayland/meta-wayland.c         |    9 +++++++--
 3 files changed, 29 insertions(+), 2 deletions(-)
---
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 758d60a..f6c23d0 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -324,3 +324,21 @@ meta_wayland_pointer_end_modal (MetaWaylandPointer *pointer)
   meta_wayland_pointer_end_grab (pointer);
   g_slice_free (MetaWaylandPointerGrab, grab);
 }
+
+/* Called when the focused resource is destroyed */
+void
+meta_wayland_pointer_destroy_focus (MetaWaylandPointer *pointer)
+{
+  if (pointer->grab == &pointer->default_grab)
+    {
+      /* The surface was destroyed, but had the implicit pointer grab.
+         Bypass the grab interface. */
+      g_assert (pointer->button_count > 0);
+
+      /* Note: we focus the NULL interface, not the current one, because
+        we have button down, and the clients would be confused if the
+        pointer enters the surface.
+      */
+      meta_wayland_pointer_set_focus (pointer, NULL, 0, 0);
+    }
+}
diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h
index db6d3bf..491cdbc 100644
--- a/src/wayland/meta-wayland-pointer.h
+++ b/src/wayland/meta-wayland-pointer.h
@@ -35,6 +35,10 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
                                 MetaWaylandSurface *surface,
                                 wl_fixed_t sx,
                                 wl_fixed_t sy);
+
+void
+meta_wayland_pointer_destroy_focus (MetaWaylandPointer *pointer);
+
 void
 meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
                                  MetaWaylandPointerGrab *grab);
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index ba3726f..56ac249 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -497,9 +497,14 @@ meta_wayland_surface_free (MetaWaylandSurface *surface)
 
   meta_wayland_compositor_repick (compositor);
 
-  /* Check that repick didn't pick the freed surface */
-  g_assert (surface != compositor->seat->pointer.focus);
   g_assert (surface != compositor->seat->keyboard.focus);
+  if (surface == compositor->seat->pointer.focus)
+    {
+      meta_wayland_pointer_destroy_focus (&compositor->seat->pointer);
+
+      g_assert (surface != compositor->seat->pointer.focus);
+      g_assert (surface != compositor->seat->pointer.grab->focus);
+    }
 
  if (compositor->implicit_grab_surface == surface)
    compositor->implicit_grab_surface = compositor->seat->pointer.current;


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