GdkWindow: Track all native windows of native windows

We keep a list of all native children of a native window. This means
we don't have to recurse over the entire hierarchy to find any
native children.
This commit is contained in:
Alexander Larsson 2013-05-15 10:23:14 +02:00
parent 3a414e0ace
commit 8306d26714
4 changed files with 41 additions and 4 deletions

View File

@ -189,6 +189,7 @@ struct _GdkWindow
GList *filters; GList *filters;
GList *children; GList *children;
GList *native_children;
cairo_pattern_t *background; cairo_pattern_t *background;

View File

@ -1375,6 +1375,9 @@ gdk_window_new (GdkWindow *parent,
_gdk_display_create_window_impl (display, window, real_parent, screen, event_mask, attributes, attributes_mask); _gdk_display_create_window_impl (display, window, real_parent, screen, event_mask, attributes, attributes_mask);
window->impl_window = window; window->impl_window = window;
if (parent)
parent->impl_window->native_children = g_list_prepend (parent->impl_window->native_children, window);
/* This will put the native window topmost in the native parent, which may /* This will put the native window topmost in the native parent, which may
* be wrong wrt other native windows in the non-native hierarchy, so restack */ * be wrong wrt other native windows in the non-native hierarchy, so restack */
if (!_gdk_window_has_impl (real_parent)) if (!_gdk_window_has_impl (real_parent))
@ -1444,6 +1447,14 @@ change_impl (GdkWindow *private,
if (child->impl == old_impl) if (child->impl == old_impl)
change_impl (child, impl_window, new); change_impl (child, impl_window, new);
else
{
/* The child is a native, update native_children */
old_impl_window->native_children =
g_list_remove (old_impl_window->native_children, child);
impl_window->native_children =
g_list_prepend (impl_window->native_children, child);
}
} }
} }
@ -1570,7 +1581,13 @@ gdk_window_reparent (GdkWindow *window,
} }
if (old_parent) if (old_parent)
old_parent->children = g_list_remove (old_parent->children, window); {
old_parent->children = g_list_remove (old_parent->children, window);
if (gdk_window_has_impl (window))
old_parent->impl_window->native_children =
g_list_remove (old_parent->impl_window->native_children, window);
}
window->parent = new_parent; window->parent = new_parent;
window->x = x; window->x = x;
@ -1578,6 +1595,9 @@ gdk_window_reparent (GdkWindow *window,
new_parent->children = g_list_prepend (new_parent->children, window); new_parent->children = g_list_prepend (new_parent->children, window);
if (gdk_window_has_impl (window))
new_parent->impl_window->native_children = g_list_prepend (new_parent->impl_window->native_children, window);
/* Switch the window type as appropriate */ /* Switch the window type as appropriate */
switch (GDK_WINDOW_TYPE (new_parent)) switch (GDK_WINDOW_TYPE (new_parent))
@ -1686,7 +1706,7 @@ gdk_window_ensure_native (GdkWindow *window)
GdkWindowImpl *new_impl, *old_impl; GdkWindowImpl *new_impl, *old_impl;
GdkDisplay *display; GdkDisplay *display;
GdkScreen *screen; GdkScreen *screen;
GdkWindow *above; GdkWindow *above, *parent;
GList listhead; GList listhead;
GdkWindowImplClass *impl_class; GdkWindowImplClass *impl_class;
@ -1711,15 +1731,20 @@ gdk_window_ensure_native (GdkWindow *window)
screen = gdk_window_get_screen (window); screen = gdk_window_get_screen (window);
display = gdk_screen_get_display (screen); display = gdk_screen_get_display (screen);
parent = window->parent;
old_impl = window->impl; old_impl = window->impl;
_gdk_display_create_window_impl (display, _gdk_display_create_window_impl (display,
window, window->parent, window, parent,
screen, screen,
get_native_event_mask (window), get_native_event_mask (window),
NULL, 0); NULL, 0);
new_impl = window->impl; new_impl = window->impl;
if (parent)
parent->impl_window->native_children =
g_list_prepend (parent->impl_window->native_children, window);
window->impl = old_impl; window->impl = old_impl;
change_impl (window, window, new_impl); change_impl (window, window, new_impl);
@ -1729,7 +1754,7 @@ gdk_window_ensure_native (GdkWindow *window)
* native parent, which may be wrong wrt the position of the previous * native parent, which may be wrong wrt the position of the previous
* non-native window wrt to the other non-native children, so correct this. * non-native window wrt to the other non-native children, so correct this.
*/ */
above = find_native_sibling_above (window->parent, window); above = find_native_sibling_above (parent, window);
if (above) if (above)
{ {
listhead.data = window; listhead.data = window;
@ -1925,6 +1950,10 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
if (window->parent->children) if (window->parent->children)
window->parent->children = g_list_remove (window->parent->children, window); window->parent->children = g_list_remove (window->parent->children, window);
if (gdk_window_has_impl (window))
window->parent->impl_window->native_children =
g_list_remove (window->parent->impl_window->native_children, window);
if (!recursing && if (!recursing &&
GDK_WINDOW_IS_MAPPED (window)) GDK_WINDOW_IS_MAPPED (window))
{ {
@ -1967,6 +1996,9 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
} }
g_list_free (children); g_list_free (children);
if (gdk_window_has_impl (window))
g_assert (window->native_children == NULL);
} }
_gdk_window_clear_update_area (window); _gdk_window_clear_update_area (window);

View File

@ -714,6 +714,8 @@ gdk_win32_window_foreign_new_for_display (GdkDisplay *display,
window->parent = _gdk_root; window->parent = _gdk_root;
window->parent->children = g_list_prepend (window->parent->children, window); window->parent->children = g_list_prepend (window->parent->children, window);
window->parent->impl_window->native_children =
g_list_prepend (window->parent->impl_window->native_children, window);
GetClientRect ((HWND) anid, &rect); GetClientRect ((HWND) anid, &rect);
point.x = rect.left; point.x = rect.left;

View File

@ -1226,6 +1226,8 @@ gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
win->parent = gdk_screen_get_root_window (screen); win->parent = gdk_screen_get_root_window (screen);
win->parent->children = g_list_prepend (win->parent->children, win); win->parent->children = g_list_prepend (win->parent->children, win);
win->parent->impl_window->native_children =
g_list_prepend (win->parent->impl_window->native_children, win);
impl->xid = window; impl->xid = window;