diff --git a/ChangeLog b/ChangeLog index 44c9f17a5a..3081eef7cd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +Fri Jun 6 11:07:33 2003 Owen Taylor + + * gtk/gtkwidget.c (event_window_still_viewable): + Before delivering an event to a widget, check that + (if relevant), the event's window is still viewable. + (#105642, Dennis Björklund) + + * gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): + NULL out private->parent, since after destruction + it might not be valid any more. + + * gdk/gdkwindow.c (gdk_window_is_viewable): Fix some + accesses before g_return_val_if_fail(). Treat + DESTROYED windows as unmapped. + Thu Jun 5 09:28:03 2003 Owen Taylor * gtk/gtkentry.c: Recompute unconditionally in diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 44c9f17a5a..3081eef7cd 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,18 @@ +Fri Jun 6 11:07:33 2003 Owen Taylor + + * gtk/gtkwidget.c (event_window_still_viewable): + Before delivering an event to a widget, check that + (if relevant), the event's window is still viewable. + (#105642, Dennis Björklund) + + * gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): + NULL out private->parent, since after destruction + it might not be valid any more. + + * gdk/gdkwindow.c (gdk_window_is_viewable): Fix some + accesses before g_return_val_if_fail(). Treat + DESTROYED windows as unmapped. + Thu Jun 5 09:28:03 2003 Owen Taylor * gtk/gtkentry.c: Recompute unconditionally in diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 44c9f17a5a..3081eef7cd 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,18 @@ +Fri Jun 6 11:07:33 2003 Owen Taylor + + * gtk/gtkwidget.c (event_window_still_viewable): + Before delivering an event to a widget, check that + (if relevant), the event's window is still viewable. + (#105642, Dennis Björklund) + + * gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): + NULL out private->parent, since after destruction + it might not be valid any more. + + * gdk/gdkwindow.c (gdk_window_is_viewable): Fix some + accesses before g_return_val_if_fail(). Treat + DESTROYED windows as unmapped. + Thu Jun 5 09:28:03 2003 Owen Taylor * gtk/gtkentry.c: Recompute unconditionally in diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 44c9f17a5a..3081eef7cd 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,18 @@ +Fri Jun 6 11:07:33 2003 Owen Taylor + + * gtk/gtkwidget.c (event_window_still_viewable): + Before delivering an event to a widget, check that + (if relevant), the event's window is still viewable. + (#105642, Dennis Björklund) + + * gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): + NULL out private->parent, since after destruction + it might not be valid any more. + + * gdk/gdkwindow.c (gdk_window_is_viewable): Fix some + accesses before g_return_val_if_fail(). Treat + DESTROYED windows as unmapped. + Thu Jun 5 09:28:03 2003 Owen Taylor * gtk/gtkentry.c: Recompute unconditionally in diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 44c9f17a5a..3081eef7cd 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,18 @@ +Fri Jun 6 11:07:33 2003 Owen Taylor + + * gtk/gtkwidget.c (event_window_still_viewable): + Before delivering an event to a widget, check that + (if relevant), the event's window is still viewable. + (#105642, Dennis Björklund) + + * gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): + NULL out private->parent, since after destruction + it might not be valid any more. + + * gdk/gdkwindow.c (gdk_window_is_viewable): Fix some + accesses before g_return_val_if_fail(). Treat + DESTROYED windows as unmapped. + Thu Jun 5 09:28:03 2003 Owen Taylor * gtk/gtkentry.c: Recompute unconditionally in diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 2534ad86d9..21310ceb2b 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -354,6 +354,7 @@ _gdk_window_destroy_hierarchy (GdkWindow *window, } _gdk_windowing_window_destroy (window, recursing, foreign_destroy); + private->parent = NULL; private->destroyed = TRUE; if (private->filters) @@ -780,17 +781,20 @@ gboolean gdk_window_is_viewable (GdkWindow *window) { GdkWindowObject *private = (GdkWindowObject *)window; - GdkScreen *screen = gdk_drawable_get_screen (window); - GdkWindow *root_window = gdk_screen_get_root_window (screen); + GdkScreen *screen; + GdkWindow *root_window; g_return_val_if_fail (window != NULL, FALSE); g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE); + + screen = gdk_drawable_get_screen (window); + root_window = gdk_screen_get_root_window (screen); while (private && (private != (GdkWindowObject *)root_window) && (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN)) { - if (!GDK_WINDOW_IS_MAPPED (window)) + if (GDK_WINDOW_DESTROYED (window) || !GDK_WINDOW_IS_MAPPED (window)) return FALSE; private = (GdkWindowObject *)private->parent; diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 9c6e4ced61..6eb4ab6b8d 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -3040,12 +3040,60 @@ gtk_widget_send_expose (GtkWidget *widget, return gtk_widget_event_internal (widget, event); } +static gboolean +event_window_is_still_viewable (GdkEvent *event) +{ + /* Check that we think the event's window is viewable before + * delivering the event, to prevent suprises. We do this here + * at the last moment, since the event may have been queued + * up behind other events, held over a recursive main loop, etc. + */ + switch (event->type) + { + case GDK_EXPOSE: + case GDK_MOTION_NOTIFY: + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + case GDK_KEY_PRESS: + case GDK_ENTER_NOTIFY: + case GDK_PROXIMITY_IN: + case GDK_SCROLL: + return event->any.window && gdk_window_is_viewable (event->any.window); + +#if 0 + /* The following events are the second half of paired events; + * we always deliver them to deal with widgets that clean up + * on the second half. + */ + case GDK_BUTTON_RELEASE: + case GDK_KEY_RELEASE: + case GDK_LEAVE_NOTIFY: + case GDK_PROXIMITY_OUT: +#endif + + default: + /* Remaining events would make sense on an not-viewable window, + * or don't have an associated window. + */ + return TRUE; + } +} + static gint gtk_widget_event_internal (GtkWidget *widget, GdkEvent *event) { gboolean return_val = FALSE; + /* We check only once for is-still-visible; if someone + * hides the window in on of the signals on the widget, + * they are responsible for returning TRUE to terminate + * handling. + */ + if (!event_window_is_still_viewable (event)) + return TRUE; + g_object_ref (widget); g_signal_emit (widget, widget_signals[EVENT], 0, event, &return_val);