Rework the code which emits ::grab-notify signals to ensure that we emit

2006-04-05  Matthias Clasen  <mclasen@redhat.com>

	* 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.
This commit is contained in:
Matthias Clasen 2006-04-06 01:58:38 +00:00 committed by Matthias Clasen
parent f58c7f1ae8
commit 12704a67bc
4 changed files with 113 additions and 39 deletions

View File

@ -1,3 +1,12 @@
2006-04-05 Matthias Clasen <mclasen@redhat.com>
* 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 <pborelli@katamail.com>
* gtk/gtktextiter.c (gtk_text_iter_ends_line): handle the case of \r

View File

@ -1,3 +1,12 @@
2006-04-05 Matthias Clasen <mclasen@redhat.com>
* 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 <pborelli@katamail.com>
* gtk/gtktextiter.c (gtk_text_iter_ends_line): handle the case of \r

View File

@ -1395,6 +1395,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;
@ -1496,61 +1497,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 (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);
@ -1560,19 +1557,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;
GtkWidget *old_grab_widget;
g_return_if_fail (widget != NULL);
@ -1582,10 +1583,15 @@ gtk_grab_add (GtkWidget *widget)
group = gtk_main_get_window_group (widget);
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, widget);
}
}
@ -1605,6 +1611,7 @@ void
gtk_grab_remove (GtkWidget *widget)
{
GtkWindowGroup *group;
GtkWidget *new_grab_widget;
g_return_if_fail (widget != NULL);
@ -1615,9 +1622,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);
}
}

View File

@ -121,6 +121,7 @@ enum {
SCREEN_CHANGED,
CAN_ACTIVATE_ACCEL,
GRAB_BROKEN,
DAMAGE_EVENT,
LAST_SIGNAL
};
@ -402,6 +403,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;
@ -664,6 +666,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 (I_("grab_notify"),
G_TYPE_FROM_CLASS (gobject_class),
@ -1362,6 +1380,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
@ -3773,6 +3814,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;