From 4ef11cfbd38d3772dc05aa5a0804372d6fc33dec Mon Sep 17 00:00:00 2001 From: Thomas Thurman Date: Tue, 16 Oct 2007 22:29:59 +0000 Subject: [PATCH] new function. rewrite assertion not to put window on top in terms of 2007-10-16 Thomas Thurman * src/window.c (window_would_be_covered): new function. * src/window.c (meta_window_show): rewrite assertion not to put window on top in terms of window_would_be_covered(); remove assertion because it's no longer valid; explicitly don't focus windows that shouldn't be focussed; closes #486445. svn path=/trunk/; revision=3358 --- ChangeLog | 8 ++++++ src/window.c | 78 ++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 72 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5550d3e92..9b4b1c9f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2007-10-16 Thomas Thurman + + * src/window.c (window_would_be_covered): new function. + * src/window.c (meta_window_show): rewrite assertion not + to put window on top in terms of window_would_be_covered(); + remove assertion because it's no longer valid; explicitly + don't focus windows that shouldn't be focussed; closes #486445. + 2007-10-14 Thomas Thurman * configure.in: Post-branch bump to 2.21.1. diff --git a/src/window.c b/src/window.c index fac38259a..a8ceda628 100644 --- a/src/window.c +++ b/src/window.c @@ -1954,6 +1954,47 @@ windows_overlap (const MetaWindow *w1, const MetaWindow *w2) return meta_rectangle_overlap (&w1rect, &w2rect); } +/* 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 + * set "above" would be underneath the new window anyway. + * + * We take "covered" to mean even partially covered, but + * some people might prefer entirely covered. I think it + * is more useful to behave this way if any part of the + * window is covered, because a partial coverage could be + * (say) ninety per cent and almost indistinguishable from total. + */ +static gboolean +window_would_be_covered (const MetaWindow *newbie) +{ + MetaWorkspace *workspace = newbie->workspace; + GList *tmp, *windows; + + windows = meta_workspace_list_windows (workspace); + + tmp = windows; + while (tmp != NULL) + { + MetaWindow *w = tmp->data; + + if (w->wm_state_above) + { + /* 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 */ + } + } + + tmp = tmp->next; + } + + g_list_free (windows); + return FALSE; /* none found */ +} + /* XXX META_EFFECT_*_MAP */ void meta_window_show (MetaWindow *window) @@ -1986,11 +2027,24 @@ meta_window_show (MetaWindow *window) takes_focus_on_map ? "does" : "does not", place_on_top_on_map ? "does" : "does not"); - if ( !takes_focus_on_map && - focus_window != NULL && - !place_on_top_on_map && - window->showing_for_first_time ) - { + /* Now, in some rare cases we should *not* put a new window on top. + * These cases include certain types of windows showing for the firat + * time, and any window which would be covered because of another window + * being set "above" ("always on top"). + * + * FIXME: Although "place_on_top_on_map" and "takes_focus_on_map" are + * generally based on the window type, there is a special case when the + * focus window is a terminal for them both to be false; this should + * 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 (meta_window_is_ancestor_of_transient (focus_window, window)) { /* This happens for error dialogs or alerts; these need to remain on @@ -2045,22 +2099,18 @@ meta_window_show (MetaWindow *window) { gboolean overlap; - /* needs_stacking_adjustment is only set under certain - * circumstances currently; if those circumstances change, this - * code may need re-thinking too - */ - g_assert(window->showing_for_first_time && - !place_on_top_on_map && - !takes_focus_on_map && - focus_window != NULL); - /* This window isn't getting focus on map. We may need to do some * special handing with it in regards to * - the stacking of the window * - the MRU position of the window * - the demands attention setting of the window + * + * Firstly, set the flag so we don't give the window focus anyway + * and confuse people. */ + takes_focus_on_map = FALSE; + overlap = windows_overlap (window, focus_window); /* We want alt tab to go to the denied-focus window */