From 6dc79ce60ad83c89e5dc1fa9e33b97d51fd3b9c4 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 6 May 2011 05:09:04 -0400 Subject: [PATCH] reload_transient_for: avoid xtransient_for loops Don't set a window's xtransient_for if it would create a loop. Since this is the only place we ever set xtransient_for, we can therefore assume everywhere else that it does not loop. https://bugzilla.gnome.org/show_bug.cgi?id=647712 --- src/core/constraints.c | 2 +- src/core/display.c | 2 +- src/core/window-props.c | 35 ++++++++++++++++++++++++++++------- src/core/window.c | 35 +++-------------------------------- 4 files changed, 33 insertions(+), 41 deletions(-) diff --git a/src/core/constraints.c b/src/core/constraints.c index 0d4a94fed..67078a009 100644 --- a/src/core/constraints.c +++ b/src/core/constraints.c @@ -754,7 +754,7 @@ constrain_modal_dialog (MetaWindow *window, if (!meta_prefs_get_attach_modal_dialogs ()) return TRUE; - if (window->type != META_WINDOW_MODAL_DIALOG || !parent || parent == window) + if (window->type != META_WINDOW_MODAL_DIALOG || !parent) return TRUE; x = parent->rect.x + (parent->rect.width / 2 - info->current.width / 2); diff --git a/src/core/display.c b/src/core/display.c index 8b1b5f210..b93f15aef 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -5194,7 +5194,7 @@ prefs_changed_callback (MetaPreference pref, MetaWindow *parent = meta_window_get_transient_for (w); meta_window_recalc_features (w); - if (w->type == META_WINDOW_MODAL_DIALOG && parent && parent != w) + if (w->type == META_WINDOW_MODAL_DIALOG && parent) { int x, y; /* Forcing a call to move_resize() does two things: first, it handles diff --git a/src/core/window-props.c b/src/core/window-props.c index 94b5a94f5..e970ffef7 100644 --- a/src/core/window-props.c +++ b/src/core/window-props.c @@ -1468,6 +1468,8 @@ reload_transient_for (MetaWindow *window, MetaPropValue *value, gboolean initial) { + MetaWindow *parent = NULL; + if (window->has_focus && window->xtransient_for != None) meta_window_propagate_focus_appearance (window, FALSE); @@ -1477,14 +1479,33 @@ reload_transient_for (MetaWindow *window, window->xtransient_for = value->v.xwindow; /* Make sure transient_for is valid */ - if (window->xtransient_for != None && - meta_display_lookup_x_window (window->display, - window->xtransient_for) == NULL) + if (window->xtransient_for != None) { - meta_warning (_("Invalid WM_TRANSIENT_FOR window 0x%lx specified " - "for %s.\n"), - window->xtransient_for, window->desc); - window->xtransient_for = None; + parent = meta_display_lookup_x_window (window->display, + window->xtransient_for); + if (!parent) + { + meta_warning (_("Invalid WM_TRANSIENT_FOR window 0x%lx specified " + "for %s.\n"), + window->xtransient_for, window->desc); + window->xtransient_for = None; + } + } + + /* Make sure there is not a loop */ + while (parent) + { + if (parent == window) + { + meta_warning (_("WM_TRANSIENT_FOR window 0x%lx for %s " + "would create loop.\n"), + window->xtransient_for, window->desc); + window->xtransient_for = None; + break; + } + + parent = meta_display_lookup_x_window (parent->display, + parent->xtransient_for); } window->transient_parent_is_root_window = diff --git a/src/core/window.c b/src/core/window.c index d2deb53c1..a06906017 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -4214,7 +4214,7 @@ move_attached_dialog (MetaWindow *window, { MetaWindow *parent = meta_window_get_transient_for (window); - if (window->type == META_WINDOW_MODAL_DIALOG && parent && parent != window) + if (window->type == META_WINDOW_MODAL_DIALOG && parent) /* It ignores x,y for such a dialog */ meta_window_move (window, FALSE, 0, 0); @@ -9258,46 +9258,17 @@ meta_window_foreach_ancestor (MetaWindow *window, void *user_data) { MetaWindow *w; - MetaWindow *tortoise; w = window; - tortoise = window; - while (TRUE) + do { if (w->xtransient_for == None || w->transient_parent_is_root_window) break; w = meta_display_lookup_x_window (w->display, w->xtransient_for); - - if (w == NULL || w == tortoise) - break; - - if (!(* func) (w, user_data)) - break; - - if (w->xtransient_for == None || - w->transient_parent_is_root_window) - break; - - w = meta_display_lookup_x_window (w->display, w->xtransient_for); - - if (w == NULL || w == tortoise) - break; - - if (!(* func) (w, user_data)) - break; - - tortoise = meta_display_lookup_x_window (tortoise->display, - tortoise->xtransient_for); - - /* "w" should have already covered all ground covered by the - * tortoise, so the following must hold. - */ - g_assert (tortoise != NULL); - g_assert (tortoise->xtransient_for != None); - g_assert (!tortoise->transient_parent_is_root_window); } + while (w && (* func) (w, user_data)); } typedef struct