From 74f58674e75d0defd5df7e52d73f78b278d72fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 11 Jul 2024 14:57:15 +0200 Subject: [PATCH] window: Don't check always-on-top overlap before placing When we show a window, we'll check if it overlaps with an existing always-on-top window with the intention to deny focus. However, we did this potentially before having placed the window, meaning we effectively checked as if it was placed at (0, 0), which created unexpected results. Instead check the overlap state after placing. A window placement test case is added to verify this works as expected. Part-of: --- src/core/place.c | 11 ++- src/core/window.c | 10 ++- src/tests/meson.build | 4 +- .../always-on-top-map-new-maximized.metatest | 20 +++++ src/tests/stacking/window-placement.metatest | 84 +++++++++++++++++++ 5 files changed, 123 insertions(+), 6 deletions(-) create mode 100644 src/tests/stacking/always-on-top-map-new-maximized.metatest create mode 100644 src/tests/stacking/window-placement.metatest diff --git a/src/core/place.c b/src/core/place.c index feb5c4cbf..01b0bd34d 100644 --- a/src/core/place.c +++ b/src/core/place.c @@ -353,7 +353,9 @@ find_most_freespace (MetaWindow *window, } static gboolean -window_overlaps_focus_window (MetaWindow *window) +window_overlaps_focus_window (MetaWindow *window, + int new_x, + int new_y) { MetaWindow *focus_window; MtkRectangle window_frame, focus_frame, overlap; @@ -363,6 +365,9 @@ window_overlaps_focus_window (MetaWindow *window) return FALSE; meta_window_get_frame_rect (window, &window_frame); + window_frame.x = new_x; + window_frame.y = new_y; + meta_window_get_frame_rect (focus_window, &focus_frame); return mtk_rectangle_intersect (&window_frame, @@ -414,7 +419,7 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window, #ifdef HAVE_X11_CLIENT meta_window_x11_same_application (window, focus_window) && #endif - window_overlaps_focus_window (window)) + window_overlaps_focus_window (window, *x, *y)) { find_most_freespace (window, focus_window, *x, *y, x, y); meta_topic (META_DEBUG_PLACEMENT, @@ -987,7 +992,7 @@ meta_window_place (MetaWindow *window, g_assert (focus_window != NULL); /* No need to do anything if the window doesn't overlap at all */ - found_fit = !window_overlaps_focus_window (window); + found_fit = !window_overlaps_focus_window (window, x, y); /* Try to do a first fit again, this time only taking into account the * focus window. diff --git a/src/core/window.c b/src/core/window.c index 3c690fa36..d6e8406be 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -2284,8 +2284,8 @@ meta_window_show (MetaWindow *window) if (focus_window && window->showing_for_first_time && !meta_window_is_ancestor_of_transient (focus_window, window) && - ((!place_on_top_on_map && !takes_focus_on_map) || - window_would_be_covered_by_always_above_window (window))) + !place_on_top_on_map && + !takes_focus_on_map) { needs_stacking_adjustment = TRUE; if (!window->placed) @@ -2316,6 +2316,12 @@ meta_window_show (MetaWindow *window) meta_window_force_placement (window, place_flags); } + if (focus_window && + window->showing_for_first_time && + !meta_window_is_ancestor_of_transient (focus_window, window) && + window_would_be_covered_by_always_above_window (window)) + needs_stacking_adjustment = TRUE; + if (needs_stacking_adjustment) { gboolean overlap; diff --git a/src/tests/meson.build b/src/tests/meson.build index 1194cb006..6b5048490 100644 --- a/src/tests/meson.build +++ b/src/tests/meson.build @@ -726,6 +726,7 @@ stacking_tests = [ 'workspace-basic', 'workspace-test', 'always-on-top', + 'always-on-top-map-new-maximized', 'focus-default-window-globally-active-input', 'workspace-unmanaging-window', 'click-to-focus-and-raise', @@ -739,7 +740,8 @@ stacking_tests = [ 'sticky', 'sticky-modals', 'sticky-transients', - 'strut-monitor-changes' + 'strut-monitor-changes', + 'window-placement', ] foreach stacking_test: stacking_tests diff --git a/src/tests/stacking/always-on-top-map-new-maximized.metatest b/src/tests/stacking/always-on-top-map-new-maximized.metatest new file mode 100644 index 000000000..f93307082 --- /dev/null +++ b/src/tests/stacking/always-on-top-map-new-maximized.metatest @@ -0,0 +1,20 @@ +resize_monitor default 400 400 + +new_client w wayland +create w/1 csd +resize w/1 350 350 +show w/1 +move w/1 25 25 +make_above w/1 true + +assert_focused w/1 +assert_stacking w/1 + +# Map a maximized window; it should not gain focus due to being mostly covered. + +create w/2 csd +maximize w/2 +show w/2 + +assert_focused w/1 +assert_stacking w/2 w/1 diff --git a/src/tests/stacking/window-placement.metatest b/src/tests/stacking/window-placement.metatest new file mode 100644 index 000000000..00634a31a --- /dev/null +++ b/src/tests/stacking/window-placement.metatest @@ -0,0 +1,84 @@ +new_client w wayland +resize_monitor default 250 250 +set_pref center-new-windows false + +# Show 4 windows in a row and assert that they are placed in a grid and focused +# correctly. + +create w/1 csd +resize w/1 100 100 +show w/1 + +assert_focused w/1 +assert_position w/1 24 16 +assert_size w/1 100 100 + +create w/2 csd +resize w/2 100 100 +show w/2 + +assert_focused w/2 +assert_position w/2 24 116 +assert_size w/2 100 100 + +create w/3 csd +resize w/3 100 100 +show w/3 + +assert_focused w/3 +assert_position w/3 124 16 +assert_size w/3 100 100 + +create w/4 csd +resize w/4 100 100 +show w/4 + +assert_focused w/4 +assert_position w/4 124 116 +assert_size w/4 100 100 + +destroy w/1 +destroy w/2 +destroy w/3 +destroy w/4 +wait + +assert_stacking + + +# Show 1 window, make it 'always-on-top' and make sure the following windows +# still get placed and focused correctly. + +create w/1 csd +resize w/1 100 100 +show w/1 + +assert_focused w/1 +assert_position w/1 24 16 +assert_size w/1 100 100 + +make_above w/1 true + +create w/2 csd +resize w/2 100 100 +show w/2 + +assert_focused w/2 +assert_position w/2 24 116 +assert_size w/2 100 100 + +create w/3 csd +resize w/3 100 100 +show w/3 + +assert_focused w/3 +assert_position w/3 124 16 +assert_size w/3 100 100 + +create w/4 csd +resize w/4 100 100 +show w/4 + +assert_focused w/4 +assert_position w/4 124 116 +assert_size w/4 100 100