window: Make process_updates faster

Only look at "impl" windows in gdk_window_process_updates_with_mode()
since these are the only ones we care about.  This avoids a lot of
unnecessary calls to g_list_copy() and g_object_ref().
This commit is contained in:
John Lindgren 2013-06-26 10:03:51 +02:00 committed by Alexander Larsson
parent d7260d4ee9
commit 5fa0da4200

View File

@ -3615,59 +3615,77 @@ enum {
PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN
};
static GList *
find_impl_windows_to_update (GList *list,
GdkWindow *window,
gint recurse_mode)
{
GList *node;
if (GDK_WINDOW_DESTROYED (window))
return list;
/* Recurse first, so that we process updates in reverse stacking
* order so composition or painting over achieves the desired effect
* for offscreen windows
*/
if (recurse_mode != PROCESS_UPDATES_NO_RECURSE)
{
for (node = window->children; node; node = node->next)
{
GdkWindow *child = node->data;
if (recurse_mode == PROCESS_UPDATES_WITH_ALL_CHILDREN ||
(recurse_mode == PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN &&
child->frame_clock == NULL))
{
list = find_impl_windows_to_update (list, child, recurse_mode);
}
}
}
/* add reference count so the window cannot be deleted in a callback */
if (window->impl_window == window)
list = g_list_prepend (list, g_object_ref (window));
return list;
}
static void
gdk_window_process_updates_with_mode (GdkWindow *window,
int recurse_mode)
{
GdkWindow *impl_window;
GList *list = NULL;
GList *node;
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
return;
/* Make sure the window lives during the expose callouts */
g_object_ref (window);
list = find_impl_windows_to_update (list, window, recurse_mode);
impl_window = gdk_window_get_impl_window (window);
if ((impl_window->update_area) &&
!impl_window->update_freeze_count &&
!gdk_window_is_toplevel_frozen (window) &&
if (window->impl_window != window)
list = g_list_prepend (list, g_object_ref (window->impl_window));
/* Don't recurse into process_updates_internal, we'll
* do the update later when idle instead. */
!impl_window->in_update)
for (node = list; node; node = node->next)
{
gdk_window_process_updates_internal ((GdkWindow *)impl_window);
gdk_window_remove_update_window ((GdkWindow *)impl_window);
GdkWindow *impl_window = node->data;
if (impl_window->update_area &&
!impl_window->update_freeze_count &&
!gdk_window_is_toplevel_frozen (impl_window) &&
/* Don't recurse into process_updates_internal, we'll
* do the update later when idle instead. */
!impl_window->in_update)
{
gdk_window_process_updates_internal (impl_window);
gdk_window_remove_update_window (impl_window);
}
}
if (recurse_mode != PROCESS_UPDATES_NO_RECURSE)
{
/* process updates in reverse stacking order so composition or
* painting over achieves the desired effect for offscreen windows
*/
GList *node, *children;
children = g_list_copy (window->children);
g_list_foreach (children, (GFunc)g_object_ref, NULL);
for (node = g_list_last (children); node; node = node->prev)
{
GdkWindow *child = node->data;
if (recurse_mode == PROCESS_UPDATES_WITH_ALL_CHILDREN ||
(recurse_mode == PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN &&
child->frame_clock == NULL))
{
gdk_window_process_updates (child, TRUE);
}
g_object_unref (child);
}
g_list_free (children);
}
g_object_unref (window);
g_list_free_full (list, g_object_unref);
}
/**