diff options
author | Alexander Larsson <alexl@redhat.com> | 2009-05-26 20:53:48 +0200 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2009-05-26 20:53:48 +0200 |
commit | 8cb385cd3105acd096d2ce6f1f88156f07dbb7fe (patch) | |
tree | 60726c50fc6528a146331e35c55bf5a371fb8eb1 | |
parent | 6c76f8f6cef2c026985995a5e7444b3a8a5840bb (diff) | |
download | gdk-pixbuf-8cb385cd3105acd096d2ce6f1f88156f07dbb7fe.tar.gz |
Add support for visibility notification
-rw-r--r-- | gdk/gdkinternals.h | 3 | ||||
-rw-r--r-- | gdk/gdkwindow.c | 128 |
2 files changed, 124 insertions, 7 deletions
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index a37f9e893..9191cf9b1 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -255,6 +255,9 @@ struct _GdkWindowObject GdkRegion *clip_region_with_children; /* Clip region in window coords */ GdkCursor *cursor; gint8 toplevel_window_type; + 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 */ GdkWindowPaint *implicit_paint; diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index d20cb44c4..1f2388b60 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -63,6 +63,9 @@ #define USE_BACKING_STORE /* Appears to work on Win32, too, now. */ +/* This adds a local value to the GdkVisibilityState enum */ +#define GDK_VISIBILITY_NOT_VIEWABLE 3 + struct _GdkWindowPaint { GdkRegion *region; @@ -311,6 +314,11 @@ gdk_window_init (GdkWindowObject *window) window->width = 1; window->height = 1; window->toplevel_window_type = -1; + /* starts hidden */ + window->effective_visibility = GDK_VISIBILITY_NOT_VIEWABLE; + window->visibility = GDK_VISIBILITY_FULLY_OBSCURED; + /* Default to unobscured since some backends don't send visibility events */ + window->native_visibility = GDK_VISIBILITY_UNOBSCURED; } static GQuark quark_pointer_window = 0; @@ -505,6 +513,64 @@ remove_child_area (GdkWindowObject *private, } } +static GdkVisibilityState +effective_visibility (GdkWindowObject *private) +{ + GdkVisibilityState native; + + if (!gdk_window_is_viewable ((GdkWindow *)private)) + return GDK_VISIBILITY_NOT_VIEWABLE; + + native = private->impl_window->native_visibility; + + if (native == GDK_VISIBILITY_FULLY_OBSCURED || + private->visibility == GDK_VISIBILITY_FULLY_OBSCURED) + return GDK_VISIBILITY_FULLY_OBSCURED; + else if (native == GDK_VISIBILITY_UNOBSCURED) + return private->visibility; + else /* native PARTIAL, private partial or unobscured */ + return GDK_VISIBILITY_PARTIAL; +} + +static void +gdk_window_update_visibility (GdkWindowObject *private) +{ + GdkVisibilityState new_visibility; + GdkEvent *event; + + new_visibility = effective_visibility (private); + + if (new_visibility != private->effective_visibility) + { + private->effective_visibility = new_visibility; + + if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE && + private->event_mask & GDK_VISIBILITY_NOTIFY) + { + event = _gdk_make_event ((GdkWindow *)private, GDK_VISIBILITY_NOTIFY, + NULL, FALSE); + event->visibility.state = new_visibility; + } + } +} + +static void +gdk_window_update_visibility_recursively (GdkWindowObject *private, + GdkWindowObject *only_for_impl) +{ + GdkWindowObject *child; + GList *l; + + gdk_window_update_visibility (private); + for (l = private->children; l != NULL; l = l->next) + { + child = l->data; + if ((only_for_impl == NULL) || + (only_for_impl == child->impl_window)) + gdk_window_update_visibility_recursively (child, only_for_impl); + } +} + static void recompute_visible_regions_internal (GdkWindowObject *private, gboolean recalculate_clip, @@ -521,7 +587,7 @@ recompute_visible_regions_internal (GdkWindowObject *private, old_abs_x = private->abs_x; old_abs_y = private->abs_y; - + /* Update absolute position */ if (gdk_window_has_impl (private)) { @@ -588,6 +654,39 @@ recompute_visible_regions_internal (GdkWindowObject *private, gdk_region_destroy (old_clip_region_with_children); } + if (clip_region_changed) + { + GdkVisibilityState visibility; + gboolean fully_visible; + + if (gdk_region_empty (private->clip_region)) + visibility = GDK_VISIBILITY_FULLY_OBSCURED; + else { + if (private->shape) + fully_visible = gdk_region_equal (private->clip_region, + private->shape); + else + { + r.x = 0; + r.y = 0; + r.width = private->width; + r.height = private->height; + fully_visible = gdk_region_rect_equal (private->clip_region, &r); + } + + if (fully_visible) + visibility = GDK_VISIBILITY_UNOBSCURED; + else + visibility = GDK_VISIBILITY_PARTIAL; + } + + if (private->visibility != visibility) + { + private->visibility = visibility; + gdk_window_update_visibility (private); + } + } + /* Update all children, recursively. */ if (abs_pos_changed || clip_region_changed || recalculate_children) { @@ -750,6 +849,7 @@ get_native_event_mask (GdkWindowObject *private) /* We need thse for all native window so we can emulate events on children: */ GDK_EXPOSURE_MASK | + GDK_VISIBILITY_NOTIFY_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | @@ -5653,11 +5753,14 @@ gdk_window_show_internal (GdkWindow *window, gboolean raise) if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK) _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE); } - + if (!was_mapped || raise) { recompute_visible_regions (private, TRUE, FALSE); - + + /* If any decendants became visible we need to send visibility notify */ + gdk_window_update_visibility_recursively (private, NULL); + if (gdk_window_is_viewable (window)) { _gdk_syntesize_crossing_events_for_geometry_change (window); @@ -5665,7 +5768,7 @@ gdk_window_show_internal (GdkWindow *window, gboolean raise) } } } - + /** * gdk_window_show_unraised: * @window: a #GdkWindow @@ -5935,9 +6038,12 @@ gdk_window_hide (GdkWindow *window) if (was_viewable) hide_all_visible_impls (private); - + recompute_visible_regions (private, TRUE, FALSE); - + + /* all decendants became non-visible, we need to send visibility notify */ + gdk_window_update_visibility_recursively (private, NULL); + if (was_mapped) { if (private->event_mask & GDK_STRUCTURE_MASK) @@ -8787,7 +8893,15 @@ _gdk_windowing_got_event (GdkDisplay *display, event->key.keyval == 0xbd); } #endif - + + if (event->type == GDK_VISIBILITY_NOTIFY) + { + event_private->native_visibility = event->visibility.state; + gdk_window_update_visibility_recursively (event_private, + event_private); + return; + } + if (!(is_button_type (event->type) || is_motion_type (event->type)) || GDK_WINDOW_TYPE (event_private) == GDK_WINDOW_ROOT) |