eventcontroller: Clarify filter_event()

The original intention with this function was to mark events that would
be filtered out - meaning one returns TRUE to skip and even and FALSE to
handle it. While this is docuemnted, it's not particularly clear and a few
controllers use it incorrectly. For example, GtkGesture intends to block
touchpad gesture events by default, yet in reality it allows them instead,
and otherwise chains up to GtkEventController that already enables
everything.

Instead, change it to work the way newer code uses it - skip everything by
default and have controllers explicitly allow events they need, and change
the return type from a boolean to a new enum with values HANDLE and SKIP.
This commit is contained in:
Alexander Mikhaylenko
2021-09-16 20:10:56 +05:00
parent 7ac3e5ac53
commit f1950cc84d
17 changed files with 138 additions and 69 deletions

View File

@@ -243,7 +243,7 @@ gtk_drag_source_get_property (GObject *object,
}
}
static gboolean
static GtkFilterEventStatus
gtk_drag_source_filter_event (GtkEventController *controller,
GdkEvent *event)
{
@@ -257,9 +257,9 @@ gtk_drag_source_filter_event (GtkEventController *controller,
n_fingers = gdk_touchpad_event_get_n_fingers (event);
if (n_fingers == n_points)
return FALSE;
return GTK_EVENT_HANDLE;
else
return TRUE;
return GTK_EVENT_SKIP;
}
return GTK_EVENT_CONTROLLER_CLASS (gtk_drag_source_parent_class)->filter_event (controller, event);

View File

@@ -77,22 +77,27 @@ static guint signals[N_SIGNALS] = { 0 };
G_DEFINE_TYPE (GtkDropControllerMotion, gtk_drop_controller_motion, GTK_TYPE_EVENT_CONTROLLER)
static GtkFilterEventStatus
gtk_drop_controller_motion_filter_event (GtkEventController *controller,
GdkEvent *event)
{
GdkEventType event_type = gdk_event_get_event_type (event);
if (event_type == GDK_DRAG_MOTION)
return GTK_EVENT_HANDLE;
return GTK_EVENT_SKIP;
}
static gboolean
gtk_drop_controller_motion_handle_event (GtkEventController *controller,
GdkEvent *event,
double x,
double y)
{
GtkEventControllerClass *parent_class;
GdkEventType type;
g_signal_emit (controller, signals[MOTION], 0, x, y);
type = gdk_event_get_event_type (event);
if (type == GDK_DRAG_MOTION)
g_signal_emit (controller, signals[MOTION], 0, x, y);
parent_class = GTK_EVENT_CONTROLLER_CLASS (gtk_drop_controller_motion_parent_class);
return parent_class->handle_event (controller, event, x, y);
return GDK_EVENT_PROPAGATE;
}
static void
@@ -204,6 +209,7 @@ gtk_drop_controller_motion_class_init (GtkDropControllerMotionClass *klass)
object_class->get_property = gtk_drop_controller_motion_get_property;
controller_class->filter_event = gtk_drop_controller_motion_filter_event;
controller_class->handle_event = gtk_drop_controller_motion_handle_event;
controller_class->handle_crossing = gtk_drop_controller_motion_handle_crossing;

View File

@@ -388,7 +388,7 @@ gtk_drop_target_drop (GtkDropTarget *self,
return FALSE;
}
static gboolean
static GtkFilterEventStatus
gtk_drop_target_filter_event (GtkEventController *controller,
GdkEvent *event)
{
@@ -398,12 +398,12 @@ gtk_drop_target_filter_event (GtkEventController *controller,
case GDK_DRAG_LEAVE:
case GDK_DRAG_MOTION:
case GDK_DROP_START:
return GTK_EVENT_CONTROLLER_CLASS (gtk_drop_target_parent_class)->filter_event (controller, event);
return GTK_EVENT_HANDLE;
default:;
}
return TRUE;
return GTK_EVENT_SKIP;
}
static gboolean

View File

@@ -183,7 +183,7 @@ gtk_drop_target_async_drop (GtkDropTargetAsync *self,
return FALSE;
}
static gboolean
static GtkFilterEventStatus
gtk_drop_target_async_filter_event (GtkEventController *controller,
GdkEvent *event)
{
@@ -193,12 +193,12 @@ gtk_drop_target_async_filter_event (GtkEventController *controller,
case GDK_DRAG_LEAVE:
case GDK_DRAG_MOTION:
case GDK_DROP_START:
return GTK_EVENT_CONTROLLER_CLASS (gtk_drop_target_async_parent_class)->filter_event (controller, event);
return GTK_EVENT_HANDLE;
default:;
}
return TRUE;
return GTK_EVENT_SKIP;
}
static gboolean

View File

@@ -87,11 +87,11 @@ gtk_event_controller_unset_widget (GtkEventController *self)
priv->widget = NULL;
}
static gboolean
static GtkFilterEventStatus
gtk_event_controller_filter_event_default (GtkEventController *self,
GdkEvent *event)
{
return FALSE;
return GTK_EVENT_SKIP;
}
static gboolean
@@ -273,7 +273,7 @@ same_native (GtkWidget *widget,
return native == native2;
}
static gboolean
static GtkFilterEventStatus
gtk_event_controller_filter_event (GtkEventController *controller,
GdkEvent *event,
GtkWidget *target)
@@ -284,11 +284,11 @@ gtk_event_controller_filter_event (GtkEventController *controller,
priv = gtk_event_controller_get_instance_private (controller);
if (priv->widget && !gtk_widget_is_sensitive (priv->widget))
return TRUE;
return GTK_EVENT_SKIP;
if (priv->limit == GTK_LIMIT_SAME_NATIVE &&
!same_native (priv->widget, target))
return TRUE;
return GTK_EVENT_SKIP;
controller_class = GTK_EVENT_CONTROLLER_GET_CLASS (controller);
@@ -357,7 +357,7 @@ gtk_event_controller_handle_event (GtkEventController *controller,
g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER (controller), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
if (gtk_event_controller_filter_event (controller, event, target))
if (gtk_event_controller_filter_event (controller, event, target) == GTK_EVENT_SKIP)
return retval;
controller_class = GTK_EVENT_CONTROLLER_GET_CLASS (controller);

View File

@@ -80,6 +80,18 @@ gtk_event_controller_key_finalize (GObject *object)
G_OBJECT_CLASS (gtk_event_controller_key_parent_class)->finalize (object);
}
static GtkFilterEventStatus
gtk_event_controller_key_filter_event (GtkEventController *controller,
GdkEvent *event)
{
GdkEventType event_type = gdk_event_get_event_type (event);
if (event_type == GDK_KEY_PRESS || event_type == GDK_KEY_RELEASE)
return GTK_EVENT_HANDLE;
return GTK_EVENT_SKIP;
}
static gboolean
gtk_event_controller_key_handle_event (GtkEventController *controller,
GdkEvent *event,
@@ -93,9 +105,6 @@ gtk_event_controller_key_handle_event (GtkEventController *controller,
guint keyval;
gboolean handled = FALSE;
if (event_type != GDK_KEY_PRESS && event_type != GDK_KEY_RELEASE)
return FALSE;
if (key->im_context &&
gtk_im_context_filter_keypress (key->im_context, event))
{
@@ -186,6 +195,7 @@ gtk_event_controller_key_class_init (GtkEventControllerKeyClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gtk_event_controller_key_finalize;
controller_class->filter_event = gtk_event_controller_key_filter_event;
controller_class->handle_event = gtk_event_controller_key_handle_event;
controller_class->handle_crossing = gtk_event_controller_key_handle_crossing;

View File

@@ -55,6 +55,13 @@ static guint signals[N_SIGNALS] = { 0, };
G_DEFINE_TYPE (GtkEventControllerLegacy, gtk_event_controller_legacy,
GTK_TYPE_EVENT_CONTROLLER)
static GtkFilterEventStatus
gtk_event_controller_legacy_filter_event (GtkEventController *controller,
GdkEvent *event)
{
return GTK_EVENT_HANDLE;
}
static gboolean
gtk_event_controller_legacy_handle_event (GtkEventController *controller,
GdkEvent *event,
@@ -73,6 +80,7 @@ gtk_event_controller_legacy_class_init (GtkEventControllerLegacyClass *klass)
{
GtkEventControllerClass *controller_class = GTK_EVENT_CONTROLLER_CLASS (klass);
controller_class->filter_event = gtk_event_controller_legacy_filter_event;
controller_class->handle_event = gtk_event_controller_legacy_handle_event;
/**

View File

@@ -73,22 +73,27 @@ static guint signals[N_SIGNALS] = { 0 };
G_DEFINE_TYPE (GtkEventControllerMotion, gtk_event_controller_motion, GTK_TYPE_EVENT_CONTROLLER)
static GtkFilterEventStatus
gtk_event_controller_motion_filter_event (GtkEventController *controller,
GdkEvent *event)
{
GdkEventType event_type = gdk_event_get_event_type (event);
if (event_type == GDK_MOTION_NOTIFY)
return GTK_EVENT_HANDLE;
return GTK_EVENT_SKIP;
}
static gboolean
gtk_event_controller_motion_handle_event (GtkEventController *controller,
GdkEvent *event,
double x,
double y)
{
GtkEventControllerClass *parent_class;
GdkEventType type;
g_signal_emit (controller, signals[MOTION], 0, x, y);
type = gdk_event_get_event_type (event);
if (type == GDK_MOTION_NOTIFY)
g_signal_emit (controller, signals[MOTION], 0, x, y);
parent_class = GTK_EVENT_CONTROLLER_CLASS (gtk_event_controller_motion_parent_class);
return parent_class->handle_event (controller, event, x, y);
return GDK_EVENT_PROPAGATE;
}
static void
@@ -191,6 +196,7 @@ gtk_event_controller_motion_class_init (GtkEventControllerMotionClass *klass)
object_class->get_property = gtk_event_controller_motion_get_property;
controller_class->filter_event = gtk_event_controller_motion_filter_event;
controller_class->handle_event = gtk_event_controller_motion_handle_event;
controller_class->handle_crossing = gtk_event_controller_motion_handle_crossing;

View File

@@ -22,6 +22,16 @@
#include "gtkeventcontroller.h"
/*
* GtkFilterEventStatus:
* @GTK_EVENT_HANDLE: the event will be used by the controller
* @GTK_EVENT_SKIP: the event will be skipped
*/
typedef enum {
GTK_EVENT_HANDLE,
GTK_EVENT_SKIP
} GtkFilterEventStatus;
/* GdkCrossingType:
* @GTK_CROSSING_FOCUS: Focus moved from one widget to another
* @GTK_CROSSING_ACTIVE: The active window changed (the crossing
@@ -108,11 +118,11 @@ struct _GtkEventControllerClass
/*<private>*/
/* Tells whether the event is filtered out, %TRUE makes
* the event unseen by the handle_event vfunc.
/* Tells whether the event will be processed or filtered out.
* By default all events are skipped, subclasses will need to list them.
*/
gboolean (* filter_event) (GtkEventController *controller,
GdkEvent *event);
GtkFilterEventStatus (* filter_event) (GtkEventController *controller,
GdkEvent *event);
gpointer padding[10];
};

View File

@@ -337,6 +337,18 @@ gtk_event_controller_scroll_handle_hold_event (GtkEventController *controller,
return GDK_EVENT_PROPAGATE;
}
static GtkFilterEventStatus
gtk_event_controller_scroll_filter_event (GtkEventController *controller,
GdkEvent *event)
{
GdkEventType event_type = gdk_event_get_event_type (event);
if (event_type == GDK_SCROLL || event_type == GDK_TOUCHPAD_HOLD)
return GTK_EVENT_HANDLE;
return GTK_EVENT_SKIP;
}
static gboolean
gtk_event_controller_scroll_handle_event (GtkEventController *controller,
GdkEvent *event,
@@ -355,9 +367,6 @@ gtk_event_controller_scroll_handle_event (GtkEventController *controller,
if (event_type == GDK_TOUCHPAD_HOLD)
return gtk_event_controller_scroll_handle_hold_event (controller, event);
if (event_type != GDK_SCROLL)
return FALSE;
if ((scroll->flags & (GTK_EVENT_CONTROLLER_SCROLL_VERTICAL |
GTK_EVENT_CONTROLLER_SCROLL_HORIZONTAL)) == 0)
return FALSE;
@@ -473,6 +482,7 @@ gtk_event_controller_scroll_class_init (GtkEventControllerScrollClass *klass)
object_class->set_property = gtk_event_controller_scroll_set_property;
object_class->get_property = gtk_event_controller_scroll_get_property;
controller_class->filter_event = gtk_event_controller_scroll_filter_event;
controller_class->handle_event = gtk_event_controller_scroll_handle_event;
/**

View File

@@ -609,19 +609,28 @@ gesture_within_surface (GtkGesture *gesture,
return surface == gtk_native_get_surface (gtk_widget_get_native (widget));
}
static gboolean
static GtkFilterEventStatus
gtk_gesture_filter_event (GtkEventController *controller,
GdkEvent *event)
{
/* Even though GtkGesture handles these events, we want
* touchpad gestures disabled by default, it will be
* subclasses which punch the holes in for the events
GdkEventType event_type = gdk_event_get_event_type (event);
/* Even though GtkGesture handles touchpad events, we want to skip them by
* default, it will be subclasses which punch the holes in for the events
* they can possibly handle.
*/
if (EVENT_IS_TOUCHPAD_GESTURE (event))
return FALSE;
return GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_parent_class)->filter_event (controller, event);
if (event_type == GDK_BUTTON_PRESS ||
event_type == GDK_BUTTON_RELEASE ||
event_type == GDK_MOTION_NOTIFY ||
event_type == GDK_TOUCH_BEGIN ||
event_type == GDK_TOUCH_UPDATE ||
event_type == GDK_TOUCH_END ||
event_type == GDK_TOUCH_CANCEL ||
event_type == GDK_GRAB_BROKEN)
return GTK_EVENT_HANDLE;
return GTK_EVENT_SKIP;
}
static gboolean

View File

@@ -58,7 +58,7 @@ static guint signals[N_SIGNALS] = { 0 };
G_DEFINE_TYPE_WITH_PRIVATE (GtkGestureDrag, gtk_gesture_drag, GTK_TYPE_GESTURE_SINGLE)
static gboolean
static GtkFilterEventStatus
gtk_gesture_drag_filter_event (GtkEventController *controller,
GdkEvent *event)
{
@@ -72,9 +72,9 @@ gtk_gesture_drag_filter_event (GtkEventController *controller,
n_fingers = gdk_touchpad_event_get_n_fingers (event);
if (n_fingers == n_points)
return FALSE;
return GTK_EVENT_HANDLE;
else
return TRUE;
return GTK_EVENT_SKIP;
}
return GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_drag_parent_class)->filter_event (controller, event);

View File

@@ -168,7 +168,7 @@ gtk_gesture_rotate_update (GtkGesture *gesture,
_gtk_gesture_rotate_check_emit (GTK_GESTURE_ROTATE (gesture));
}
static gboolean
static GtkFilterEventStatus
gtk_gesture_rotate_filter_event (GtkEventController *controller,
GdkEvent *event)
{
@@ -181,9 +181,9 @@ gtk_gesture_rotate_filter_event (GtkEventController *controller,
n_fingers = gdk_touchpad_event_get_n_fingers (event);
if (n_fingers == 2)
return FALSE;
return GTK_EVENT_HANDLE;
else
return TRUE;
return GTK_EVENT_SKIP;
}
return GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_rotate_parent_class)->filter_event (controller, event);

View File

@@ -80,7 +80,7 @@ gtk_gesture_swipe_finalize (GObject *object)
G_OBJECT_CLASS (gtk_gesture_swipe_parent_class)->finalize (object);
}
static gboolean
static GtkFilterEventStatus
gtk_gesture_swipe_filter_event (GtkEventController *controller,
GdkEvent *event)
{
@@ -96,9 +96,9 @@ gtk_gesture_swipe_filter_event (GtkEventController *controller,
n_fingers = gdk_touchpad_event_get_n_fingers (event);
if (n_fingers == n_points)
return FALSE;
return GTK_EVENT_HANDLE;
else
return TRUE;
return GTK_EVENT_SKIP;
}
return GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_swipe_parent_class)->filter_event (controller, event);

View File

@@ -145,7 +145,7 @@ _gtk_gesture_zoom_check_emit (GtkGestureZoom *gesture)
return TRUE;
}
static gboolean
static GtkFilterEventStatus
gtk_gesture_zoom_filter_event (GtkEventController *controller,
GdkEvent *event)
{
@@ -158,9 +158,9 @@ gtk_gesture_zoom_filter_event (GtkEventController *controller,
n_fingers = gdk_touchpad_event_get_n_fingers (event);
if (n_fingers == 2)
return FALSE;
return GTK_EVENT_HANDLE;
else
return TRUE;
return GTK_EVENT_SKIP;
}
return GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_zoom_parent_class)->filter_event (controller, event);

View File

@@ -198,7 +198,7 @@ gtk_pad_controller_handle_mode_switch (GtkPadController *controller,
#endif
}
static gboolean
static GtkFilterEventStatus
gtk_pad_controller_filter_event (GtkEventController *controller,
GdkEvent *event)
{
@@ -210,13 +210,13 @@ gtk_pad_controller_filter_event (GtkEventController *controller,
event_type != GDK_PAD_RING &&
event_type != GDK_PAD_STRIP &&
event_type != GDK_PAD_GROUP_MODE)
return TRUE;
return GTK_EVENT_SKIP;
if (pad_controller->pad &&
gdk_event_get_device (event) != pad_controller->pad)
return TRUE;
return GTK_EVENT_SKIP;
return FALSE;
return GTK_EVENT_HANDLE;
}
static gboolean

View File

@@ -422,6 +422,18 @@ gtk_shortcut_controller_run_controllers (GtkEventController *controller,
return retval;
}
static GtkFilterEventStatus
gtk_shortcut_controller_filter_event (GtkEventController *controller,
GdkEvent *event)
{
GdkEventType event_type = gdk_event_get_event_type (event);
if (event_type == GDK_KEY_PRESS || event_type == GDK_KEY_RELEASE)
return GTK_EVENT_HANDLE;
return GTK_EVENT_SKIP;
}
static gboolean
gtk_shortcut_controller_handle_event (GtkEventController *controller,
GdkEvent *event,
@@ -435,9 +447,6 @@ gtk_shortcut_controller_handle_event (GtkEventController *controller,
if (self->scope != GTK_SHORTCUT_SCOPE_LOCAL)
return FALSE;
if (event_type != GDK_KEY_PRESS && event_type != GDK_KEY_RELEASE)
return FALSE;
if (event_type == GDK_KEY_PRESS)
{
GdkModifierType modifiers, consumed_modifiers;
@@ -558,6 +567,7 @@ gtk_shortcut_controller_class_init (GtkShortcutControllerClass *klass)
object_class->set_property = gtk_shortcut_controller_set_property;
object_class->get_property = gtk_shortcut_controller_get_property;
controller_class->filter_event = gtk_shortcut_controller_filter_event;
controller_class->handle_event = gtk_shortcut_controller_handle_event;
controller_class->set_widget = gtk_shortcut_controller_set_widget;
controller_class->unset_widget = gtk_shortcut_controller_unset_widget;