[mutter/wip/carlosg/issue-273: 47/47] core: Preserve focus across decoration changes



commit 8dcac664faf03ac2ea382e44d587d1f7dc92f7a3
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Aug 22 00:58:06 2018 +0200

    core: Preserve focus across decoration changes
    
    Changes in window decoration result in the window being reparented
    in and out its frame. This in turn causes unmap/map events, and
    XI_FocusOut if the window happened to be focused.
    
    In order to preserve the focused window across the decoration change,
    add a flag so that the focus may be restored on MapNotify.
    
    Closes: #273

 src/core/frame.c          | 12 ++++++++++++
 src/core/window-private.h |  3 +++
 src/core/window.c         |  3 +++
 src/x11/events.c          |  6 ++++++
 4 files changed, 24 insertions(+)
---
diff --git a/src/core/frame.c b/src/core/frame.c
index dc0109208..cfd284bc9 100644
--- a/src/core/frame.c
+++ b/src/core/frame.c
@@ -109,6 +109,12 @@ meta_window_ensure_frame (MetaWindow *window)
   /* FIXME handle this error */
   meta_x11_error_trap_pop (x11_display);
 
+  /* Ensure focus is restored after the unmap/map events triggered
+   * by XReparentWindow().
+   */
+  if (meta_window_has_focus (window))
+    window->restore_focus_on_map = TRUE;
+
   /* stick frame to the window */
   window->frame = frame;
 
@@ -201,6 +207,12 @@ meta_window_destroy_frame (MetaWindow *window)
 
   meta_ui_frame_unmanage (frame->ui_frame);
 
+  /* Ensure focus is restored after the unmap/map events triggered
+   * by XReparentWindow().
+   */
+  if (meta_window_has_focus (window))
+    window->restore_focus_on_map = TRUE;
+
   meta_x11_display_unregister_x_window (x11_display, frame->xwindow);
 
   window->frame = NULL;
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 26206c3d1..60f8f5e8e 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -415,6 +415,9 @@ struct _MetaWindow
   /* whether or not the window is from a program running on another machine */
   guint is_remote : 1;
 
+  /* whether focus should be restored on map */
+  guint restore_focus_on_map : 1;
+
   /* if non-NULL, the bounds of the window frame */
   cairo_region_t *frame_bounds;
 
diff --git a/src/core/window.c b/src/core/window.c
index c51cd29dc..2e24e4ed2 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -4653,6 +4653,9 @@ meta_window_focus (MetaWindow  *window,
 
   g_return_if_fail (!window->override_redirect);
 
+  /* This is a oneshot flag */
+  window->restore_focus_on_map = FALSE;
+
   meta_topic (META_DEBUG_FOCUS,
               "Setting input focus to window %s, input: %d take_focus: %d\n",
               window->desc, window->input, window->take_focus);
diff --git a/src/x11/events.c b/src/x11/events.c
index 53e1aa191..59caeb4b9 100644
--- a/src/x11/events.c
+++ b/src/x11/events.c
@@ -1374,6 +1374,12 @@ handle_other_xevent (MetaX11Display *x11_display,
           window = meta_window_x11_new (display, event->xmap.window,
                                         FALSE, META_COMP_EFFECT_CREATE);
         }
+      else if (window && window->restore_focus_on_map)
+        {
+          meta_window_focus (window,
+                             meta_display_get_current_time_roundtrip (display));
+        }
+
       break;
     case MapRequest:
       if (window == NULL)


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