diff --git a/ChangeLog b/ChangeLog index 37374feb11..9b52432dd9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2006-04-05 Matthias Clasen + + * gtk/gtkmain.c (gtk_grab_add, gtk_grab_remove, gtk_grab_notify) + (gtk_grab_notify_foreach): Rework the code which emits ::grab-notify + signals to ensure that we emit enough signals. Also optimize the + code to not do unnecessary tree walking. + + * gtk/gtkwidget.c (gtk_widget_class_init): Document ::grab-notify. + 2006-04-05 Paolo Borelli * gtk/gtktextiter.c (gtk_text_iter_ends_line): handle the case of \r diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 37374feb11..9b52432dd9 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,12 @@ +2006-04-05 Matthias Clasen + + * gtk/gtkmain.c (gtk_grab_add, gtk_grab_remove, gtk_grab_notify) + (gtk_grab_notify_foreach): Rework the code which emits ::grab-notify + signals to ensure that we emit enough signals. Also optimize the + code to not do unnecessary tree walking. + + * gtk/gtkwidget.c (gtk_widget_class_init): Document ::grab-notify. + 2006-04-05 Paolo Borelli * gtk/gtktextiter.c (gtk_text_iter_ends_line): handle the case of \r diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index b5bb6f2c90..9ae4b78230 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1399,6 +1399,7 @@ gtk_main_do_event (GdkEvent *event) case GDK_VISIBILITY_NOTIFY: case GDK_WINDOW_STATE: case GDK_GRAB_BROKEN: + case GDK_DAMAGE: gtk_widget_event (event_widget, event); break; @@ -1500,61 +1501,57 @@ typedef struct { GtkWidget *old_grab_widget; GtkWidget *new_grab_widget; + gboolean was_grabbed; + gboolean is_grabbed; } GrabNotifyInfo; -static gboolean -check_is_grabbed (GtkWidget *widget, - GtkWidget *grab_widget) -{ - if (grab_widget) - return !(widget == grab_widget || gtk_widget_is_ancestor (widget, grab_widget)); - else - return FALSE; -} - static void gtk_grab_notify_foreach (GtkWidget *child, gpointer data) { GrabNotifyInfo *info = data; - gboolean was_grabbed = check_is_grabbed (child, info->old_grab_widget); - gboolean is_grabbed = check_is_grabbed (child, info->new_grab_widget); + + gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed; - if (was_grabbed != is_grabbed) - { - g_object_ref (child); + was_grabbed = info->was_grabbed; + is_grabbed = info->is_grabbed; - _gtk_widget_grab_notify (child, was_grabbed); + info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget); + info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget); + + was_shadowed = info->old_grab_widget && !info->was_grabbed; + is_shadowed = info->new_grab_widget && !info->is_grabbed; + + g_object_ref (child); + + if (was_shadowed != is_shadowed) + _gtk_widget_grab_notify (child, was_shadowed); + + if ((was_shadowed || is_shadowed) && GTK_IS_CONTAINER (child)) + gtk_container_foreach (GTK_CONTAINER (child), gtk_grab_notify_foreach, info); - if (GTK_IS_CONTAINER (child)) - gtk_container_foreach (GTK_CONTAINER (child), gtk_grab_notify_foreach, info); - - g_object_unref (child); - } + g_object_unref (child); + + info->was_grabbed = was_grabbed; + info->is_grabbed = is_grabbed; } static void gtk_grab_notify (GtkWindowGroup *group, - GtkWidget *grab_widget, - gboolean was_grabbed) + GtkWidget *old_grab_widget, + GtkWidget *new_grab_widget) { GList *toplevels; GrabNotifyInfo info; - if (was_grabbed) - { - info.old_grab_widget = grab_widget; - info.new_grab_widget = group->grabs ? group->grabs->data : NULL; - } - else - { - info.old_grab_widget = (group->grabs && group->grabs->next) ? group->grabs->next->data : NULL; - info.new_grab_widget = grab_widget; - } + if (old_grab_widget == new_grab_widget) + return; + + info.old_grab_widget = old_grab_widget; + info.new_grab_widget = new_grab_widget; g_object_ref (group); - g_object_ref (grab_widget); toplevels = gtk_window_list_toplevels (); g_list_foreach (toplevels, (GFunc)g_object_ref, NULL); @@ -1564,20 +1561,23 @@ gtk_grab_notify (GtkWindowGroup *group, GtkWindow *toplevel = toplevels->data; toplevels = g_list_delete_link (toplevels, toplevels); + info.was_grabbed = FALSE; + info.is_grabbed = FALSE; + if (group == _gtk_window_get_group (toplevel)) - gtk_container_foreach (GTK_CONTAINER (toplevel), gtk_grab_notify_foreach, &info); + gtk_container_foreach (GTK_CONTAINER (toplevel), + gtk_grab_notify_foreach, &info); g_object_unref (toplevel); } g_object_unref (group); - g_object_unref (grab_widget); } void gtk_grab_add (GtkWidget *widget) { GtkWindowGroup *group; - gboolean was_grabbed; + GtkWidget *old_grab_widget; g_return_if_fail (widget != NULL); @@ -1587,12 +1587,15 @@ gtk_grab_add (GtkWidget *widget) group = gtk_main_get_window_group (widget); - was_grabbed = (group->grabs != NULL); + if (group->grabs) + old_grab_widget = (GtkWidget *)group->grabs->data; + else + old_grab_widget = NULL; g_object_ref (widget); group->grabs = g_slist_prepend (group->grabs, widget); - gtk_grab_notify (group, widget, FALSE); + gtk_grab_notify (group, old_grab_widget); } } @@ -1612,6 +1615,7 @@ void gtk_grab_remove (GtkWidget *widget) { GtkWindowGroup *group; + GtkWidget *new_grab_widget; g_return_if_fail (widget != NULL); @@ -1622,9 +1626,14 @@ gtk_grab_remove (GtkWidget *widget) group = gtk_main_get_window_group (widget); group->grabs = g_slist_remove (group->grabs, widget); - g_object_unref (widget); + if (group->grabs) + new_grab_widget = (GtkWidget *)group->grabs->data; + else + new_grab_widget = NULL; - gtk_grab_notify (group, widget, TRUE); + gtk_grab_notify (group, widget, new_grab_widget); + + g_object_unref (widget); } } diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 6979e690b3..8d882a6005 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -121,6 +121,7 @@ enum { SCREEN_CHANGED, CAN_ACTIVATE_ACCEL, GRAB_BROKEN, + DAMAGE_EVENT, LAST_SIGNAL }; @@ -401,6 +402,7 @@ gtk_widget_class_init (GtkWidgetClass *klass) klass->screen_changed = NULL; klass->can_activate_accel = gtk_widget_real_can_activate_accel; klass->grab_broken_event = NULL; + klass->damage_event = NULL; klass->show_help = gtk_widget_real_show_help; @@ -663,6 +665,22 @@ gtk_widget_class_init (GtkWidgetClass *klass) _gtk_marshal_VOID__ENUM, G_TYPE_NONE, 1, GTK_TYPE_TEXT_DIRECTION); + + /** + * GtkWidget::grab-notify: + * @widget: the object which received the signal + * @was_grabbed: %FALSE if the widget becomes shadowed, %TRUE + * if it becomes unshadowed + * + * The ::grab-notify signal is emitted when a widget becomes + * shadowed by a GTK+ grab (not a pointer or keyboard grab) on + * another widget, or when it becomes unshadowed due to a grab + * being removed. + * + * A widget is shadowed by a gtk_grab_add() when the topmost + * grab widget in the grab stack of its window group is not + * its ancestor. + */ widget_signals[GRAB_NOTIFY] = g_signal_new ("grab_notify", G_TYPE_FROM_CLASS (gobject_class), @@ -1353,6 +1371,29 @@ gtk_widget_class_init (GtkWidgetClass *klass) _gtk_marshal_BOOLEAN__BOXED, G_TYPE_BOOLEAN, 1, GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + /** + * GtkWidget::damage-event: + * @widget: the object which received the signal + * @event: the #GdkEventExpose event + * + * Emitted when a redirected window belonging to @widget gets drawn into. + * The region/area members of the event shows what area of the redirected + * drawable was drawn into. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + * + * Since: 2.10 + */ + widget_signals[DAMAGE_EVENT] = + g_signal_new ("damage_event", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkWidgetClass, damage_event), + _gtk_boolean_handled_accumulator, NULL, + _gtk_marshal_BOOLEAN__BOXED, + G_TYPE_BOOLEAN, 1, + GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); /** * GtkWidget::popup-menu * @widget: the object which received the signal @@ -3723,6 +3764,9 @@ gtk_widget_event_internal (GtkWidget *widget, case GDK_GRAB_BROKEN: signal_num = GRAB_BROKEN; break; + case GDK_DAMAGE: + signal_num = DAMAGE_EVENT; + break; default: g_warning ("gtk_widget_event(): unhandled event type: %d", event->type); signal_num = -1;