From bac668d287deebee928f73d8938cc32ac73646ef Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Sat, 13 Nov 2010 14:45:01 -0500 Subject: [PATCH] Optimize out restacks that don't change actor order For various reasons (mostly the stack tracker correctly predicting the stacking order before getting events, but also because of the processing that the compositor does to get the actor stacking order) the compositor can be told to sync the stack when it has nothing to do. Detect this at the last moment before actually telling Clutter to restack to avoid triggering unnecessary redraws. https://bugzilla.gnome.org/show_bug.cgi?id=634771 --- src/compositor/compositor.c | 49 +++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index ad964b6ad..7eb10defa 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -34,7 +34,7 @@ composite_at_least_version (MetaDisplay *display, int maj, int min) return (major > maj || (major == maj && minor >= min)); } -static void sync_actor_stacking (GList *windows); +static void sync_actor_stacking (MetaCompScreen *info); static void meta_finish_workspace_switch (MetaCompScreen *info) @@ -48,7 +48,7 @@ meta_finish_workspace_switch (MetaCompScreen *info) /* * Fix up stacking order in case the plugin messed it up. */ - sync_actor_stacking (info->windows); + sync_actor_stacking (info); /* printf ("... FINISHED DESKTOP SWITCH\n"); */ @@ -87,7 +87,7 @@ add_win (MetaWindow *window) meta_window_actor_new (window); - sync_actor_stacking (info->windows); + sync_actor_stacking (info); } static void @@ -827,13 +827,48 @@ meta_compositor_switch_workspace (MetaCompositor *compositor, } static void -sync_actor_stacking (GList *windows) +sync_actor_stacking (MetaCompScreen *info) { + GList *children; GList *tmp; + GList *old; + gboolean reordered; - /* NB: The first entry in the list is stacked the lowest */ + /* NB: The first entries in the lists are stacked the lowest */ - for (tmp = g_list_last (windows); tmp != NULL; tmp = tmp->prev) + /* Restacking will trigger full screen redraws, so it's worth a + * little effort to make sure we actually need to restack before + * we go ahead and do it */ + + children = clutter_container_get_children (CLUTTER_CONTAINER (info->window_group)); + reordered = FALSE; + + old = children; + for (tmp = info->windows; tmp != NULL; tmp = tmp->next) + { + while (old && !META_IS_WINDOW_ACTOR (old->data)) + old = old->next; + + /* old == NULL: someone reparented a window out of the window group, + * order undefined, always restack */ + if (old == NULL || old->data != tmp->data) + { + reordered = TRUE; + break; + } + + old = old->next; + } + + if (old != NULL) /* An extra MetaWindowActor??? .... restack */ + reordered = TRUE; + + g_list_free (children); + + if (!reordered) + return; + + for (tmp = g_list_last (info->windows); tmp != NULL; tmp = tmp->prev) { MetaWindowActor *window_actor = tmp->data; @@ -927,7 +962,7 @@ meta_compositor_sync_stack (MetaCompositor *compositor, old_stack = g_list_remove (old_stack, actor); } - sync_actor_stacking (info->windows); + sync_actor_stacking (info); } void