1155 lines
43 KiB
Diff
1155 lines
43 KiB
Diff
From a93862f377dc77207ade317a2b2b284402e496e7 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Wed, 3 Jul 2024 14:13:59 +0200
|
|
Subject: [PATCH 01/13] window: Don't switch workspace on sticky transient when
|
|
activating
|
|
|
|
If a transient window is sticky (visible on all workspaces) and it gets
|
|
activated, we'd call move_worskpace() which would effectively unstick
|
|
it, which is rather unexpected. It'd also effectively unstick its parent
|
|
as well, due to moving a transient window also moves its descendants and
|
|
ascendants.
|
|
---
|
|
src/core/window.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/src/core/window.c b/src/core/window.c
|
|
index 7d86adece4..ee4ea90354 100644
|
|
--- a/src/core/window.c
|
|
+++ b/src/core/window.c
|
|
@@ -3762,7 +3762,7 @@ meta_window_activate_full (MetaWindow *window,
|
|
/* We've marked it as demanding, don't need to do anything else. */
|
|
return;
|
|
}
|
|
- else if (window->transient_for != NULL)
|
|
+ else if (window->transient_for != NULL && !window->on_all_workspaces)
|
|
{
|
|
/* Move transients to current workspace - preference dialogs should appear over
|
|
the source window. */
|
|
--
|
|
2.44.0.501.g19981daefd.dirty
|
|
|
|
|
|
From 5d2e7e48a055cf422f1ef2b8d99bbe5346f704b0 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Wed, 3 Jul 2024 14:17:48 +0200
|
|
Subject: [PATCH 02/13] window: Inherit stickyness from parent when becoming
|
|
transient
|
|
|
|
When a transient window becomes transient, check if the parent is
|
|
sticky, and if it is, make the transient sticky as well. This handles
|
|
situations where e.g. a utility dialog (such as search and replace) is
|
|
opened on a sticky window, also making the utility dialog sharing the
|
|
same stickyness state.
|
|
|
|
This is also more in line with the semantics of making a window sticky,
|
|
where transient would implicitly become sticky as a side effect.
|
|
---
|
|
src/core/window.c | 3 +++
|
|
1 file changed, 3 insertions(+)
|
|
|
|
diff --git a/src/core/window.c b/src/core/window.c
|
|
index ee4ea90354..6da7ae7c03 100644
|
|
--- a/src/core/window.c
|
|
+++ b/src/core/window.c
|
|
@@ -8105,6 +8105,9 @@ meta_window_set_transient_for (MetaWindow *window,
|
|
|
|
if (meta_window_appears_focused (window) && window->transient_for != NULL)
|
|
meta_window_propagate_focus_appearance (window, TRUE);
|
|
+
|
|
+ if (parent && parent->on_all_workspaces)
|
|
+ meta_window_stick (window);
|
|
}
|
|
|
|
void
|
|
--
|
|
2.44.0.501.g19981daefd.dirty
|
|
|
|
|
|
From fe04ff1ff3b63a6943d7a192c494f6fc99eea088 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Tue, 16 Jul 2024 11:32:37 +0200
|
|
Subject: [PATCH 03/13] window: Ignoring unmanaging ancestor when finding root
|
|
|
|
This avoids the following critical warning happening sometimes when a
|
|
Wayland client exits taking all its window with it in an arbitrary
|
|
order:
|
|
|
|
CRITICAL: meta_window_set_stack_position_no_sync: assertion 'window->stack_position >= 0' failed
|
|
---
|
|
src/core/window.c | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/core/window.c b/src/core/window.c
|
|
index 6da7ae7c03..8d21e3419a 100644
|
|
--- a/src/core/window.c
|
|
+++ b/src/core/window.c
|
|
@@ -5096,7 +5096,8 @@ find_root_ancestor (MetaWindow *window,
|
|
MetaWindow **ancestor = data;
|
|
|
|
/* Overwrite the previously "most-root" ancestor with the new one found */
|
|
- *ancestor = window;
|
|
+ if (!window->unmanaging)
|
|
+ *ancestor = window;
|
|
|
|
/* We want this to continue until meta_window_foreach_ancestor quits because
|
|
* there are no more valid ancestors.
|
|
--
|
|
2.44.0.501.g19981daefd.dirty
|
|
|
|
|
|
From 02ec655ea9356aefdef4a07896287358903c417b Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Tue, 16 Jul 2024 11:44:05 +0200
|
|
Subject: [PATCH 04/13] tests/test-runner: Add (un)set_modal
|
|
|
|
Ends up calling gtk_window_(un)set_modal() in the client.
|
|
---
|
|
src/tests/test-client.c | 32 ++++++++++++++++++++++++++++++++
|
|
src/tests/test-runner.c | 2 ++
|
|
2 files changed, 34 insertions(+)
|
|
|
|
diff --git a/src/tests/test-client.c b/src/tests/test-client.c
|
|
index 73931375e9..63fdf5818b 100644
|
|
--- a/src/tests/test-client.c
|
|
+++ b/src/tests/test-client.c
|
|
@@ -738,6 +738,38 @@ process_line (const char *line)
|
|
|
|
gtk_window_unmaximize (GTK_WINDOW (window));
|
|
}
|
|
+ else if (strcmp (argv[0], "set_modal") == 0)
|
|
+ {
|
|
+ GtkWidget *window;
|
|
+
|
|
+ if (argc != 2)
|
|
+ {
|
|
+ g_print ("usage: set_modal <id>\n");
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ window = lookup_window (argv[1]);
|
|
+ if (!window)
|
|
+ goto out;
|
|
+
|
|
+ gtk_window_set_modal (GTK_WINDOW (window), TRUE);
|
|
+ }
|
|
+ else if (strcmp (argv[0], "unset_modal") == 0)
|
|
+ {
|
|
+ GtkWidget *window;
|
|
+
|
|
+ if (argc != 2)
|
|
+ {
|
|
+ g_print ("usage: unset_modal <id>\n");
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ window = lookup_window (argv[1]);
|
|
+ if (!window)
|
|
+ goto out;
|
|
+
|
|
+ gtk_window_set_modal (GTK_WINDOW (window), FALSE);
|
|
+ }
|
|
else if (strcmp (argv[0], "fullscreen") == 0)
|
|
{
|
|
if (argc != 2)
|
|
diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c
|
|
index d94e0e1c2b..88aeac30d8 100644
|
|
--- a/src/tests/test-runner.c
|
|
+++ b/src/tests/test-runner.c
|
|
@@ -703,6 +703,8 @@ test_case_do (TestCase *test,
|
|
strcmp (argv[0], "unmaximize") == 0 ||
|
|
strcmp (argv[0], "fullscreen") == 0 ||
|
|
strcmp (argv[0], "unfullscreen") == 0 ||
|
|
+ strcmp (argv[0], "set_modal") == 0 ||
|
|
+ strcmp (argv[0], "unset_modal") == 0 ||
|
|
strcmp (argv[0], "freeze") == 0 ||
|
|
strcmp (argv[0], "thaw") == 0 ||
|
|
strcmp (argv[0], "destroy") == 0)
|
|
--
|
|
2.44.0.501.g19981daefd.dirty
|
|
|
|
|
|
From d893cb65583d451e718ae6f5b470a873ea7e0735 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Tue, 16 Jul 2024 11:44:58 +0200
|
|
Subject: [PATCH 05/13] window: Propagate stickyness across modal dialog chains
|
|
|
|
While marking a parent window as sticky or non-sticky always propagates
|
|
to the children, also propagate to the parents if the dialog in question
|
|
is modal.
|
|
---
|
|
src/core/window.c | 23 +++++++++++++++++++++++
|
|
1 file changed, 23 insertions(+)
|
|
|
|
diff --git a/src/core/window.c b/src/core/window.c
|
|
index 8d21e3419a..de9efb8a7b 100644
|
|
--- a/src/core/window.c
|
|
+++ b/src/core/window.c
|
|
@@ -5057,6 +5057,27 @@ stick_foreach_func (MetaWindow *window,
|
|
return TRUE;
|
|
}
|
|
|
|
+static void
|
|
+foreach_modal_ancestor (MetaWindow *window,
|
|
+ void (*func) (MetaWindow *window))
|
|
+{
|
|
+ MetaWindow *parent;
|
|
+
|
|
+ if (window->type != META_WINDOW_MODAL_DIALOG)
|
|
+ return;
|
|
+
|
|
+ parent = window->transient_for;
|
|
+ while (parent)
|
|
+ {
|
|
+ func (parent);
|
|
+
|
|
+ if (parent->type != META_WINDOW_MODAL_DIALOG)
|
|
+ break;
|
|
+
|
|
+ parent = parent->transient_for;
|
|
+ }
|
|
+}
|
|
+
|
|
void
|
|
meta_window_stick (MetaWindow *window)
|
|
{
|
|
@@ -5068,6 +5089,7 @@ meta_window_stick (MetaWindow *window)
|
|
meta_window_foreach_transient (window,
|
|
stick_foreach_func,
|
|
&stick);
|
|
+ foreach_modal_ancestor (window, window_stick_impl);
|
|
}
|
|
|
|
void
|
|
@@ -5081,6 +5103,7 @@ meta_window_unstick (MetaWindow *window)
|
|
meta_window_foreach_transient (window,
|
|
stick_foreach_func,
|
|
&stick);
|
|
+ foreach_modal_ancestor (window, window_unstick_impl);
|
|
}
|
|
|
|
void
|
|
--
|
|
2.44.0.501.g19981daefd.dirty
|
|
|
|
|
|
From 4ab883d5a509db954f09c410f88f5661ed17351d Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Thu, 4 Jul 2024 11:50:24 +0200
|
|
Subject: [PATCH 06/13] window: Clean up formatting and naming of stacking
|
|
adjustment condition
|
|
|
|
The function checking whether a 'always-on-top' window covers the
|
|
showing window now has that in the name, to make it more obvious. That
|
|
function was also changed to use the more common way of iterating a
|
|
list, and now uses auto cleanup pointers for the list.
|
|
|
|
The condition itself was updated to follow the current coding style.
|
|
---
|
|
src/core/window.c | 37 +++++++++++++++----------------------
|
|
1 file changed, 15 insertions(+), 22 deletions(-)
|
|
|
|
diff --git a/src/core/window.c b/src/core/window.c
|
|
index de9efb8a7b..8b7b33b29e 100644
|
|
--- a/src/core/window.c
|
|
+++ b/src/core/window.c
|
|
@@ -2338,33 +2338,25 @@ windows_overlap (const MetaWindow *w1, const MetaWindow *w2)
|
|
* (say) ninety per cent and almost indistinguishable from total.
|
|
*/
|
|
static gboolean
|
|
-window_would_be_covered (const MetaWindow *newbie)
|
|
+window_would_be_covered_by_always_above_window (MetaWindow *window)
|
|
{
|
|
- MetaWorkspace *workspace = meta_window_get_workspace ((MetaWindow *)newbie);
|
|
- GList *tmp, *windows;
|
|
+ MetaWorkspace *workspace = meta_window_get_workspace (window);
|
|
+ g_autoptr (GList) windows = NULL;
|
|
+ GList *l;
|
|
|
|
windows = meta_workspace_list_windows (workspace);
|
|
-
|
|
- tmp = windows;
|
|
- while (tmp != NULL)
|
|
+ for (l = windows; l; l = l->next)
|
|
{
|
|
- MetaWindow *w = tmp->data;
|
|
+ MetaWindow *other_window = l->data;
|
|
|
|
- if (w->wm_state_above && w != newbie)
|
|
+ if (other_window->wm_state_above && other_window != window)
|
|
{
|
|
- /* We have found a window that is "above". Perhaps it overlaps. */
|
|
- if (windows_overlap (w, newbie))
|
|
- {
|
|
- g_list_free (windows); /* clean up... */
|
|
- return TRUE; /* yes, it does */
|
|
- }
|
|
+ if (windows_overlap (other_window, window))
|
|
+ return TRUE;
|
|
}
|
|
-
|
|
- tmp = tmp->next;
|
|
}
|
|
|
|
- g_list_free (windows);
|
|
- return FALSE; /* none found */
|
|
+ return FALSE;
|
|
}
|
|
|
|
void
|
|
@@ -2445,10 +2437,11 @@ meta_window_show (MetaWindow *window)
|
|
* probably rather be a term in the "if" condition below.
|
|
*/
|
|
|
|
- if ( focus_window != NULL && window->showing_for_first_time &&
|
|
- ( (!place_on_top_on_map && !takes_focus_on_map) ||
|
|
- window_would_be_covered (window) )
|
|
- ) {
|
|
+ if (focus_window &&
|
|
+ window->showing_for_first_time &&
|
|
+ ((!place_on_top_on_map && !takes_focus_on_map) ||
|
|
+ window_would_be_covered_by_always_above_window (window)))
|
|
+ {
|
|
if (!meta_window_is_ancestor_of_transient (focus_window, window))
|
|
{
|
|
needs_stacking_adjustment = TRUE;
|
|
--
|
|
2.44.0.501.g19981daefd.dirty
|
|
|
|
|
|
From 7b201110be2990073518fe859c55bf0a0b3b220b Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Thu, 4 Jul 2024 13:50:53 +0200
|
|
Subject: [PATCH 07/13] place: Remove a couple of comments about X11 roundtrips
|
|
|
|
It's not relevant in the context where the comment is, and don't need to
|
|
be reminded of X11 quirks here.
|
|
---
|
|
src/core/place.c | 2 --
|
|
1 file changed, 2 deletions(-)
|
|
|
|
diff --git a/src/core/place.c b/src/core/place.c
|
|
index 1075fe20d5..b03f746121 100644
|
|
--- a/src/core/place.c
|
|
+++ b/src/core/place.c
|
|
@@ -807,7 +807,6 @@ meta_window_place (MetaWindow *window,
|
|
MetaRectangle work_area;
|
|
MetaRectangle frame_rect;
|
|
|
|
- /* Warning, this function is a round trip! */
|
|
logical_monitor = meta_backend_get_current_logical_monitor (backend);
|
|
|
|
meta_window_get_work_area_for_logical_monitor (window,
|
|
@@ -851,7 +850,6 @@ meta_window_place (MetaWindow *window,
|
|
g_slist_free (all_windows);
|
|
}
|
|
|
|
- /* Warning, on X11 this might be a round trip! */
|
|
logical_monitor = meta_backend_get_current_logical_monitor (backend);
|
|
|
|
/* Maximize windows if they are too big for their work area (bit of
|
|
--
|
|
2.44.0.501.g19981daefd.dirty
|
|
|
|
|
|
From 508ca92d4e01b4b79906528d25898a6ef1decee4 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Thu, 11 Jul 2024 14:23:26 +0200
|
|
Subject: [PATCH 08/13] window: Add place flags
|
|
|
|
Replace a boolean argument and a temporary MetaWindow struct field with
|
|
a `MetaPlaceFlag` passed where relevant. This includes
|
|
`meta_window_move_resize_internal()` and `meta_window_constrain()`, as
|
|
placement may happen during constraining, and also
|
|
`meta_window_force_placement()`.
|
|
|
|
The struct field (denied_focus_and_not_transient) was only ever set in
|
|
meta_window_show(), before meta_window_force_placement(), and
|
|
immediately unset as a side effect of that. In .._show() we'll always
|
|
force placement if the window wasn't already placed, and in
|
|
meta_window_constrain(), we'd only ever call meta_window_place() if the
|
|
window wasn't already placed, meaning the variable would only ever be
|
|
relevant during `meta_window_show()`. Having it as a flag makes that
|
|
relationship and temporary state clearer.
|
|
---
|
|
src/core/constraints.c | 12 +++++---
|
|
src/core/constraints.h | 1 +
|
|
src/core/place.c | 16 +++++-----
|
|
src/core/place.h | 11 +++----
|
|
src/core/window-private.h | 15 ++++++----
|
|
src/core/window.c | 45 +++++++++++++++++++---------
|
|
src/wayland/meta-wayland-xdg-shell.c | 2 +-
|
|
src/wayland/meta-window-wayland.c | 7 ++++-
|
|
src/x11/window-x11.c | 18 +++++++++--
|
|
9 files changed, 87 insertions(+), 40 deletions(-)
|
|
|
|
diff --git a/src/core/constraints.c b/src/core/constraints.c
|
|
index a140c62458..e0df50f1a2 100644
|
|
--- a/src/core/constraints.c
|
|
+++ b/src/core/constraints.c
|
|
@@ -217,6 +217,7 @@ static void setup_constraint_info (ConstraintInfo *info,
|
|
const MetaRectangle *orig,
|
|
MetaRectangle *new);
|
|
static void place_window_if_needed (MetaWindow *window,
|
|
+ MetaPlaceFlag place_flags,
|
|
ConstraintInfo *info);
|
|
static void update_onscreen_requirements (MetaWindow *window,
|
|
ConstraintInfo *info);
|
|
@@ -290,6 +291,7 @@ do_all_constraints (MetaWindow *window,
|
|
void
|
|
meta_window_constrain (MetaWindow *window,
|
|
MetaMoveResizeFlags flags,
|
|
+ MetaPlaceFlag place_flags,
|
|
MetaGravity resize_gravity,
|
|
const MetaRectangle *orig,
|
|
MetaRectangle *new,
|
|
@@ -313,7 +315,7 @@ meta_window_constrain (MetaWindow *window,
|
|
resize_gravity,
|
|
orig,
|
|
new);
|
|
- place_window_if_needed (window, &info);
|
|
+ place_window_if_needed (window, place_flags, &info);
|
|
|
|
while (!satisfied && priority <= PRIORITY_MAXIMUM) {
|
|
gboolean check_only = TRUE;
|
|
@@ -519,8 +521,9 @@ get_start_rect_for_resize (MetaWindow *window,
|
|
}
|
|
|
|
static void
|
|
-place_window_if_needed(MetaWindow *window,
|
|
- ConstraintInfo *info)
|
|
+place_window_if_needed (MetaWindow *window,
|
|
+ MetaPlaceFlag place_flags,
|
|
+ ConstraintInfo *info)
|
|
{
|
|
gboolean did_placement;
|
|
|
|
@@ -564,7 +567,8 @@ place_window_if_needed(MetaWindow *window,
|
|
}
|
|
else
|
|
{
|
|
- meta_window_place (window, orig_rect.x, orig_rect.y,
|
|
+ meta_window_place (window, place_flags,
|
|
+ orig_rect.x, orig_rect.y,
|
|
&placed_rect.x, &placed_rect.y);
|
|
|
|
/* placing the window may have changed the monitor. Find the
|
|
diff --git a/src/core/constraints.h b/src/core/constraints.h
|
|
index eaa4e45940..0bbcf7146a 100644
|
|
--- a/src/core/constraints.h
|
|
+++ b/src/core/constraints.h
|
|
@@ -29,6 +29,7 @@
|
|
|
|
void meta_window_constrain (MetaWindow *window,
|
|
MetaMoveResizeFlags flags,
|
|
+ MetaPlaceFlag place_flags,
|
|
MetaGravity resize_gravity,
|
|
const MetaRectangle *orig,
|
|
MetaRectangle *new,
|
|
diff --git a/src/core/place.c b/src/core/place.c
|
|
index b03f746121..350e1ed0f1 100644
|
|
--- a/src/core/place.c
|
|
+++ b/src/core/place.c
|
|
@@ -327,9 +327,10 @@ window_place_centered (MetaWindow *window)
|
|
}
|
|
|
|
static void
|
|
-avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
|
|
- int *x,
|
|
- int *y)
|
|
+avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
|
|
+ MetaPlaceFlag flags,
|
|
+ int *x,
|
|
+ int *y)
|
|
{
|
|
/* We can't center this dialog if it was denied focus and it
|
|
* overlaps with the focus window and this dialog is modal and this
|
|
@@ -351,7 +352,7 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
|
|
|
|
/* denied_focus_and_not_transient is only set when focus_window != NULL */
|
|
|
|
- if (window->denied_focus_and_not_transient &&
|
|
+ if (flags & META_PLACE_FLAG_DENIED_FOCUS_AND_NOT_TRANSIENT &&
|
|
window->type == META_WINDOW_MODAL_DIALOG &&
|
|
meta_window_same_application (window, focus_window) &&
|
|
window_overlaps_focus_window (window))
|
|
@@ -660,6 +661,7 @@ meta_window_process_placement (MetaWindow *window,
|
|
|
|
void
|
|
meta_window_place (MetaWindow *window,
|
|
+ MetaPlaceFlag flags,
|
|
int x,
|
|
int y,
|
|
int *new_x,
|
|
@@ -758,7 +760,7 @@ meta_window_place (MetaWindow *window,
|
|
{
|
|
meta_topic (META_DEBUG_PLACEMENT,
|
|
"Not placing window with PPosition or USPosition set");
|
|
- avoid_being_obscured_as_second_modal_dialog (window, &x, &y);
|
|
+ avoid_being_obscured_as_second_modal_dialog (window, flags, &x, &y);
|
|
goto done;
|
|
}
|
|
}
|
|
@@ -791,7 +793,7 @@ meta_window_place (MetaWindow *window,
|
|
"Centered window %s over transient parent",
|
|
window->desc);
|
|
|
|
- avoid_being_obscured_as_second_modal_dialog (window, &x, &y);
|
|
+ avoid_being_obscured_as_second_modal_dialog (window, flags, &x, &y);
|
|
|
|
goto done;
|
|
}
|
|
@@ -895,7 +897,7 @@ meta_window_place (MetaWindow *window,
|
|
* if at all possible. This is guaranteed to only be called if the
|
|
* focus_window is non-NULL, and we try to avoid that window.
|
|
*/
|
|
- if (window->denied_focus_and_not_transient)
|
|
+ if (flags & META_PLACE_FLAG_DENIED_FOCUS_AND_NOT_TRANSIENT)
|
|
{
|
|
MetaWindow *focus_window;
|
|
gboolean found_fit;
|
|
diff --git a/src/core/place.h b/src/core/place.h
|
|
index 2e2c811413..0c95ad6329 100644
|
|
--- a/src/core/place.h
|
|
+++ b/src/core/place.h
|
|
@@ -30,10 +30,11 @@ void meta_window_process_placement (MetaWindow *window,
|
|
int *rel_x,
|
|
int *rel_y);
|
|
|
|
-void meta_window_place (MetaWindow *window,
|
|
- int x,
|
|
- int y,
|
|
- int *new_x,
|
|
- int *new_y);
|
|
+void meta_window_place (MetaWindow *window,
|
|
+ MetaPlaceFlag place_flags,
|
|
+ int x,
|
|
+ int y,
|
|
+ int *new_x,
|
|
+ int *new_y);
|
|
|
|
#endif
|
|
diff --git a/src/core/window-private.h b/src/core/window-private.h
|
|
index d1730c9880..cacc45e964 100644
|
|
--- a/src/core/window-private.h
|
|
+++ b/src/core/window-private.h
|
|
@@ -81,6 +81,13 @@ typedef enum
|
|
META_MOVE_RESIZE_PLACEMENT_CHANGED = 1 << 11,
|
|
} MetaMoveResizeFlags;
|
|
|
|
+typedef enum _MetaPlaceFlag
|
|
+{
|
|
+ META_PLACE_FLAG_NONE = 0,
|
|
+ META_PLACE_FLAG_FORCE_MOVE = 1 << 0,
|
|
+ META_PLACE_FLAG_DENIED_FOCUS_AND_NOT_TRANSIENT = 1 << 1,
|
|
+} MetaPlaceFlag;
|
|
+
|
|
typedef enum
|
|
{
|
|
META_MOVE_RESIZE_RESULT_MOVED = 1 << 0,
|
|
@@ -385,9 +392,6 @@ struct _MetaWindow
|
|
/* Have we placed this window? */
|
|
guint placed : 1;
|
|
|
|
- /* Is this not a transient of the focus window which is being denied focus? */
|
|
- guint denied_focus_and_not_transient : 1;
|
|
-
|
|
/* Has this window not ever been shown yet? */
|
|
guint showing_for_first_time : 1;
|
|
|
|
@@ -861,6 +865,7 @@ void meta_window_update_resize (MetaWindow *window,
|
|
|
|
void meta_window_move_resize_internal (MetaWindow *window,
|
|
MetaMoveResizeFlags flags,
|
|
+ MetaPlaceFlag place_flags,
|
|
MetaGravity gravity,
|
|
MetaRectangle frame_rect);
|
|
|
|
@@ -875,8 +880,8 @@ void meta_window_emit_size_changed (MetaWindow *window);
|
|
|
|
MetaPlacementRule *meta_window_get_placement_rule (MetaWindow *window);
|
|
|
|
-void meta_window_force_placement (MetaWindow *window,
|
|
- gboolean force_move);
|
|
+void meta_window_force_placement (MetaWindow *window,
|
|
+ MetaPlaceFlag flags);
|
|
|
|
void meta_window_force_restore_shortcuts (MetaWindow *window,
|
|
ClutterInputDevice *source);
|
|
diff --git a/src/core/window.c b/src/core/window.c
|
|
index 8b7b33b29e..f1c81c644b 100644
|
|
--- a/src/core/window.c
|
|
+++ b/src/core/window.c
|
|
@@ -1085,7 +1085,6 @@ _meta_window_shared_new (MetaDisplay *display,
|
|
/* if already mapped we don't want to do the placement thing;
|
|
* override-redirect windows are placed by the app */
|
|
window->placed = ((window->mapped && !window->hidden) || window->override_redirect);
|
|
- window->denied_focus_and_not_transient = FALSE;
|
|
window->unmanaging = FALSE;
|
|
window->is_in_queues = 0;
|
|
window->keys_grabbed = FALSE;
|
|
@@ -2360,8 +2359,8 @@ window_would_be_covered_by_always_above_window (MetaWindow *window)
|
|
}
|
|
|
|
void
|
|
-meta_window_force_placement (MetaWindow *window,
|
|
- gboolean force_move)
|
|
+meta_window_force_placement (MetaWindow *window,
|
|
+ MetaPlaceFlag place_flags)
|
|
{
|
|
MetaMoveResizeFlags flags;
|
|
|
|
@@ -2379,11 +2378,12 @@ meta_window_force_placement (MetaWindow *window,
|
|
window->calc_placement = TRUE;
|
|
|
|
flags = META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION;
|
|
- if (force_move)
|
|
+ if (place_flags & META_PLACE_FLAG_FORCE_MOVE)
|
|
flags |= META_MOVE_RESIZE_FORCE_MOVE;
|
|
|
|
meta_window_move_resize_internal (window,
|
|
flags,
|
|
+ place_flags,
|
|
META_GRAVITY_NORTH_WEST,
|
|
window->unconstrained_rect);
|
|
window->calc_placement = FALSE;
|
|
@@ -2393,11 +2393,6 @@ meta_window_force_placement (MetaWindow *window,
|
|
* still get placed when they are ultimately shown.
|
|
*/
|
|
window->placed = TRUE;
|
|
-
|
|
- /* Don't want to accidentally reuse the fact that we had been denied
|
|
- * focus in any future constraints unless we're denied focus again.
|
|
- */
|
|
- window->denied_focus_and_not_transient = FALSE;
|
|
}
|
|
|
|
static void
|
|
@@ -2410,6 +2405,7 @@ meta_window_show (MetaWindow *window)
|
|
MetaWindow *focus_window;
|
|
gboolean notify_demands_attention = FALSE;
|
|
MetaDisplay *display = window->display;
|
|
+ MetaPlaceFlag place_flags = META_PLACE_FLAG_NONE;
|
|
|
|
meta_topic (META_DEBUG_WINDOW_STATE,
|
|
"Showing window %s, shaded: %d iconic: %d placed: %d",
|
|
@@ -2446,7 +2442,7 @@ meta_window_show (MetaWindow *window)
|
|
{
|
|
needs_stacking_adjustment = TRUE;
|
|
if (!window->placed)
|
|
- window->denied_focus_and_not_transient = TRUE;
|
|
+ place_flags |= META_PLACE_FLAG_DENIED_FOCUS_AND_NOT_TRANSIENT;
|
|
}
|
|
}
|
|
|
|
@@ -2466,7 +2462,7 @@ meta_window_show (MetaWindow *window)
|
|
window->maximize_vertically_after_placement = TRUE;
|
|
}
|
|
}
|
|
- meta_window_force_placement (window, FALSE);
|
|
+ meta_window_force_placement (window, place_flags);
|
|
}
|
|
|
|
if (needs_stacking_adjustment)
|
|
@@ -2934,6 +2930,7 @@ meta_window_maximize (MetaWindow *window,
|
|
(META_MOVE_RESIZE_MOVE_ACTION |
|
|
META_MOVE_RESIZE_RESIZE_ACTION |
|
|
META_MOVE_RESIZE_STATE_CHANGED),
|
|
+ META_PLACE_FLAG_NONE,
|
|
META_GRAVITY_NORTH_WEST,
|
|
window->unconstrained_rect);
|
|
}
|
|
@@ -3202,6 +3199,7 @@ meta_window_tile (MetaWindow *window,
|
|
(META_MOVE_RESIZE_MOVE_ACTION |
|
|
META_MOVE_RESIZE_RESIZE_ACTION |
|
|
META_MOVE_RESIZE_STATE_CHANGED),
|
|
+ META_PLACE_FLAG_NONE,
|
|
META_GRAVITY_NORTH_WEST,
|
|
window->unconstrained_rect);
|
|
|
|
@@ -3411,6 +3409,7 @@ meta_window_unmaximize (MetaWindow *window,
|
|
META_MOVE_RESIZE_RESIZE_ACTION |
|
|
META_MOVE_RESIZE_STATE_CHANGED |
|
|
META_MOVE_RESIZE_UNMAXIMIZE),
|
|
+ META_PLACE_FLAG_NONE,
|
|
META_GRAVITY_NORTH_WEST,
|
|
target_rect);
|
|
|
|
@@ -3528,6 +3527,7 @@ meta_window_make_fullscreen (MetaWindow *window)
|
|
(META_MOVE_RESIZE_MOVE_ACTION |
|
|
META_MOVE_RESIZE_RESIZE_ACTION |
|
|
META_MOVE_RESIZE_STATE_CHANGED),
|
|
+ META_PLACE_FLAG_NONE,
|
|
META_GRAVITY_NORTH_WEST,
|
|
window->unconstrained_rect);
|
|
}
|
|
@@ -3575,6 +3575,7 @@ meta_window_unmake_fullscreen (MetaWindow *window)
|
|
META_MOVE_RESIZE_RESIZE_ACTION |
|
|
META_MOVE_RESIZE_STATE_CHANGED |
|
|
META_MOVE_RESIZE_UNFULLSCREEN),
|
|
+ META_PLACE_FLAG_NONE,
|
|
META_GRAVITY_NORTH_WEST,
|
|
target_rect);
|
|
|
|
@@ -3834,6 +3835,7 @@ meta_window_reposition (MetaWindow *window)
|
|
meta_window_move_resize_internal (window,
|
|
(META_MOVE_RESIZE_MOVE_ACTION |
|
|
META_MOVE_RESIZE_RESIZE_ACTION),
|
|
+ META_PLACE_FLAG_NONE,
|
|
META_GRAVITY_NORTH_WEST,
|
|
window->rect);
|
|
}
|
|
@@ -4005,6 +4007,7 @@ meta_window_update_monitor (MetaWindow *window,
|
|
void
|
|
meta_window_move_resize_internal (MetaWindow *window,
|
|
MetaMoveResizeFlags flags,
|
|
+ MetaPlaceFlag place_flags,
|
|
MetaGravity gravity,
|
|
MetaRectangle frame_rect)
|
|
{
|
|
@@ -4099,6 +4102,7 @@ meta_window_move_resize_internal (MetaWindow *window,
|
|
|
|
meta_window_constrain (window,
|
|
flags,
|
|
+ place_flags,
|
|
gravity,
|
|
&old_rect,
|
|
&constrained_rect,
|
|
@@ -4216,7 +4220,11 @@ meta_window_move_frame (MetaWindow *window,
|
|
g_return_if_fail (!window->override_redirect);
|
|
|
|
flags = (user_op ? META_MOVE_RESIZE_USER_ACTION : 0) | META_MOVE_RESIZE_MOVE_ACTION;
|
|
- meta_window_move_resize_internal (window, flags, META_GRAVITY_NORTH_WEST, rect);
|
|
+ meta_window_move_resize_internal (window,
|
|
+ flags,
|
|
+ META_PLACE_FLAG_NONE,
|
|
+ META_GRAVITY_NORTH_WEST,
|
|
+ rect);
|
|
}
|
|
|
|
static void
|
|
@@ -4249,6 +4257,7 @@ meta_window_move_between_rects (MetaWindow *window,
|
|
move_resize_flags |
|
|
META_MOVE_RESIZE_MOVE_ACTION |
|
|
META_MOVE_RESIZE_RESIZE_ACTION,
|
|
+ META_PLACE_FLAG_NONE,
|
|
META_GRAVITY_NORTH_WEST,
|
|
window->unconstrained_rect);
|
|
}
|
|
@@ -4280,7 +4289,11 @@ meta_window_move_resize_frame (MetaWindow *window,
|
|
|
|
flags = (user_op ? META_MOVE_RESIZE_USER_ACTION : 0) | META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION;
|
|
|
|
- meta_window_move_resize_internal (window, flags, META_GRAVITY_NORTH_WEST, rect);
|
|
+ meta_window_move_resize_internal (window,
|
|
+ flags,
|
|
+ META_PLACE_FLAG_NONE,
|
|
+ META_GRAVITY_NORTH_WEST,
|
|
+ rect);
|
|
}
|
|
|
|
/**
|
|
@@ -4379,7 +4392,11 @@ meta_window_resize_frame_with_gravity (MetaWindow *window,
|
|
}
|
|
|
|
flags = (user_op ? META_MOVE_RESIZE_USER_ACTION : 0) | META_MOVE_RESIZE_RESIZE_ACTION;
|
|
- meta_window_move_resize_internal (window, flags, gravity, rect);
|
|
+ meta_window_move_resize_internal (window,
|
|
+ flags,
|
|
+ META_PLACE_FLAG_NONE,
|
|
+ gravity,
|
|
+ rect);
|
|
}
|
|
|
|
static void
|
|
diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c
|
|
index c5f0d0b913..16c7cac60e 100644
|
|
--- a/src/wayland/meta-wayland-xdg-shell.c
|
|
+++ b/src/wayland/meta-wayland-xdg-shell.c
|
|
@@ -429,7 +429,7 @@ xdg_toplevel_set_maximized (struct wl_client *client,
|
|
if (!window->has_maximize_func)
|
|
return;
|
|
|
|
- meta_window_force_placement (window, TRUE);
|
|
+ meta_window_force_placement (window, META_PLACE_FLAG_FORCE_MOVE);
|
|
meta_window_maximize (window, META_MAXIMIZE_BOTH);
|
|
}
|
|
|
|
diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c
|
|
index 12e9567d9c..92cb684bb2 100644
|
|
--- a/src/wayland/meta-window-wayland.c
|
|
+++ b/src/wayland/meta-window-wayland.c
|
|
@@ -1000,7 +1000,11 @@ meta_window_wayland_finish_move_resize (MetaWindow *window,
|
|
gravity = meta_resize_gravity_from_grab_op (window->display->grab_op);
|
|
else
|
|
gravity = META_GRAVITY_STATIC;
|
|
- meta_window_move_resize_internal (window, flags, gravity, rect);
|
|
+ meta_window_move_resize_internal (window,
|
|
+ flags,
|
|
+ META_PLACE_FLAG_NONE,
|
|
+ gravity,
|
|
+ rect);
|
|
|
|
g_clear_pointer (&acked_configuration, meta_wayland_window_configuration_free);
|
|
}
|
|
@@ -1046,6 +1050,7 @@ meta_window_place_with_placement_rule (MetaWindow *window,
|
|
(META_MOVE_RESIZE_MOVE_ACTION |
|
|
META_MOVE_RESIZE_RESIZE_ACTION |
|
|
META_MOVE_RESIZE_PLACEMENT_CHANGED),
|
|
+ META_PLACE_FLAG_NONE,
|
|
META_GRAVITY_NORTH_WEST,
|
|
window->unconstrained_rect);
|
|
window->calc_placement = FALSE;
|
|
diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
|
|
index 204b49e93e..a4bd06bf0e 100644
|
|
--- a/src/x11/window-x11.c
|
|
+++ b/src/x11/window-x11.c
|
|
@@ -509,7 +509,11 @@ meta_window_apply_session_info (MetaWindow *window,
|
|
|
|
adjust_for_gravity (window, FALSE, gravity, &rect);
|
|
meta_window_client_rect_to_frame_rect (window, &rect, &rect);
|
|
- meta_window_move_resize_internal (window, flags, gravity, rect);
|
|
+ meta_window_move_resize_internal (window,
|
|
+ flags,
|
|
+ META_PLACE_FLAG_NONE,
|
|
+ gravity,
|
|
+ rect);
|
|
}
|
|
}
|
|
|
|
@@ -577,7 +581,11 @@ meta_window_x11_manage (MetaWindow *window)
|
|
|
|
adjust_for_gravity (window, TRUE, gravity, &rect);
|
|
meta_window_client_rect_to_frame_rect (window, &rect, &rect);
|
|
- meta_window_move_resize_internal (window, flags, gravity, rect);
|
|
+ meta_window_move_resize_internal (window,
|
|
+ flags,
|
|
+ META_PLACE_FLAG_NONE,
|
|
+ gravity,
|
|
+ rect);
|
|
}
|
|
|
|
meta_window_x11_update_shape_region (window);
|
|
@@ -2658,7 +2666,11 @@ meta_window_move_resize_request (MetaWindow *window,
|
|
|
|
adjust_for_gravity (window, TRUE, gravity, &rect);
|
|
meta_window_client_rect_to_frame_rect (window, &rect, &rect);
|
|
- meta_window_move_resize_internal (window, flags, gravity, rect);
|
|
+ meta_window_move_resize_internal (window,
|
|
+ flags,
|
|
+ META_PLACE_FLAG_NONE,
|
|
+ gravity,
|
|
+ rect);
|
|
}
|
|
}
|
|
|
|
--
|
|
2.44.0.501.g19981daefd.dirty
|
|
|
|
|
|
From e7b243bd6aee654b94812a402ad1a1f3103fdde3 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Thu, 11 Jul 2024 14:33:01 +0200
|
|
Subject: [PATCH 09/13] window: Move required condition into main if statement
|
|
in show()
|
|
|
|
No logical changes.
|
|
---
|
|
src/core/window.c | 10 ++++------
|
|
1 file changed, 4 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/src/core/window.c b/src/core/window.c
|
|
index f1c81c644b..aa5623682b 100644
|
|
--- a/src/core/window.c
|
|
+++ b/src/core/window.c
|
|
@@ -2435,15 +2435,13 @@ 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)))
|
|
{
|
|
- if (!meta_window_is_ancestor_of_transient (focus_window, window))
|
|
- {
|
|
- needs_stacking_adjustment = TRUE;
|
|
- if (!window->placed)
|
|
- place_flags |= META_PLACE_FLAG_DENIED_FOCUS_AND_NOT_TRANSIENT;
|
|
- }
|
|
+ needs_stacking_adjustment = TRUE;
|
|
+ if (!window->placed)
|
|
+ place_flags |= META_PLACE_FLAG_DENIED_FOCUS_AND_NOT_TRANSIENT;
|
|
}
|
|
|
|
if (!window->placed)
|
|
--
|
|
2.44.0.501.g19981daefd.dirty
|
|
|
|
|
|
From b92ae1e8d11719bdf2aaa00a80259ca8d7661a13 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Thu, 11 Jul 2024 14:46:04 +0200
|
|
Subject: [PATCH 10/13] window: Clarify expression for deciding whether to
|
|
auto-maximize
|
|
|
|
Calculate areas and store them in descriptively named variables, and
|
|
then compare them, instead of doing it all in one go.
|
|
---
|
|
src/core/window.c | 12 +++++++++---
|
|
1 file changed, 9 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/core/window.c b/src/core/window.c
|
|
index aa5623682b..8ab86933ef 100644
|
|
--- a/src/core/window.c
|
|
+++ b/src/core/window.c
|
|
@@ -2452,9 +2452,15 @@ meta_window_show (MetaWindow *window)
|
|
window->has_maximize_func)
|
|
{
|
|
MetaRectangle work_area;
|
|
- meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area);
|
|
- /* Automaximize windows that map with a size > MAX_UNMAXIMIZED_WINDOW_AREA of the work area */
|
|
- if (window->rect.width * window->rect.height > work_area.width * work_area.height * MAX_UNMAXIMIZED_WINDOW_AREA)
|
|
+ int window_area;
|
|
+ int work_area_area;
|
|
+
|
|
+ window_area = window->rect.width * window->rect.height;
|
|
+ meta_window_get_work_area_for_monitor (window, window->monitor->number,
|
|
+ &work_area);
|
|
+ work_area_area = work_area.width * work_area.height;
|
|
+
|
|
+ if (window_area > work_area_area * MAX_UNMAXIMIZED_WINDOW_AREA)
|
|
{
|
|
window->maximize_horizontally_after_placement = TRUE;
|
|
window->maximize_vertically_after_placement = TRUE;
|
|
--
|
|
2.44.0.501.g19981daefd.dirty
|
|
|
|
|
|
From b7d43ff70a9188b64e42d5cfd1d1be6c9ea3b768 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Thu, 11 Jul 2024 14:47:07 +0200
|
|
Subject: [PATCH 11/13] window: Fix minor coding style issue
|
|
|
|
---
|
|
src/core/window.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/src/core/window.c b/src/core/window.c
|
|
index 8ab86933ef..6a693a7a9d 100644
|
|
--- a/src/core/window.c
|
|
+++ b/src/core/window.c
|
|
@@ -4102,8 +4102,8 @@ meta_window_move_resize_internal (MetaWindow *window,
|
|
window->monitor)
|
|
{
|
|
MetaRectangle old_rect;
|
|
- meta_window_get_frame_rect (window, &old_rect);
|
|
|
|
+ meta_window_get_frame_rect (window, &old_rect);
|
|
meta_window_constrain (window,
|
|
flags,
|
|
place_flags,
|
|
--
|
|
2.44.0.501.g19981daefd.dirty
|
|
|
|
|
|
From 6397f60c9b5f06ece742bcaa2936b6501498ede7 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Thu, 11 Jul 2024 14:57:15 +0200
|
|
Subject: [PATCH 12/13] 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.
|
|
---
|
|
src/core/place.c | 11 ++++++++---
|
|
src/core/window.c | 10 ++++++++--
|
|
2 files changed, 16 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/src/core/place.c b/src/core/place.c
|
|
index 350e1ed0f1..e89aa4887b 100644
|
|
--- a/src/core/place.c
|
|
+++ b/src/core/place.c
|
|
@@ -296,7 +296,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;
|
|
MetaRectangle window_frame, focus_frame, overlap;
|
|
@@ -306,6 +308,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 meta_rectangle_intersect (&window_frame,
|
|
@@ -355,7 +360,7 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
|
|
if (flags & META_PLACE_FLAG_DENIED_FOCUS_AND_NOT_TRANSIENT &&
|
|
window->type == META_WINDOW_MODAL_DIALOG &&
|
|
meta_window_same_application (window, focus_window) &&
|
|
- 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,
|
|
@@ -906,7 +911,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 6a693a7a9d..6082a158a7 100644
|
|
--- a/src/core/window.c
|
|
+++ b/src/core/window.c
|
|
@@ -2436,8 +2436,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)
|
|
@@ -2469,6 +2469,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;
|
|
--
|
|
2.44.0.501.g19981daefd.dirty
|
|
|
|
|
|
From aefa1b34670124c0c95c741328c4095b55ec6333 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
Date: Thu, 11 Jul 2024 15:11:13 +0200
|
|
Subject: [PATCH 13/13] window: Only deny focus if mostly overlapped with
|
|
always-on-top window
|
|
|
|
Having an always-on-top window affects focus granting logic if the
|
|
to be showing window overlaps with any of them. Instead of triggering
|
|
the focus denying logic if a new window ever so slightly touches an
|
|
always-on-top window to only triggering if it's covered more than 60% by
|
|
always-on-top windows.
|
|
|
|
This is intended to make using always-on-top windows a bit less annoying
|
|
and not cause as many unintended focus-on-map denials.
|
|
---
|
|
src/core/window.c | 41 ++++++++++++++++++++++++++++++++++-------
|
|
1 file changed, 34 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/src/core/window.c b/src/core/window.c
|
|
index 6082a158a7..fe34023673 100644
|
|
--- a/src/core/window.c
|
|
+++ b/src/core/window.c
|
|
@@ -68,6 +68,7 @@
|
|
#include "backends/meta-backend-private.h"
|
|
#include "backends/meta-logical-monitor.h"
|
|
#include "cogl/cogl.h"
|
|
+#include "compositor/region-utils.h"
|
|
#include "core/boxes-private.h"
|
|
#include "core/constraints.h"
|
|
#include "core/edge-resistance.h"
|
|
@@ -2325,6 +2326,20 @@ windows_overlap (const MetaWindow *w1, const MetaWindow *w2)
|
|
return meta_rectangle_overlap (&w1rect, &w2rect);
|
|
}
|
|
|
|
+static int
|
|
+calculate_region_area (cairo_region_t *region)
|
|
+{
|
|
+ MetaRegionIterator iter;
|
|
+ int area = 0;
|
|
+
|
|
+ for (meta_region_iterator_init (&iter, region);
|
|
+ !meta_region_iterator_at_end (&iter);
|
|
+ meta_region_iterator_next (&iter))
|
|
+ area += iter.rectangle.width * iter.rectangle.height;
|
|
+
|
|
+ return area;
|
|
+}
|
|
+
|
|
/* Returns whether a new window would be covered by any
|
|
* existing window on the same workspace that is set
|
|
* to be "above" ("always on top"). A window that is not
|
|
@@ -2337,25 +2352,37 @@ windows_overlap (const MetaWindow *w1, const MetaWindow *w2)
|
|
* (say) ninety per cent and almost indistinguishable from total.
|
|
*/
|
|
static gboolean
|
|
-window_would_be_covered_by_always_above_window (MetaWindow *window)
|
|
+window_would_mostly_be_covered_by_always_above_window (MetaWindow *window)
|
|
{
|
|
MetaWorkspace *workspace = meta_window_get_workspace (window);
|
|
g_autoptr (GList) windows = NULL;
|
|
GList *l;
|
|
+ cairo_region_t *region;
|
|
+ int window_area, intersection_area, visible_area;
|
|
|
|
+ region = cairo_region_create ();
|
|
windows = meta_workspace_list_windows (workspace);
|
|
for (l = windows; l; l = l->next)
|
|
{
|
|
MetaWindow *other_window = l->data;
|
|
|
|
if (other_window->wm_state_above && other_window != window)
|
|
- {
|
|
- if (windows_overlap (other_window, window))
|
|
- return TRUE;
|
|
- }
|
|
+ cairo_region_union_rectangle (region, &other_window->rect);
|
|
}
|
|
|
|
- return FALSE;
|
|
+ window_area = window->rect.width * window->rect.height;
|
|
+
|
|
+ cairo_region_intersect_rectangle (region, &window->rect);
|
|
+ intersection_area = calculate_region_area (region);
|
|
+ visible_area = window_area - intersection_area;
|
|
+
|
|
+ cairo_region_destroy (region);
|
|
+
|
|
+#define REQUIRED_VISIBLE_AREA_PERCENT 40
|
|
+ if ((100 * visible_area) / window_area > REQUIRED_VISIBLE_AREA_PERCENT)
|
|
+ return FALSE;
|
|
+ else
|
|
+ return TRUE;
|
|
}
|
|
|
|
void
|
|
@@ -2472,7 +2499,7 @@ meta_window_show (MetaWindow *window)
|
|
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))
|
|
+ window_would_mostly_be_covered_by_always_above_window (window))
|
|
needs_stacking_adjustment = TRUE;
|
|
|
|
if (needs_stacking_adjustment)
|
|
--
|
|
2.44.0.501.g19981daefd.dirty
|
|
|