From aa8693f2cb67d29720672203bcc9a36a3660ad29 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Sat, 18 Jul 2009 20:29:50 +0200 Subject: [PATCH] Track viewable for GdkWindow --- gdk/directfb/gdkwindow-directfb.c | 2 + gdk/gdkevents.c | 3 ++ gdk/gdkinternals.h | 2 + gdk/gdkwindow.c | 63 +++++++++++++++++++++++-------- gdk/quartz/gdkwindow-quartz.c | 1 + gdk/win32/gdkwindow-win32.c | 2 + gdk/x11/gdkwindow-x11.c | 4 +- 7 files changed, 61 insertions(+), 16 deletions(-) diff --git a/gdk/directfb/gdkwindow-directfb.c b/gdk/directfb/gdkwindow-directfb.c index 7f82a6d083..b7795f8ea4 100644 --- a/gdk/directfb/gdkwindow-directfb.c +++ b/gdk/directfb/gdkwindow-directfb.c @@ -313,6 +313,7 @@ _gdk_windowing_window_init (void) private->window_type = GDK_WINDOW_ROOT; private->state = 0; private->children = NULL; + private->viewable = TRUE; // impl->drawable.paint_region = NULL; impl->gdkWindow = _gdk_parent_root; impl->window = NULL; @@ -2501,6 +2502,7 @@ gdk_window_foreign_new_for_display (GdkDisplay* display,GdkNativeWindow anid) private->impl = g_object_new (_gdk_window_impl_get_type (), NULL); private->parent = parent_private; private->window_type = GDK_WINDOW_TOPLEVEL; + private->viewable = TRUE; impl = GDK_WINDOW_IMPL_DIRECTFB (private->impl); impl->drawable.wrapper = GDK_DRAWABLE (window); diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c index 3af4195cc9..90e16d7bd8 100644 --- a/gdk/gdkevents.c +++ b/gdk/gdkevents.c @@ -1266,6 +1266,9 @@ gdk_synthesize_window_state (GdkWindow *window, ((GdkWindowObject*) window)->state = temp_event.window_state.new_window_state; + if (temp_event.window_state.changed_mask & GDK_WINDOW_STATE_WITHDRAWN) + _gdk_window_update_viewable (window); + /* We only really send the event to toplevels, since * all the window states don't apply to non-toplevels. * Non-toplevels do use the GDK_WINDOW_STATE_WITHDRAWN flag diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index 6d1a4d0613..ec29042b75 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -260,6 +260,7 @@ struct _GdkWindowObject guint effective_visibility : 2; guint visibility : 2; /* The visibility wrt the toplevel (i.e. based on clip_region) */ guint native_visibility : 2; /* the native visibility of a impl windows */ + guint viewable : 1; /* mapped and all parents mapped */ guint num_offscreen_children; GdkWindowPaint *implicit_paint; @@ -385,6 +386,7 @@ void _gdk_window_destroy (GdkWindow *window, gboolean foreign_destroy); void _gdk_window_clear_update_area (GdkWindow *window); void _gdk_window_update_size (GdkWindow *window); +void _gdk_window_update_viewable (GdkWindow *window); void _gdk_window_process_updates_recurse (GdkWindow *window, GdkRegion *expose_region); diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 4bcbfbc90f..c8778c3199 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -1479,6 +1479,8 @@ gdk_window_reparent (GdkWindow *window, apply_redirect_to_children (private, private->redirect); } + _gdk_window_update_viewable (window); + recompute_visible_regions (private, TRUE, FALSE); if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT) recompute_visible_regions (old_parent, FALSE, TRUE); @@ -2208,25 +2210,13 @@ gboolean gdk_window_is_viewable (GdkWindow *window) { GdkWindowObject *private = (GdkWindowObject *)window; - GdkScreen *screen; - GdkWindow *root_window; g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE); - screen = gdk_drawable_get_screen (window); - root_window = gdk_screen_get_root_window (screen); + if (private->destroyed) + return FALSE; - while (private && - (private != (GdkWindowObject *)root_window) && - (private->window_type != GDK_WINDOW_FOREIGN)) - { - if (GDK_WINDOW_DESTROYED (private) || !GDK_WINDOW_IS_MAPPED (private)) - return FALSE; - - private = (GdkWindowObject *)private->parent; - } - - return TRUE; + return private->viewable; } /** @@ -5774,6 +5764,45 @@ show_all_visible_impls (GdkWindowObject *private, gboolean already_mapped) GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private, already_mapped); } +static void +set_viewable (GdkWindowObject *w, + gboolean val) +{ + GdkWindowObject *child; + GList *l; + + w->viewable = val; + + for (l = w->children; l != NULL; l = l->next) + { + child = l->data; + + if (GDK_WINDOW_IS_MAPPED (child) && + child->window_type != GDK_WINDOW_FOREIGN) + set_viewable (child, val); + } +} + +void +_gdk_window_update_viewable (GdkWindow *window) +{ + GdkWindowObject *priv = (GdkWindowObject *)window; + gboolean viewable; + + if (priv->window_type == GDK_WINDOW_FOREIGN || + priv->window_type == GDK_WINDOW_ROOT) + viewable = TRUE; + else if (priv->parent == NULL || + priv->parent->window_type == GDK_WINDOW_ROOT || + priv->parent->viewable) + viewable = GDK_WINDOW_IS_MAPPED (priv); + else + viewable = FALSE; + + if (priv->viewable != viewable) + set_viewable (priv, viewable); +} + static void gdk_window_show_internal (GdkWindow *window, gboolean raise) { @@ -5804,6 +5833,8 @@ gdk_window_show_internal (GdkWindow *window, gboolean raise) private->state = 0; } + _gdk_window_update_viewable (window); + if (gdk_window_is_viewable (window)) show_all_visible_impls (private, was_mapped); @@ -6106,6 +6137,8 @@ gdk_window_hide (GdkWindow *window) private->state = GDK_WINDOW_STATE_WITHDRAWN; } + _gdk_window_update_viewable (window); + if (was_viewable) hide_all_visible_impls (private); diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c index 283cda18ff..cbc80a7e73 100644 --- a/gdk/quartz/gdkwindow-quartz.c +++ b/gdk/quartz/gdkwindow-quartz.c @@ -969,6 +969,7 @@ _gdk_windowing_window_init (void) private->state = 0; /* We don't want GDK_WINDOW_STATE_WITHDRAWN here */ private->window_type = GDK_WINDOW_ROOT; private->depth = 24; + private->viewable = TRUE; drawable_impl = GDK_DRAWABLE_IMPL_QUARTZ (private->impl); diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c index cf27086685..461f61786f 100644 --- a/gdk/win32/gdkwindow-win32.c +++ b/gdk/win32/gdkwindow-win32.c @@ -283,6 +283,7 @@ _gdk_windowing_window_init (GdkScreen *screen) private->abs_y = 0; private->width = GetSystemMetrics (SM_CXSCREEN); private->height = GetSystemMetrics (SM_CYSCREEN); + private->viewable = TRUE; gdk_win32_handle_table_insert ((HANDLE *) &draw_impl->handle, _gdk_root); @@ -758,6 +759,7 @@ gdk_window_foreign_new_for_display (GdkDisplay *display, else private->state &= (~GDK_WINDOW_STATE_ABOVE); private->state &= (~GDK_WINDOW_STATE_BELOW); + private->viewable = TRUE; private->depth = gdk_visual_get_system ()->depth; diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 9cd453b1ee..b6e19c3a54 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -450,6 +450,7 @@ _gdk_windowing_window_init (GdkScreen * screen) private->abs_y = 0; private->width = WidthOfScreen (screen_x11->xscreen); private->height = HeightOfScreen (screen_x11->xscreen); + private->viewable = TRUE; _gdk_window_update_size (screen_x11->root_window); _gdk_xid_table_insert (screen_x11->display, @@ -936,6 +937,7 @@ gdk_window_foreign_new_for_display (GdkDisplay *display, private->state = GDK_WINDOW_STATE_WITHDRAWN; else private->state = 0; + private->viewable = TRUE; private->depth = attrs.depth; @@ -944,7 +946,7 @@ gdk_window_foreign_new_for_display (GdkDisplay *display, /* Update the clip region, etc */ _gdk_window_update_size (window); - + return window; }