summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2012-02-18 17:29:13 +0100
committerCarlos Garnacho <carlosg@gnome.org>2012-02-18 18:05:00 +0100
commita3283138856d126aafbe9a93f45e0783495b8b8f (patch)
tree44fd5d166e5c88fb784efbeeadcee075f1efd644
parent8528385c80a3daac9f8b3f1a798c23df7db0466d (diff)
downloadgtk+-a3283138856d126aafbe9a93f45e0783495b8b8f.tar.gz
gtk: Release captured events down the hierarchy
Instead of releasing directly onto the target widget, release down the hierarchy as if uncaptured.
-rw-r--r--gtk/gtkmain.c20
-rw-r--r--gtk/gtkprivate.h4
-rw-r--r--gtk/gtkwidget.c40
3 files changed, 50 insertions, 14 deletions
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 39cefd1e88..2264986f58 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -132,10 +132,6 @@
#include "a11y/gailutil.h"
-static gboolean gtk_propagate_captured_event (GtkWidget *widget,
- GdkEvent *event,
- GtkWidget *topmost);
-
/* Private type definitions
*/
typedef struct _GtkKeySnooperData GtkKeySnooperData;
@@ -1667,7 +1663,7 @@ gtk_main_do_event (GdkEvent *event)
_gtk_widget_press_and_hold_check_start (grab_widget, &event->button);
}
- if (!gtk_propagate_captured_event (grab_widget, event, topmost_widget))
+ if (!_gtk_propagate_captured_event (grab_widget, event, topmost_widget))
gtk_propagate_event (grab_widget, event);
break;
@@ -1731,7 +1727,7 @@ gtk_main_do_event (GdkEvent *event)
_gtk_widget_press_and_hold_check_threshold (grab_widget,
&event->motion);
- if (!gtk_propagate_captured_event (grab_widget, event, topmost_widget))
+ if (!_gtk_propagate_captured_event (grab_widget, event, topmost_widget))
gtk_propagate_event (grab_widget, event);
break;
@@ -1742,7 +1738,7 @@ gtk_main_do_event (GdkEvent *event)
gdk_event_get_device (event),
event->any.window);
if (gtk_widget_is_sensitive (grab_widget) &&
- !gtk_propagate_captured_event (grab_widget, event, topmost_widget))
+ !_gtk_propagate_captured_event (grab_widget, event, topmost_widget))
gtk_widget_event (grab_widget, event);
break;
@@ -1753,7 +1749,7 @@ gtk_main_do_event (GdkEvent *event)
gdk_event_get_device (event),
NULL);
if (gtk_widget_is_sensitive (grab_widget) &&
- !gtk_propagate_captured_event (grab_widget, event, topmost_widget))
+ !_gtk_propagate_captured_event (grab_widget, event, topmost_widget))
gtk_widget_event (grab_widget, event);
break;
@@ -2557,10 +2553,10 @@ gtk_propagate_event (GtkWidget *widget,
propagate_event (widget, event, FALSE, NULL);
}
-static gboolean
-gtk_propagate_captured_event (GtkWidget *widget,
- GdkEvent *event,
- GtkWidget *topmost)
+gboolean
+_gtk_propagate_captured_event (GtkWidget *widget,
+ GdkEvent *event,
+ GtkWidget *topmost)
{
return propagate_event (widget, event, TRUE, topmost);
}
diff --git a/gtk/gtkprivate.h b/gtk/gtkprivate.h
index 957176fec2..2ab7ad4e6b 100644
--- a/gtk/gtkprivate.h
+++ b/gtk/gtkprivate.h
@@ -78,6 +78,10 @@ gboolean _gtk_translate_keyboard_accel_state (GdkKeymap *keymap,
gint *level,
GdkModifierType *consumed_modifiers);
+gboolean _gtk_propagate_captured_event (GtkWidget *widget,
+ GdkEvent *event,
+ GtkWidget *topmost);
+
G_END_DECLS
#endif /* __GTK_PRIVATE_H__ */
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 7b10a06613..c557d532d0 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -14574,8 +14574,9 @@ _gtk_widget_set_style (GtkWidget *widget,
*
* Releases the events that a widget has captured and stored
* in the #GtkWidget::captured-event signal. if @emit is #TRUE,
- * the events will be emitted on the target widget (the widget
- * that would receive the event if no signal capturing happened)
+ * event emission will continue as if uncaptured (i.e. the
+ * capturing phase will continue down the hierarchy to the event
+ * widget, followed by the event being propagated up again).
*
* Since: 3.4
**/
@@ -14598,9 +14599,44 @@ gtk_widget_release_captured_events (GtkWidget *widget,
{
GtkWidget *event_widget;
GdkEvent *event = l->data;
+ gboolean propagated = FALSE;
event_widget = gtk_get_event_widget (event);
+ /* Find out the next widget handling the captured event,
+ * if event_widget == widget, the capturing phase for
+ * this event has finished, so the next thing is bubbling
+ * it up.
+ */
+ if (event_widget != widget &&
+ gtk_widget_is_ancestor (event_widget, widget))
+ {
+ GtkWidget *parent, *intermediate;
+
+ intermediate = event_widget;
+
+ while (intermediate)
+ {
+ parent = gtk_widget_get_parent (intermediate);
+
+ /* Found the next intermediate that should handle
+ * the captured event.
+ */
+ if (parent == widget)
+ break;
+
+ intermediate = parent;
+ }
+
+ if (intermediate)
+ propagated = _gtk_propagate_captured_event (event_widget,
+ event,
+ intermediate);
+ }
+
+ if (propagated)
+ continue;
+
switch (event->type)
{
case GDK_PROPERTY_NOTIFY: