From 49c06fd9b104ef41e03ce496973bc29ec930d964 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Wed, 22 Aug 2018 00:58:06 +0200 Subject: [PATCH] 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 (cherry picked from commit 8dcac664faf03ac2ea382e44d587d1f7dc92f7a3) --- 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 47174f24d..b7aa49cb8 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -105,6 +105,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; @@ -194,6 +200,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_display_unregister_x_window (window->display, frame->xwindow); diff --git a/src/core/window-private.h b/src/core/window-private.h index 8552829b2..c7253fe45 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -416,6 +416,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 a1f4aa4f3..dad68ffab 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -4629,6 +4629,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 f60f650a6..4c256932a 100644 --- a/src/x11/events.c +++ b/src/x11/events.c @@ -1365,6 +1365,12 @@ handle_other_xevent (MetaDisplay *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)