gtk: emit ::captured-event starting from the GTK grab widget
This commit is contained in:
@@ -133,7 +133,8 @@
|
||||
#include "a11y/gailutil.h"
|
||||
|
||||
static gboolean gtk_propagate_captured_event (GtkWidget *widget,
|
||||
GdkEvent *event);
|
||||
GdkEvent *event,
|
||||
GtkWidget *topmost);
|
||||
|
||||
/* Private type definitions
|
||||
*/
|
||||
@@ -1476,6 +1477,7 @@ gtk_main_do_event (GdkEvent *event)
|
||||
{
|
||||
GtkWidget *event_widget;
|
||||
GtkWidget *grab_widget = NULL;
|
||||
GtkWidget *topmost_widget = NULL;
|
||||
GtkWindowGroup *window_group;
|
||||
GdkEvent *rewritten_event = NULL;
|
||||
GdkDevice *device;
|
||||
@@ -1535,6 +1537,14 @@ gtk_main_do_event (GdkEvent *event)
|
||||
if (!grab_widget)
|
||||
grab_widget = gtk_window_group_get_current_grab (window_group);
|
||||
|
||||
/* Find out the topmost widget where captured event propagation
|
||||
* should start, which is the widget holding the GTK+ grab
|
||||
* if any, otherwise it's left NULL and events are emitted
|
||||
* from the toplevel (or topmost parentless parent).
|
||||
*/
|
||||
if (grab_widget)
|
||||
topmost_widget = grab_widget;
|
||||
|
||||
/* If the grab widget is an ancestor of the event widget
|
||||
* then we send the event to the original event widget.
|
||||
* This is the key to implementing modality.
|
||||
@@ -1639,7 +1649,7 @@ gtk_main_do_event (GdkEvent *event)
|
||||
case GDK_BUTTON_PRESS:
|
||||
case GDK_2BUTTON_PRESS:
|
||||
case GDK_3BUTTON_PRESS:
|
||||
if (!gtk_propagate_captured_event (grab_widget, event))
|
||||
if (!gtk_propagate_captured_event (grab_widget, event, topmost_widget))
|
||||
gtk_propagate_event (grab_widget, event);
|
||||
break;
|
||||
|
||||
@@ -1689,7 +1699,7 @@ gtk_main_do_event (GdkEvent *event)
|
||||
case GDK_BUTTON_RELEASE:
|
||||
case GDK_PROXIMITY_IN:
|
||||
case GDK_PROXIMITY_OUT:
|
||||
if (!gtk_propagate_captured_event (grab_widget, event))
|
||||
if (!gtk_propagate_captured_event (grab_widget, event, topmost_widget))
|
||||
gtk_propagate_event (grab_widget, event);
|
||||
break;
|
||||
|
||||
@@ -2339,7 +2349,8 @@ gtk_get_event_widget (GdkEvent *event)
|
||||
|
||||
static gboolean
|
||||
propagate_event_up (GtkWidget *widget,
|
||||
GdkEvent *event)
|
||||
GdkEvent *event,
|
||||
GtkWidget *topmost)
|
||||
{
|
||||
gboolean handled_event = FALSE;
|
||||
|
||||
@@ -2366,6 +2377,9 @@ propagate_event_up (GtkWidget *widget,
|
||||
tmp = gtk_widget_get_parent (widget);
|
||||
g_object_unref (widget);
|
||||
|
||||
if (widget == topmost)
|
||||
break;
|
||||
|
||||
widget = tmp;
|
||||
|
||||
if (handled_event || !widget)
|
||||
@@ -2377,20 +2391,24 @@ propagate_event_up (GtkWidget *widget,
|
||||
|
||||
static gboolean
|
||||
propagate_event_down (GtkWidget *widget,
|
||||
GdkEvent *event)
|
||||
GdkEvent *event,
|
||||
GtkWidget *topmost)
|
||||
{
|
||||
gint handled_event = FALSE;
|
||||
GList *widgets = NULL;
|
||||
GList *l;
|
||||
|
||||
widgets = g_list_prepend (widgets, g_object_ref (widget));
|
||||
while (TRUE)
|
||||
while (widget && widget != topmost)
|
||||
{
|
||||
widget = gtk_widget_get_parent (widget);
|
||||
if (!widget)
|
||||
break;
|
||||
|
||||
widgets = g_list_prepend (widgets, g_object_ref (widget));
|
||||
|
||||
if (widget == topmost)
|
||||
break;
|
||||
}
|
||||
|
||||
for (l = widgets; l && !handled_event; l = g_list_next (l))
|
||||
@@ -2410,7 +2428,8 @@ propagate_event_down (GtkWidget *widget,
|
||||
static gboolean
|
||||
propagate_event (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
gboolean captured)
|
||||
gboolean captured,
|
||||
GtkWidget *topmost)
|
||||
{
|
||||
gboolean handled_event = FALSE;
|
||||
gboolean (* propagate_func) (GtkWidget *widget, GdkEvent *event);
|
||||
@@ -2452,7 +2471,9 @@ propagate_event (GtkWidget *widget,
|
||||
}
|
||||
|
||||
/* Other events get propagated up/down the widget tree */
|
||||
return captured ? propagate_event_down (widget, event) : propagate_event_up (widget, event);
|
||||
return captured ?
|
||||
propagate_event_down (widget, event, topmost) :
|
||||
propagate_event_up (widget, event, topmost);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2486,12 +2507,13 @@ gtk_propagate_event (GtkWidget *widget,
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (event != NULL);
|
||||
|
||||
propagate_event (widget, event, FALSE);
|
||||
propagate_event (widget, event, FALSE, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_propagate_captured_event (GtkWidget *widget,
|
||||
GdkEvent *event)
|
||||
GdkEvent *event,
|
||||
GtkWidget *topmost)
|
||||
{
|
||||
return propagate_event (widget, event, TRUE);
|
||||
return propagate_event (widget, event, TRUE, topmost);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user