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
This commit is contained in:
Dan Winship 2011-05-06 05:09:04 -04:00
parent a8cfdc19e2
commit 6dc79ce60a
4 changed files with 33 additions and 41 deletions

View File

@ -754,7 +754,7 @@ constrain_modal_dialog (MetaWindow *window,
if (!meta_prefs_get_attach_modal_dialogs ()) if (!meta_prefs_get_attach_modal_dialogs ())
return TRUE; return TRUE;
if (window->type != META_WINDOW_MODAL_DIALOG || !parent || parent == window) if (window->type != META_WINDOW_MODAL_DIALOG || !parent)
return TRUE; return TRUE;
x = parent->rect.x + (parent->rect.width / 2 - info->current.width / 2); x = parent->rect.x + (parent->rect.width / 2 - info->current.width / 2);

View File

@ -5194,7 +5194,7 @@ prefs_changed_callback (MetaPreference pref,
MetaWindow *parent = meta_window_get_transient_for (w); MetaWindow *parent = meta_window_get_transient_for (w);
meta_window_recalc_features (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; int x, y;
/* Forcing a call to move_resize() does two things: first, it handles /* Forcing a call to move_resize() does two things: first, it handles

View File

@ -1468,6 +1468,8 @@ reload_transient_for (MetaWindow *window,
MetaPropValue *value, MetaPropValue *value,
gboolean initial) gboolean initial)
{ {
MetaWindow *parent = NULL;
if (window->has_focus && window->xtransient_for != None) if (window->has_focus && window->xtransient_for != None)
meta_window_propagate_focus_appearance (window, FALSE); meta_window_propagate_focus_appearance (window, FALSE);
@ -1477,14 +1479,33 @@ reload_transient_for (MetaWindow *window,
window->xtransient_for = value->v.xwindow; window->xtransient_for = value->v.xwindow;
/* Make sure transient_for is valid */ /* Make sure transient_for is valid */
if (window->xtransient_for != None && if (window->xtransient_for != None)
meta_display_lookup_x_window (window->display,
window->xtransient_for) == NULL)
{ {
meta_warning (_("Invalid WM_TRANSIENT_FOR window 0x%lx specified " parent = meta_display_lookup_x_window (window->display,
"for %s.\n"), window->xtransient_for);
window->xtransient_for, window->desc); if (!parent)
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;
}
}
/* 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 = window->transient_parent_is_root_window =

View File

@ -4214,7 +4214,7 @@ move_attached_dialog (MetaWindow *window,
{ {
MetaWindow *parent = meta_window_get_transient_for (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 */ /* It ignores x,y for such a dialog */
meta_window_move (window, FALSE, 0, 0); meta_window_move (window, FALSE, 0, 0);
@ -9258,46 +9258,17 @@ meta_window_foreach_ancestor (MetaWindow *window,
void *user_data) void *user_data)
{ {
MetaWindow *w; MetaWindow *w;
MetaWindow *tortoise;
w = window; w = window;
tortoise = window; do
while (TRUE)
{ {
if (w->xtransient_for == None || if (w->xtransient_for == None ||
w->transient_parent_is_root_window) w->transient_parent_is_root_window)
break; break;
w = meta_display_lookup_x_window (w->display, w->xtransient_for); 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 typedef struct