summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlberts Muktupāvels <alberts.muktupavels@gmail.com>2019-09-05 14:30:17 +0300
committerAlberts Muktupāvels <alberts.muktupavels@gmail.com>2019-09-14 00:41:53 +0300
commitc8235d44a7fba351f3c6075c8e268a01c1255bfb (patch)
treeae868e75429377be61bea81285354a49b1a78e7f
parentd820fce97a3a34b8c17540b1b51a45ee0e2b9b7f (diff)
downloadmetacity-c8235d44a7fba351f3c6075c8e268a01c1255bfb.tar.gz
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 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. Based on mutter commit: https://gitlab.gnome.org/GNOME/mutter/commit/8dcac664faf03ac2ea382e
-rw-r--r--src/core/display.c5
-rw-r--r--src/core/frame.c12
-rw-r--r--src/core/window-private.h3
-rw-r--r--src/core/window.c3
4 files changed, 23 insertions, 0 deletions
diff --git a/src/core/display.c b/src/core/display.c
index 555543f8..c43ed3d4 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -2352,6 +2352,11 @@ event_callback (XEvent *event,
window = meta_window_new (display, event->xmap.window, FALSE,
META_EFFECT_TYPE_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)
diff --git a/src/core/frame.c b/src/core/frame.c
index e804775d..c166b865 100644
--- a/src/core/frame.c
+++ b/src/core/frame.c
@@ -146,6 +146,12 @@ meta_window_ensure_frame (MetaWindow *window)
/* FIXME handle this error */
meta_error_trap_pop (window->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;
@@ -216,6 +222,12 @@ meta_window_destroy_frame (MetaWindow *window)
meta_ui_destroy_frame_window (window->screen->ui, frame->xwindow);
+ /* 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_display_unregister_x_window (window->display,
frame->xwindow);
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 7f7eb276..cc99b7a1 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -341,6 +341,9 @@ struct _MetaWindow
/* if TRUE, we are freezing updates during a resize */
guint updates_frozen_for_resize : 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 bdb2512e..53ccf86c 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -4499,6 +4499,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);