diff options
author | Alberts Muktupāvels <alberts.muktupavels@gmail.com> | 2019-09-05 14:30:17 +0300 |
---|---|---|
committer | Alberts Muktupāvels <alberts.muktupavels@gmail.com> | 2019-09-14 00:41:53 +0300 |
commit | c8235d44a7fba351f3c6075c8e268a01c1255bfb (patch) | |
tree | ae868e75429377be61bea81285354a49b1a78e7f | |
parent | d820fce97a3a34b8c17540b1b51a45ee0e2b9b7f (diff) | |
download | metacity-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.c | 5 | ||||
-rw-r--r-- | src/core/frame.c | 12 | ||||
-rw-r--r-- | src/core/window-private.h | 3 | ||||
-rw-r--r-- | src/core/window.c | 3 |
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); |