From d34e54785d89967333ed8423085e60aa143c3f5a Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Mon, 17 Mar 2003 06:36:39 +0000 Subject: [PATCH] Should fix #108108, #106217, tracked down by Owen Taylor and Frederic 2003-03-11 Havoc Pennington Should fix #108108, #106217, tracked down by Owen Taylor and Frederic Crozat * src/window.c (meta_window_foreach_transient): change MetaWindowForeachFunc to return a boolean for whether to continue (meta_window_foreach_ancestor): new function (window_should_be_showing): use meta_window_foreach_ancestor (unminimize_window_and_all_transient_parents): ditto (update_sm_hints): ditto (meta_window_is_ancestor_of_transient): ditto * src/stack.c (get_maximum_layer_of_ancestor): use meta_window_foreach_ancestor --- ChangeLog | 16 ++++ src/stack.c | 51 ++++++------ src/window.c | 229 +++++++++++++++++++++++++++++++++------------------ src/window.h | 17 ++-- 4 files changed, 197 insertions(+), 116 deletions(-) diff --git a/ChangeLog b/ChangeLog index 53ba73d97..b8a8b7ecc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2003-03-11 Havoc Pennington + + Should fix #108108, #106217, tracked down by Owen Taylor and + Frederic Crozat + + * src/window.c (meta_window_foreach_transient): change + MetaWindowForeachFunc to return a boolean for whether to continue + (meta_window_foreach_ancestor): new function + (window_should_be_showing): use meta_window_foreach_ancestor + (unminimize_window_and_all_transient_parents): ditto + (update_sm_hints): ditto + (meta_window_is_ancestor_of_transient): ditto + + * src/stack.c (get_maximum_layer_of_ancestor): use + meta_window_foreach_ancestor + 2003-03-16 Rob Adams * window.c (meta_window_show_menu): Free old window menu if it diff --git a/src/stack.c b/src/stack.c index 1f81b5ea6..5ad699c0a 100644 --- a/src/stack.c +++ b/src/stack.c @@ -262,37 +262,34 @@ get_standalone_layer (MetaWindow *window) return layer; } +typedef struct +{ + MetaStackLayer max; +} MaxLayerData; + +static gboolean +max_layer_func (MetaWindow *window, + void *data) +{ + MaxLayerData *d = data; + MetaStackLayer layer; + + layer = get_standalone_layer (window); + if (layer > d->max) + d->max = layer; + + return TRUE; +} + static MetaStackLayer get_maximum_layer_of_ancestor (MetaWindow *window) { - MetaWindow *w; - MetaStackLayer max; - MetaStackLayer layer; - - max = get_standalone_layer (window); - - w = window; - while (w != NULL) - { - 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 == window) - break; /* Cute, someone thought they'd make a transient_for cycle */ - - /* w may be null... */ - if (w != NULL) - { - layer = get_standalone_layer (w); - if (layer > max) - max = layer; - } - } + MaxLayerData d; - return max; + d.max = get_standalone_layer (window); + meta_window_foreach_ancestor (window, max_layer_func, &d); + + return d.max; } /* Note that this function can never use window->layer only diff --git a/src/window.c b/src/window.c index f5bf5c4cd..a12938d84 100644 --- a/src/window.c +++ b/src/window.c @@ -1124,6 +1124,31 @@ meta_window_visible_on_workspace (MetaWindow *window, meta_workspace_contains_window (workspace, window); } +static gboolean +is_minimized_foreach (MetaWindow *window, + void *data) +{ + gboolean *result = data; + + *result = window->minimized; + if (*result) + return FALSE; /* stop as soon as we find one */ + else + return TRUE; +} + +static gboolean +ancestor_is_minimized (MetaWindow *window) +{ + gboolean is_minimized; + + is_minimized = FALSE; + + meta_window_foreach_ancestor (window, is_minimized_foreach, &is_minimized); + + return is_minimized; +} + static gboolean window_should_be_showing (MetaWindow *window) { @@ -1173,28 +1198,8 @@ window_should_be_showing (MetaWindow *window) if (showing) { - MetaWindow *w; - - w = window; - while (w != NULL) - { - if (w->minimized) - { - showing = FALSE; - 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 == window) - break; /* Cute, someone thought they'd make a transient_for cycle */ - - /* w may be null... */ - } + if (ancestor_is_minimized (window)) + showing = FALSE; } return showing; @@ -1701,11 +1706,12 @@ meta_window_hide (MetaWindow *window) } } -static void +static gboolean queue_calc_showing_func (MetaWindow *window, void *data) { meta_window_queue_calc_showing (window); + return TRUE; } void @@ -1942,27 +1948,19 @@ meta_window_unshade (MetaWindow *window) } } +static gboolean +unminimize_func (MetaWindow *window, + void *data) +{ + meta_window_unminimize (window); + return TRUE; +} + static void unminimize_window_and_all_transient_parents (MetaWindow *window) { - MetaWindow *w; - - w = window; - while (w != NULL) - { - meta_window_unminimize (w); - - 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 == window) - break; /* Cute, someone thought they'd make a transient_for cycle */ - - /* w may be null... */ - } + meta_window_unminimize (window); + meta_window_foreach_ancestor (window, unminimize_func, NULL); } void @@ -3141,11 +3139,12 @@ meta_window_change_workspace_without_transients (MetaWindow *window, g_assert (window->workspaces->next == NULL); } -static void +static gboolean change_workspace_foreach (MetaWindow *window, void *data) { meta_window_change_workspace_without_transients (window, data); + return TRUE; } void @@ -4465,10 +4464,29 @@ read_client_leader (MetaDisplay *display, return retval; } +typedef struct +{ + Window leader; +} ClientLeaderData; + +static gboolean +find_client_leader_func (MetaWindow *ancestor, + void *data) +{ + ClientLeaderData *d; + + d = data; + + d->leader = read_client_leader (ancestor->display, + ancestor->xwindow); + + /* keep going if no client leader found */ + return d->leader == None; +} + static void update_sm_hints (MetaWindow *window) { - MetaWindow *w; Window leader; window->xclient_leader = None; @@ -4478,26 +4496,17 @@ update_sm_hints (MetaWindow *window) * leader from transient parents. If we find a client * leader, we read the SM_CLIENT_ID from it. */ - leader = None; - w = window; - while (w != NULL) + leader = read_client_leader (window->display, window->xwindow); + if (leader == None) { - leader = read_client_leader (window->display, w->xwindow); - - if (leader != None) - 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 == window) - break; /* Cute, someone thought they'd make a transient_for cycle */ + ClientLeaderData d; + d.leader = None; + meta_window_foreach_ancestor (window, find_client_leader_func, + &d); + leader = d.leader; } - if (leader) + if (leader != None) { char *str; @@ -6237,7 +6246,10 @@ meta_window_foreach_transient (MetaWindow *window, MetaWindow *transient = tmp->data; if (meta_window_is_ancestor_of_transient (window, transient)) - (* func) (transient, data); + { + if (!(* func) (transient, data)) + break; + } tmp = tmp->next; } @@ -6245,34 +6257,87 @@ meta_window_foreach_transient (MetaWindow *window, g_slist_free (windows); } +void +meta_window_foreach_ancestor (MetaWindow *window, + MetaWindowForeachFunc func, + void *data) +{ + MetaWindow *w; + MetaWindow *tortoise; + + w = window; + tortoise = window; + while (TRUE) + { + 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, 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, 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); + } +} + +typedef struct +{ + MetaWindow *ancestor; + gboolean found; +} FindAncestorData; + +static gboolean +find_ancestor_func (MetaWindow *window, + void *data) +{ + FindAncestorData *d = data; + + if (window == d->ancestor) + { + d->found = TRUE; + return FALSE; + } + + return TRUE; +} + gboolean meta_window_is_ancestor_of_transient (MetaWindow *window, MetaWindow *transient) { - MetaWindow *w; + FindAncestorData d; - if (window == transient) - return FALSE; - - w = transient; - while (w != NULL) - { - if (w->xtransient_for == None || - w->transient_parent_is_root_window) - return FALSE; + d.ancestor = window; + d.found = FALSE; - if (w->xtransient_for == window->xwindow) - return TRUE; - - w = meta_display_lookup_x_window (w->display, w->xtransient_for); - - if (w == transient) - return FALSE; /* Cycle */ - - /* w may be null... */ - } + meta_window_foreach_ancestor (transient, find_ancestor_func, &d); - return FALSE; + return d.found; } static gboolean diff --git a/src/window.h b/src/window.h index 202bddfaf..2c331d847 100644 --- a/src/window.h +++ b/src/window.h @@ -33,8 +33,8 @@ typedef struct _MetaGroup MetaGroup; -typedef void (*MetaWindowForeachFunc) (MetaWindow *window, - void *data); +typedef gboolean (*MetaWindowForeachFunc) (MetaWindow *window, + void *data); typedef enum { @@ -442,11 +442,14 @@ void meta_window_refresh_resize_popup (MetaWindow *window); void meta_window_free_delete_dialog (MetaWindow *window); -void meta_window_foreach_transient (MetaWindow *window, - MetaWindowForeachFunc func, - void *data); -gboolean meta_window_is_ancestor_of_transient (MetaWindow *window, - MetaWindow *transient); +void meta_window_foreach_transient (MetaWindow *window, + MetaWindowForeachFunc func, + void *data); +gboolean meta_window_is_ancestor_of_transient (MetaWindow *window, + MetaWindow *transient); +void meta_window_foreach_ancestor (MetaWindow *window, + MetaWindowForeachFunc func, + void *data); gboolean meta_window_warp_pointer (MetaWindow *window, MetaGrabOp grab_op);