[mutter] window: Fix focus of unmappable modal transient's parent



commit 6c8f6afdc43feb09a7aecc20dc714aa22b4213fd
Author: Jonas Ådahl <jadahl gmail com>
Date:   Thu Sep 1 18:42:58 2016 +0800

    window: Fix focus of unmappable modal transient's parent
    
    When a modal transient is unmanaging, most likely the parent of the
    modal transient should be focused.
    
    In Wayland, a MetaWindow is created when a shell surface role (like
    xdg_toplevel) is created, but a window cannot be shown until a buffer
    is attached. If a client would create two modal transients and make
    them both have the same parent, but only one get a buffer attached
    (i.e. shown), when unmanaging the modal transient that was showing,
    when finding a new focus candidate, the stacking code will ignore the
    not-to-be-shown buffer-less modal transient when finding a good
    candidate for focusing. In the case described here, this means it will
    find the parent of the unmanaging modal transient.
    
    This newly chosen candidate will then be passed to meta_window_focus();
    meta_window_focus() will then try to find any modal transient to focus
    instead, will find the one without any buffer, then fail to focus it
    because it cannot be mapped, thus making meta_window_focus() not focus
    anything. Since meta_window_focus() didn't change any focus state, the
    assert in meta_window_unmanage() checking that the unmanaging window
    isn't focused anymore will be hit, causing mutter to abort.
    
    For now, fix this by checking whether the modal transient can actually
    be focused in meta_window_focus(). For X11 client windows, a window
    will be defined to be focusable always, but for Wayland client windows,
    a window will be determined focusable only if it has a buffer attached.
    
    In the future, we should probably do a more thorough refactorization of
    focus handling to get rid of any X11 - Wayland differences.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=757568

 src/core/window.c |   14 +++++++++++++-
 1 files changed, 13 insertions(+), 1 deletions(-)
---
diff --git a/src/core/window.c b/src/core/window.c
index 2f72ca2..60716fb 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -4253,6 +4253,17 @@ get_modal_transient (MetaWindow *window)
   return modal_transient;
 }
 
+static gboolean
+meta_window_transient_can_focus (MetaWindow *window)
+{
+#ifdef HAVE_WAYLAND
+  if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
+    return meta_wayland_surface_get_buffer (window->surface) != NULL;
+#endif
+
+  return TRUE;
+}
+
 /* XXX META_EFFECT_FOCUS */
 void
 meta_window_focus (MetaWindow  *window,
@@ -4278,7 +4289,8 @@ meta_window_focus (MetaWindow  *window,
 
   modal_transient = get_modal_transient (window);
   if (modal_transient != NULL &&
-      !modal_transient->unmanaging)
+      !modal_transient->unmanaging &&
+      meta_window_transient_can_focus (modal_transient))
     {
       meta_topic (META_DEBUG_FOCUS,
                   "%s has %s as a modal transient, so focusing it instead.\n",


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