Compare commits

...

14 Commits

Author SHA1 Message Date
Alexander Mikhaylenko
74002c680a tmp 2022-05-11 18:31:07 +04:00
Alexander Mikhaylenko
7dac42a3fd Revert "gesturedrag: Allow scroll events"
This reverts commit 654b03d47a.
2022-05-02 23:04:52 +04:00
Alexander Mikhaylenko
41fff5c88a Revert "gestureswipe: Allow scroll events"
This reverts commit 03de3ceaf1.
2022-05-02 23:04:45 +04:00
Alexander Mikhaylenko
53a69af780 scrolledwindow: Port to the new controllers
Make sure the drag code path can handle scrolling without behavior
changes, replace GtkEventControllerScroll with Wheel.
2022-05-02 14:02:50 +04:00
Alexander Mikhaylenko
876d409129 fixup! Add GtkEventControllerWheel 2022-05-02 14:02:38 +04:00
Alexander Mikhaylenko
423db86e5e tmp demo 2022-04-29 19:57:11 +04:00
Alexander Mikhaylenko
06b0e0203c Add GtkEventControllerWheel
Gestures handle touchpad and trackpoint scrolling now, but we still need
something for mice. Add a new controller that does just that, without
scroll-begin/end or deceleration handling.
2022-04-29 19:57:09 +04:00
Alexander Mikhaylenko
03de3ceaf1 gestureswipe: Allow scroll events 2022-04-29 19:56:02 +04:00
Alexander Mikhaylenko
835366c5a1 gestureswipe: Don't emit :swipe for cancelled gestures
Turns out that it was emitting the :swipe signal when ending the gesture
unconditionally, even if was cancelled. That shouldn't happen.
2022-04-29 19:53:56 +04:00
Alexander Mikhaylenko
654b03d47a gesturedrag: Allow scroll events 2022-04-29 19:53:40 +04:00
Alexander Mikhaylenko
4dba0eaa9f gesturesingle: Pass through scroll events
We want to have them in GtkGestureDrag/Pan/Swipe.

Ignore motion events when no button is pressed - otherwise moving the
widget under the poitner in response to scrolling or a touchpad swipe would
interfere with them.

FIXME: I don't remmeber what ther button == 0 is about.
2022-04-29 19:53:25 +04:00
Alexander Mikhaylenko
51e6774ddd gesture: Handle scroll events
This is the first step for supporting touchpad scrolling in gestures like
GtkGestureDrag.
2022-04-29 19:50:14 +04:00
Alexander Mikhaylenko
f1950cc84d 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.
2022-04-29 19:41:29 +04:00
Alexander Mikhaylenko
7ac3e5ac53 events: Give scroll events pointer position
We'll need to have it for parity with touchpad swipes to use in GtkGesture.

FIXME: do we want to stop accumulation when position changes?
2022-04-29 19:39:03 +04:00
36 changed files with 1043 additions and 220 deletions

View File

@@ -46,17 +46,26 @@ static void
setup_listitem_cb (GtkListItemFactory *factory,
GtkListItem *list_item)
{
GtkWidget *swindow;
GtkWidget *box;
GtkWidget *image;
GtkWidget *label;
swindow = gtk_scrolled_window_new ();
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
GTK_POLICY_EXTERNAL, GTK_POLICY_NEVER);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (swindow), box);
gtk_widget_set_size_request (box, 1000, 200);
image = gtk_image_new ();
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
gtk_box_append (GTK_BOX (box), image);
label = gtk_label_new ("");
gtk_box_append (GTK_BOX (box), label);
gtk_list_item_set_child (list_item, box);
gtk_list_item_set_child (list_item, swindow);
g_object_set_data (G_OBJECT (list_item), "image", image);
g_object_set_data (G_OBJECT (list_item), "label", label);
}
/* Here we need to prepare the listitem for displaying its item. We get the
@@ -73,12 +82,12 @@ bind_listitem_cb (GtkListItemFactory *factory,
GtkWidget *label;
GAppInfo *app_info;
image = gtk_widget_get_first_child (gtk_list_item_get_child (list_item));
label = gtk_widget_get_next_sibling (image);
image = g_object_get_data (G_OBJECT (list_item), "image");
label = g_object_get_data (G_OBJECT (list_item), "label");
app_info = gtk_list_item_get_item (list_item);
gtk_image_set_from_gicon (GTK_IMAGE (image), g_app_info_get_icon (app_info));
gtk_label_set_label (GTK_LABEL (label), g_app_info_get_display_name (app_info));
gtk_label_set_label (GTK_LABEL (label), g_strdup_printf ("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magnam aliquam quaerat voluptatem. ut enim ad sapientiam perveniri potest, non paranda nobis solum ea, sed fruenda etiam sapientia est; sive hoc difficile est, tamen nec modus ullus nec finis inveniri potest. Quodsi. %s", g_app_info_get_display_name (app_info)));
}
/* In more complex code, we would also need functions to unbind and teardown

View File

@@ -187,6 +187,8 @@ _gdk_broadway_events_got_input (GdkDisplay *display,
NULL,
message->base.time,
message->pointer.state,
message->pointer.win_x,
message->pointer.win_y,
message->scroll.dir == 0
? GDK_SCROLL_UP
: GDK_SCROLL_DOWN,

View File

@@ -615,6 +615,8 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
GdkScrollUnit scroll_unit = GDK_SCROLL_UNIT_WHEEL;
gboolean scroll_unit_defined = FALSE;
GdkTimeCoord hist;
double x = 0.0, y = 0.0;
gboolean has_coords = FALSE;
l = g_queue_peek_tail_link (&display->queued_events);
@@ -622,6 +624,7 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
{
GdkEvent *event = l->data;
GdkScrollEvent *scroll_event = (GdkScrollEvent *) event;
double event_x, event_y;
if (event->flags & GDK_EVENT_PENDING)
break;
@@ -642,6 +645,14 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
scroll_unit != scroll_event->unit)
break;
gdk_event_get_position (event, &event_x, &event_y);
if (has_coords && x != event_x)
break;
if (has_coords && y != event_y) // FIXME do we want this?
break;
if (!last_event)
last_event = event;
@@ -649,6 +660,9 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
device = event->device;
scroll_unit = scroll_event->unit;
scroll_unit_defined = TRUE;
has_coords = TRUE;
x = event_x;
y = event_y;
scrolls = l;
l = l->prev;
@@ -718,6 +732,8 @@ gdk_event_queue_handle_scroll_compression (GdkDisplay *display)
gdk_event_get_device_tool (old_event),
gdk_event_get_time (old_event),
gdk_event_get_modifier_state (old_event),
x,
y,
dx,
dy,
gdk_scroll_event_is_stop (old_event),
@@ -2320,6 +2336,19 @@ gdk_scroll_event_get_state (GdkEvent *event)
return self->state;
}
static gboolean
gdk_scroll_event_get_position (GdkEvent *event,
double *x,
double *y)
{
GdkScrollEvent *self = (GdkScrollEvent *) event;
*x = self->x;
*y = self->y;
return TRUE;
}
static GdkDeviceTool *
gdk_scroll_event_get_tool (GdkEvent *event)
{
@@ -2333,7 +2362,7 @@ static const GdkEventTypeInfo gdk_scroll_event_info = {
NULL,
gdk_scroll_event_finalize,
gdk_scroll_event_get_state,
NULL,
gdk_scroll_event_get_position,
NULL,
gdk_scroll_event_get_tool,
NULL,
@@ -2349,6 +2378,8 @@ gdk_scroll_event_new (GdkSurface *surface,
GdkDeviceTool *tool,
guint32 time,
GdkModifierType state,
double x,
double y,
double delta_x,
double delta_y,
gboolean is_stop,
@@ -2359,6 +2390,8 @@ gdk_scroll_event_new (GdkSurface *surface,
self->tool = tool != NULL ? g_object_ref (tool) : NULL;
self->state = state;
self->direction = GDK_SCROLL_SMOOTH;
self->x = x;
self->y = y;
self->delta_x = delta_x;
self->delta_y = delta_y;
self->is_stop = is_stop;
@@ -2373,6 +2406,8 @@ gdk_scroll_event_new_discrete (GdkSurface *surface,
GdkDeviceTool *tool,
guint32 time,
GdkModifierType state,
double x,
double y,
GdkScrollDirection direction,
gboolean emulated)
{
@@ -2380,6 +2415,8 @@ gdk_scroll_event_new_discrete (GdkSurface *surface,
self->tool = tool != NULL ? g_object_ref (tool) : NULL;
self->state = state;
self->x = x;
self->y = y;
self->direction = direction;
self->pointer_emulated = emulated;
self->unit = GDK_SCROLL_UNIT_WHEEL;

View File

@@ -204,6 +204,8 @@ struct _GdkTouchEvent
* @direction: the direction to scroll to (one of %GDK_SCROLL_UP,
* %GDK_SCROLL_DOWN, %GDK_SCROLL_LEFT, %GDK_SCROLL_RIGHT or
* %GDK_SCROLL_SMOOTH).
* @x: the x coordinate of the pointer
* @y: the y coordinate of the pointer
* @delta_x: the x coordinate of the scroll delta
* @delta_y: the y coordinate of the scroll delta
* @pointer_emulated: whether the scroll event was the result of
@@ -229,6 +231,8 @@ struct _GdkScrollEvent
GdkModifierType state;
GdkScrollDirection direction;
double x;
double y;
double delta_x;
double delta_y;
gboolean pointer_emulated;
@@ -486,6 +490,8 @@ GdkEvent * gdk_scroll_event_new (GdkSurface *surface,
GdkDeviceTool *tool,
guint32 time,
GdkModifierType state,
double x,
double y,
double delta_x,
double delta_y,
gboolean is_stop,
@@ -496,6 +502,8 @@ GdkEvent * gdk_scroll_event_new_discrete (GdkSurface *surface,
GdkDeviceTool *tool,
guint32 time,
GdkModifierType state,
double x,
double y,
GdkScrollDirection direction,
gboolean emulated);

View File

@@ -644,6 +644,7 @@ fill_scroll_event (GdkMacosDisplay *self,
NULL,
get_time_from_ns_event (nsevent),
state,
x, y,
0.0, 0.0, TRUE,
GDK_SCROLL_UNIT_SURFACE);
@@ -664,6 +665,8 @@ fill_scroll_event (GdkMacosDisplay *self,
NULL,
get_time_from_ns_event (nsevent),
state,
x,
y,
-sx,
-sy,
FALSE,
@@ -700,6 +703,8 @@ fill_scroll_event (GdkMacosDisplay *self,
NULL,
get_time_from_ns_event (nsevent),
state,
x,
y,
direction,
FALSE);
}
@@ -716,6 +721,7 @@ fill_scroll_event (GdkMacosDisplay *self,
NULL,
get_time_from_ns_event (nsevent),
state,
x, y,
0.0, 0.0, TRUE,
GDK_SCROLL_UNIT_SURFACE);
}

View File

@@ -1394,6 +1394,8 @@ flush_discrete_scroll_event (GdkWaylandSeat *seat,
NULL,
seat->pointer_info.time,
device_get_modifiers (seat->logical_pointer),
seat->pointer_info.surface_x,
seat->pointer_info.surface_y,
direction,
TRUE);
@@ -1415,6 +1417,8 @@ flush_smooth_scroll_event (GdkWaylandSeat *seat,
NULL,
seat->pointer_info.time,
device_get_modifiers (seat->logical_pointer),
seat->pointer_info.surface_x,
seat->pointer_info.surface_y,
delta_x, delta_y,
is_stop,
GDK_SCROLL_UNIT_SURFACE);
@@ -3994,6 +3998,8 @@ tablet_tool_handle_wheel (void *data,
tablet->current_tool->tool,
tablet->pointer_info.time,
device_get_modifiers (tablet->logical_device),
tablet->pointer_info.surface_x,
tablet->pointer_info.surface_y,
0, clicks,
FALSE,
GDK_SCROLL_UNIT_WHEEL);
@@ -4006,6 +4012,8 @@ tablet_tool_handle_wheel (void *data,
tablet->current_tool->tool,
tablet->pointer_info.time,
device_get_modifiers (tablet->logical_device),
tablet->pointer_info.surface_x,
tablet->pointer_info.surface_y,
clicks > 0 ? GDK_SCROLL_DOWN : GDK_SCROLL_UP,
TRUE);

View File

@@ -2727,6 +2727,8 @@ gdk_event_translate (MSG *msg,
NULL,
_gdk_win32_get_next_tick (msg->time),
build_pointer_event_state (msg),
point.x,
point.y,
delta_x,
delta_y,
FALSE,
@@ -2748,6 +2750,8 @@ gdk_event_translate (MSG *msg,
NULL,
_gdk_win32_get_next_tick (msg->time),
build_pointer_event_state (msg),
point.x,
point.y,
direction,
TRUE);

View File

@@ -1663,6 +1663,8 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
NULL,
xev->time,
_gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group),
(double) xev->event_x / scale,
(double) xev->event_x / scale,
direction,
FALSE);
@@ -1766,6 +1768,8 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
NULL,
xev->time,
state,
(double) xev->event_x / scale,
(double) xev->event_y / scale,
direction,
FALSE);
}
@@ -1776,6 +1780,8 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
NULL,
xev->time,
state,
(double) xev->event_x / scale,
(double) xev->event_y / scale,
delta_x,
delta_y,
delta_x == 0.0 && delta_y == 0.0,

View File

@@ -114,6 +114,7 @@
#include <gtk/gtkeventcontrollerlegacy.h>
#include <gtk/gtkeventcontrollermotion.h>
#include <gtk/gtkeventcontrollerscroll.h>
#include <gtk/gtkeventcontrollerwheel.h>
#include <gtk/gtkexpander.h>
#include <gtk/gtkexpression.h>
#include <gtk/gtkfixed.h>

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

@@ -0,0 +1,227 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2017, Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author(s): Carlos Garnacho <carlosg@gnome.org>
*/
/**
* GtkEventControllerWheel:
*
* `GtkEventControllerWheel` is an event controller that handles mouse scroll
* events.
*
* It is capable of handling both discrete and continuous scroll
* events from mice or touchpads, abstracting them both with the
* [signal@Gtk.EventControllerScroll::scroll] signal. Deltas in
* the discrete case are multiples of 1.
*
* In the case of continuous scroll events, `GtkEventControllerScroll`
* encloses all [signal@Gtk.EventControllerScroll::scroll] emissions
* between two [signal@Gtk.EventControllerScroll::scroll-begin] and
* [signal@Gtk.EventControllerScroll::scroll-end] signals.
*
* The behavior of the event controller can be modified by the flags
* given at creation time, or modified at a later point through
* [method@Gtk.EventControllerScroll.set_flags] (e.g. because the scrolling
* conditions of the widget changed).
*
* The controller can be set up to emit motion for either/both vertical
* and horizontal scroll events through %GTK_EVENT_CONTROLLER_SCROLL_VERTICAL,
* %GTK_EVENT_CONTROLLER_SCROLL_HORIZONTAL and %GTK_EVENT_CONTROLLER_SCROLL_BOTH_AXES.
* If any axis is disabled, the respective [signal@Gtk.EventControllerScroll::scroll]
* delta will be 0. Vertical scroll events will be translated to horizontal
* motion for the devices incapable of horizontal scrolling.
*
* The event controller can also be forced to emit discrete events on all
* devices through %GTK_EVENT_CONTROLLER_SCROLL_DISCRETE. This can be used
* to implement discrete actions triggered through scroll events (e.g.
* switching across combobox options).
*
* The %GTK_EVENT_CONTROLLER_SCROLL_KINETIC flag toggles the emission of the
* [signal@Gtk.EventControllerScroll::decelerate] signal, emitted at the end
* of scrolling with two X/Y velocity arguments that are consistent with the
* motion that was received.
*
* Since: 4.8
*/
#include "config.h"
#include "gtkintl.h"
#include "gtkeventcontrollerprivate.h"
#include "gtkeventcontrollerwheel.h"
#include "gtkmarshalers.h"
#include "gtkprivate.h"
struct _GtkEventControllerWheel
{
GtkEventController parent_instance;
GdkScrollUnit cur_unit;
};
struct _GtkEventControllerWheelClass
{
GtkEventControllerClass parent_class;
};
enum {
SCROLL,
N_SIGNALS
};
static guint signals[N_SIGNALS] = { 0 };
G_DEFINE_TYPE (GtkEventControllerWheel, gtk_event_controller_wheel,
GTK_TYPE_EVENT_CONTROLLER)
static GtkFilterEventStatus
gtk_event_controller_wheel_filter_event (GtkEventController *controller,
GdkEvent *event)
{
GdkEventType event_type = gdk_event_get_event_type (event);
if (event_type == GDK_SCROLL) {
GdkDevice *source_device = gdk_event_get_device (event);
GdkInputSource source = gdk_device_get_source (source_device);
if (source == GDK_SOURCE_MOUSE)
return GTK_EVENT_HANDLE;
}
return GTK_EVENT_SKIP;
}
static gboolean
gtk_event_controller_wheel_handle_event (GtkEventController *controller,
GdkEvent *event,
double x,
double y)
{
GtkEventControllerWheel *self = GTK_EVENT_CONTROLLER_WHEEL (controller);
GdkScrollDirection direction = GDK_SCROLL_SMOOTH;
double dx = 0, dy = 0;
gboolean handled = GDK_EVENT_PROPAGATE;
/* FIXME: Handle device changes */
direction = gdk_scroll_event_get_direction (event);
if (direction == GDK_SCROLL_SMOOTH)
gdk_scroll_event_get_deltas (event, &dx, &dy);
else
{
switch (direction)
{
case GDK_SCROLL_UP:
dy -= 1;
break;
case GDK_SCROLL_DOWN:
dy += 1;
break;
case GDK_SCROLL_LEFT:
dx -= 1;
break;
case GDK_SCROLL_RIGHT:
dx += 1;
break;
case GDK_SCROLL_SMOOTH:
default:
g_assert_not_reached ();
break;
}
}
if (dx != 0 || dy != 0)
g_signal_emit (controller, signals[SCROLL], 0, dx, dy, &handled);
self->cur_unit = gdk_scroll_event_get_unit (event);
return handled;
}
static void
gtk_event_controller_wheel_class_init (GtkEventControllerWheelClass *klass)
{
GtkEventControllerClass *controller_class = GTK_EVENT_CONTROLLER_CLASS (klass);
controller_class->filter_event = gtk_event_controller_wheel_filter_event;
controller_class->handle_event = gtk_event_controller_wheel_handle_event;
/**
* GtkEventControllerWheel:scroll:
* @controller: The object that received the signal
* @dx: X delta
* @dy: Y delta
*
* Signals that the widget should scroll by the
* amount specified by @dx and @dy.
*
* Returns: %TRUE if the scroll event was handled,
* %FALSE otherwise.
*/
signals[SCROLL] =
g_signal_new (I_("scroll"),
GTK_TYPE_EVENT_CONTROLLER_WHEEL,
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
_gtk_marshal_BOOLEAN__DOUBLE_DOUBLE,
G_TYPE_BOOLEAN, 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
g_signal_set_va_marshaller (signals[SCROLL],
G_TYPE_FROM_CLASS (klass),
_gtk_marshal_BOOLEAN__DOUBLE_DOUBLEv);
}
static void
gtk_event_controller_wheel_init (GtkEventControllerWheel *self)
{
}
/**
* gtk_event_controller_wheel_new:
*
* Creates a new event controller that will handle scroll events.
*
* Returns: a new `GtkEventControllerWheel`
*
* Since: 4.8
*/
GtkEventController *
gtk_event_controller_wheel_new (void)
{
return g_object_new (GTK_TYPE_EVENT_CONTROLLER_WHEEL,
NULL);
}
/**
* gtk_event_controller_wheel_get_unit:
* @self: a `GtkEventControllerWheel`.
*
* Gets the scroll unit of the last
* [signal@Gtk.GtkEventControllerWheel::scroll] signal received.
*
* Always returns %GDK_SCROLL_UNIT_WHEEL if the
* %GTK_EVENT_CONTROLLER_SCROLL_DISCRETE flag is set.
*
* Returns: the scroll unit.
*
* Since: 4.8
*/
GdkScrollUnit
gtk_event_controller_wheel_get_unit (GtkEventControllerWheel *self)
{
g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER_WHEEL (self),
GDK_SCROLL_UNIT_WHEEL);
return self->cur_unit;
}

View File

@@ -0,0 +1,50 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2017, Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author(s): Carlos Garnacho <carlosg@gnome.org>
*/
#pragma once
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#include <gdk/gdk.h>
#include <gtk/gtkeventcontroller.h>
G_BEGIN_DECLS
#define GTK_TYPE_EVENT_CONTROLLER_WHEEL (gtk_event_controller_wheel_get_type ())
#define GTK_EVENT_CONTROLLER_WHEEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_EVENT_CONTROLLER_WHEEL, GtkEventControllerWheel))
#define GTK_EVENT_CONTROLLER_WHEEL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_EVENT_CONTROLLER_WHEEL, GtkEventControllerWheelClass))
#define GTK_IS_EVENT_CONTROLLER_WHEEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_EVENT_CONTROLLER_WHEEL))
#define GTK_IS_EVENT_CONTROLLER_WHEEL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_EVENT_CONTROLLER_WHEEL))
#define GTK_EVENT_CONTROLLER_WHEEL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_EVENT_CONTROLLER_WHEEL, GtkEventControllerWheelClass))
typedef struct _GtkEventControllerWheel GtkEventControllerWheel;
typedef struct _GtkEventControllerWheelClass GtkEventControllerWheelClass;
GDK_AVAILABLE_IN_4_8
GType gtk_event_controller_wheel_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_4_8
GtkEventController *gtk_event_controller_wheel_new (void);
GDK_AVAILABLE_IN_4_8
GdkScrollUnit gtk_event_controller_wheel_get_unit (GtkEventControllerWheel *self);
G_END_DECLS

View File

@@ -165,6 +165,7 @@ struct _GtkGesturePrivate
guint hold_timeout_id;
guint recognized : 1;
guint touchpad : 1;
guint scrolling : 1;
};
static guint signals[N_SIGNALS] = { 0 };
@@ -232,6 +233,31 @@ gtk_gesture_finalize (GObject *object)
G_OBJECT_CLASS (gtk_gesture_parent_class)->finalize (object);
}
static guint
_gtk_gesture_get_n_scroll_points (GtkGesture *gesture,
gboolean only_active)
{
GtkGesturePrivate *priv;
PointData *data;
priv = gtk_gesture_get_instance_private (gesture);
if (!priv->scrolling)
return 0;
data = g_hash_table_lookup (priv->points, NULL);
if (!data)
return 0;
if (only_active &&
(data->state == GTK_EVENT_SEQUENCE_DENIED ||
gdk_scroll_event_is_stop (data->event)))
return 0;
return 2;
}
static guint
_gtk_gesture_get_n_touchpad_points (GtkGesture *gesture,
gboolean only_active)
@@ -307,7 +333,9 @@ _gtk_gesture_get_n_physical_points (GtkGesture *gesture,
priv = gtk_gesture_get_instance_private (gesture);
if (priv->touchpad)
if (priv->scrolling)
return _gtk_gesture_get_n_scroll_points (gesture, only_active);
else if (priv->touchpad)
return _gtk_gesture_get_n_touchpad_points (gesture, only_active);
else
return _gtk_gesture_get_n_touch_points (gesture, only_active);
@@ -318,10 +346,16 @@ gtk_gesture_check_impl (GtkGesture *gesture)
{
GtkGesturePrivate *priv;
guint n_points;
GdkEvent *event;
priv = gtk_gesture_get_instance_private (gesture);
n_points = _gtk_gesture_get_n_physical_points (gesture, TRUE);
event = gtk_gesture_get_last_event (gesture, priv->last_sequence);
if (event && gdk_event_get_event_type (event) == GDK_TOUCHPAD_HOLD)
return n_points >= 1 && n_points <= priv->n_points;
return n_points == priv->n_points;
}
@@ -365,10 +399,21 @@ _gtk_gesture_has_matching_touchpoints (GtkGesture *gesture)
{
GtkGesturePrivate *priv = gtk_gesture_get_instance_private (gesture);
guint active_n_points, current_n_points;
GdkEvent *event;
current_n_points = _gtk_gesture_get_n_physical_points (gesture, FALSE);
active_n_points = _gtk_gesture_get_n_physical_points (gesture, TRUE);
event = gtk_gesture_get_last_event (gesture, priv->last_sequence);
if (event && gdk_event_get_event_type (event) == GDK_TOUCHPAD_HOLD)
{
return (active_n_points <= priv->n_points &&
active_n_points >= 1 &&
current_n_points <= priv->n_points &&
current_n_points >= 1);
}
return (active_n_points == priv->n_points &&
current_n_points == priv->n_points);
}
@@ -417,6 +462,13 @@ _update_touchpad_deltas (PointData *data)
data->accum_dy += dy;
}
}
else if (gdk_event_get_event_type (event) == GDK_SCROLL)
{
gdk_scroll_event_get_deltas (event, &dx, &dy);
data->accum_dx += dx;
data->accum_dy += dy;
}
}
static GtkEventSequenceState
@@ -453,7 +505,7 @@ _gtk_gesture_update_point (GtkGesture *gesture,
GdkEventSequence *sequence;
GtkGesturePrivate *priv;
GdkDevice *device;
gboolean existed, touchpad;
gboolean existed, touchpad, scrolling, hold;
PointData *data;
device = gdk_event_get_device (event);
@@ -463,9 +515,30 @@ _gtk_gesture_update_point (GtkGesture *gesture,
priv = gtk_gesture_get_instance_private (gesture);
touchpad = EVENT_IS_TOUCHPAD_GESTURE (event);
hold = gdk_event_get_event_type (event) == GDK_TOUCHPAD_HOLD;
scrolling = gdk_event_get_event_type (event) == GDK_SCROLL;
if (add)
{
gboolean was_scrolling;
/* FIXME if it was already claimed, set the thing */
was_scrolling = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (device),
"gtk-gesture-is-device-scrolling"));
/* The device changes when transitioning from hold to scrolling */
if (scrolling && priv->touchpad && !was_scrolling)
{
priv->device = device;
priv->touchpad = touchpad;
priv->scrolling = scrolling;
if (gtk_gesture_get_sequence_state (gesture, NULL) == GTK_EVENT_SEQUENCE_DENIED)
g_object_set_data (G_OBJECT (device),
"gtk-gesture-is-device-scrolling",
GINT_TO_POINTER (TRUE));
}
/* If the event happens with the wrong device, or
* on the wrong window, ignore.
*/
@@ -473,9 +546,9 @@ _gtk_gesture_update_point (GtkGesture *gesture,
return FALSE;
/* Make touchpad and touchscreen gestures mutually exclusive */
if (touchpad && g_hash_table_size (priv->points) > 0)
if ((touchpad || scrolling) && g_hash_table_size (priv->points) > 0)
return FALSE;
else if (!touchpad && priv->touchpad)
else if (!touchpad && priv->touchpad && !scrolling)
return FALSE;
}
else if (!priv->device)
@@ -493,6 +566,7 @@ _gtk_gesture_update_point (GtkGesture *gesture,
{
priv->device = device;
priv->touchpad = touchpad;
priv->scrolling = scrolling;
}
data = g_new0 (PointData, 1);
@@ -539,8 +613,15 @@ _gtk_gesture_check_empty (GtkGesture *gesture)
if (g_hash_table_size (priv->points) == 0)
{
if (priv->scrolling) {
g_print ("%p Removing is-scrolling on %s\n", gesture, gdk_device_get_name (priv->device));
g_object_steal_data (G_OBJECT (priv->device),
"gtk-gesture-is-device-scrolling");
}
priv->device = NULL;
priv->touchpad = FALSE;
priv->scrolling = FALSE;
}
}
@@ -556,9 +637,13 @@ _gtk_gesture_remove_point (GtkGesture *gesture,
device = gdk_event_get_device (event);
priv = gtk_gesture_get_instance_private (gesture);
g_print ("%p remove point\n", gesture);
if (priv->device != device)
return;
g_print ("%p remove point device matches\n", gesture);
g_hash_table_remove (priv->points, sequence);
_gtk_gesture_check_empty (gesture);
}
@@ -609,19 +694,27 @@ 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
* they can possibly handle.
*/
if (EVENT_IS_TOUCHPAD_GESTURE (event))
return FALSE;
GdkEventType event_type = gdk_event_get_event_type (event);
return GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_parent_class)->filter_event (controller, event);
/* Even though GtkGesture handles touchpad and scroll 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_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
@@ -639,6 +732,7 @@ gtk_gesture_handle_event (GtkEventController *controller,
GdkTouchpadGesturePhase phase = 0;
GdkModifierType state;
GtkWidget *target;
gboolean was_scrolling = FALSE, is_scroll_stop = FALSE;
source_device = gdk_event_get_device (event);
@@ -653,6 +747,19 @@ gtk_gesture_handle_event (GtkEventController *controller,
if (EVENT_IS_TOUCHPAD_GESTURE (event))
phase = gdk_touchpad_event_get_gesture_phase (event);
if (event_type == GDK_SCROLL)
{
GdkInputSource source = gdk_device_get_source (source_device);
if (source != GDK_SOURCE_TOUCHPAD &&
source != GDK_SOURCE_TRACKPOINT)
return FALSE; // FIXME
is_scroll_stop = gdk_scroll_event_is_stop (event);
was_scrolling = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (source_device),
"gtk-gesture-is-device-scrolling"));
}
target = gtk_event_controller_get_target (controller);
if (gtk_gesture_get_sequence_state (gesture, sequence) != GTK_EVENT_SEQUENCE_DENIED)
@@ -662,12 +769,17 @@ gtk_gesture_handle_event (GtkEventController *controller,
event_type == GDK_TOUCH_BEGIN ||
(event_type == GDK_TOUCHPAD_SWIPE && phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN) ||
(event_type == GDK_TOUCHPAD_PINCH && phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN) ||
(event_type == GDK_TOUCHPAD_HOLD && phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN))
(event_type == GDK_TOUCHPAD_HOLD && phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN) ||
(event_type == GDK_SCROLL && !priv->scrolling && !is_scroll_stop && !was_scrolling))
{
if ((event_type == GDK_TOUCHPAD_PINCH || event_type == GDK_TOUCHPAD_SWIPE) &&
if ((event_type == GDK_TOUCHPAD_PINCH ||
event_type == GDK_TOUCHPAD_SWIPE ||
event_type == GDK_TOUCHPAD_HOLD ||
event_type == GDK_SCROLL) &&
_gtk_gesture_has_matching_touchpoints (gesture))
g_clear_handle_id (&priv->hold_timeout_id, g_source_remove);
g_print ("%p calling add, was scrolling? %d %s\n", gesture, was_scrolling, gdk_device_get_name (source_device));
if (_gtk_gesture_update_point (gesture, event, target, x, y, TRUE))
{
gboolean triggered_recognition;
@@ -699,7 +811,8 @@ gtk_gesture_handle_event (GtkEventController *controller,
event_type == GDK_TOUCH_END ||
(event_type == GDK_TOUCHPAD_SWIPE && phase == GDK_TOUCHPAD_GESTURE_PHASE_END) ||
(event_type == GDK_TOUCHPAD_PINCH && phase == GDK_TOUCHPAD_GESTURE_PHASE_END) ||
(event_type == GDK_TOUCHPAD_HOLD && phase == GDK_TOUCHPAD_GESTURE_PHASE_END))
(event_type == GDK_TOUCHPAD_HOLD && phase == GDK_TOUCHPAD_GESTURE_PHASE_END) ||
(event_type == GDK_SCROLL && priv->scrolling && is_scroll_stop))
{
gboolean was_claimed = FALSE;
@@ -720,7 +833,8 @@ gtk_gesture_handle_event (GtkEventController *controller,
else if (event_type == GDK_MOTION_NOTIFY ||
event_type == GDK_TOUCH_UPDATE ||
(event_type == GDK_TOUCHPAD_SWIPE && phase == GDK_TOUCHPAD_GESTURE_PHASE_UPDATE) ||
(event_type == GDK_TOUCHPAD_PINCH && phase == GDK_TOUCHPAD_GESTURE_PHASE_UPDATE))
(event_type == GDK_TOUCHPAD_PINCH && phase == GDK_TOUCHPAD_GESTURE_PHASE_UPDATE) ||
(event_type == GDK_SCROLL && priv->scrolling))
{
if (event_type == GDK_MOTION_NOTIFY)
{
@@ -734,7 +848,7 @@ gtk_gesture_handle_event (GtkEventController *controller,
}
else if (event_type == GDK_TOUCH_CANCEL)
{
if (!priv->touchpad)
if (!priv->touchpad && !priv->scrolling)
_gtk_gesture_cancel_sequence (gesture, sequence);
}
else if ((event_type == GDK_TOUCHPAD_SWIPE && phase == GDK_TOUCHPAD_GESTURE_PHASE_CANCEL) ||
@@ -1090,6 +1204,16 @@ gtk_gesture_set_sequence_state (GtkGesture *gesture,
data->state = state;
if (priv->scrolling && state == GTK_EVENT_SEQUENCE_CLAIMED)
{
GdkDevice *source_device = gdk_event_get_device (data->event);
g_print ("%p Setting is-scrolling on %s\n", gesture, gdk_device_get_name (source_device));
g_object_set_data (G_OBJECT (source_device),
"gtk-gesture-is-device-scrolling",
GINT_TO_POINTER (TRUE));
}
gtk_widget_cancel_event_sequence (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)),
gesture, sequence, state);
g_signal_emit (gesture, signals[SEQUENCE_STATE_CHANGED], 0,
@@ -1422,7 +1546,8 @@ gtk_gesture_get_bounding_box_center (GtkGesture *gesture,
sequence = gtk_gesture_get_last_updated_sequence (gesture);
last_event = gtk_gesture_get_last_event (gesture, sequence);
if (EVENT_IS_TOUCHPAD_GESTURE (last_event))
if (EVENT_IS_TOUCHPAD_GESTURE (last_event) ||
gdk_event_get_event_type (last_event) == GDK_SCROLL)
return gtk_gesture_get_point (gesture, sequence, x, y);
else if (!gtk_gesture_get_bounding_box (gesture, &rect))
return FALSE;

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

@@ -73,7 +73,6 @@ gboolean _gtk_gesture_get_last_update_time (GtkGesture *gesture,
GtkWidget *gtk_gesture_get_last_target (GtkGesture *gesture,
GdkEventSequence *sequence);
G_END_DECLS
#endif /* __GTK_GESTURE_PRIVATE_H__ */

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);

215
gtk/gtkgesturescroll.c Normal file
View File

@@ -0,0 +1,215 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 202, Purism SPC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author(s): Alexander Mikhaylenko <alexm@gnome.org>
*/
/**
* GtkGestureScroll:
*
* `GtkGestureScroll` is a `GtkGesture` implementation for scrolls.
*
* The scroll operation itself can be tracked throughout the
* [signal@Gtk.GestureScroll::scroll-begin],
* [signal@Gtk.GestureScroll::scroll-update] and
* [signal@Gtk.GestureScroll::scroll-end] signals, and the relevant
* coordinates can be extracted through
* [method@Gtk.GestureScroll.get_offset] and
* [method@Gtk.GestureScroll.get_start_point].
*/
#include "config.h"
#include "gtkgestureprivate.h"
#include "gtkgesturescrollprivate.h"
#include "gtkintl.h"
#include "gtkmarshalers.h"
typedef struct _GtkGestureScrollPrivate GtkGestureScrollPrivate;
typedef struct _EventData EventData;
struct _GtkGestureScrollPrivate
{
double start_x;
double start_y;
double last_x;
double last_y;
};
enum {
SCROLL_BEGIN,
SCROLL,
SCROLL_END,
N_SIGNALS
};
static guint signals[N_SIGNALS] = { 0 };
G_DEFINE_TYPE_WITH_PRIVATE (GtkGestureScroll, gtk_gesture_scroll, GTK_TYPE_GESTURE)
static GtkFilterEventStatus
gtk_gesture_scroll_filter_event (GtkEventController *controller,
GdkEvent *event)
{
GdkEventType event_type = gdk_event_get_event_type (event);
if (event_type == GDK_TOUCHPAD_HOLD)
{
int n_fingers = gdk_touchpad_event_get_n_fingers (event);
if (n_fingers == 1 || n_fingers == 2)
return GTK_EVENT_HANDLE;
}
if (event_type == GDK_SCROLL ||
event_type == GDK_GRAB_BROKEN)
return GTK_EVENT_HANDLE;
return GTK_EVENT_SKIP;
}
static void
gtk_gesture_scroll_begin (GtkGesture *gesture,
GdkEventSequence *sequence)
{
GtkGestureScrollPrivate *priv;
// GdkEventSequence *current;
// current = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
priv = gtk_gesture_scroll_get_instance_private (GTK_GESTURE_SCROLL (gesture));
gtk_gesture_get_point (gesture, NULL, &priv->last_x, &priv->last_y);
g_signal_emit (gesture, signals[SCROLL_BEGIN], 0);
}
static void
gtk_gesture_scroll_update (GtkGesture *gesture,
GdkEventSequence *sequence)
{
GtkGestureScrollPrivate *priv;
double x, y;
priv = gtk_gesture_scroll_get_instance_private (GTK_GESTURE_SCROLL (gesture));
gtk_gesture_get_point (gesture, NULL, &x, &y);
g_signal_emit (gesture, signals[SCROLL], 0, x - priv->last_x, y - priv->last_y);
priv->last_x = x;
priv->last_y = y;
}
static void
gtk_gesture_scroll_end (GtkGesture *gesture,
GdkEventSequence *sequence)
{
g_signal_emit (gesture, signals[SCROLL_END], 0);
}
static GObject *
gtk_gesture_scroll_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
GObject *object;
object = G_OBJECT_CLASS (gtk_gesture_scroll_parent_class)->constructor (type,
n_construct_properties,
construct_properties);
g_object_set (object, "n-points", 2, NULL);
return object;
}
static void
gtk_gesture_scroll_class_init (GtkGestureScrollClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkEventControllerClass *event_controller_class = GTK_EVENT_CONTROLLER_CLASS (klass);
GtkGestureClass *gesture_class = GTK_GESTURE_CLASS (klass);
object_class->constructor = gtk_gesture_scroll_constructor;
event_controller_class->filter_event = gtk_gesture_scroll_filter_event;
gesture_class->begin = gtk_gesture_scroll_begin;
gesture_class->update = gtk_gesture_scroll_update;
gesture_class->end = gtk_gesture_scroll_end;
/**
* GtkGestureScroll::scroll-begin:
* @gesture: the object which received the signal
*
* Emitted whenever scrollging starts.
*/
signals[SCROLL_BEGIN] =
g_signal_new (I_("scroll-begin"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
/**
* GtkGestureScroll::scroll:
* @gesture: the object which received the signal
* @dx: X delta
* @dy: Y delta
*
* Signals that the widget should scroll by the
* amount specified by @dx and @dy.
*
* For the representation unit of the deltas, see
* [method@Gtk.EventControllerScroll.get_unit].
*/
signals[SCROLL] =
g_signal_new (I_("scroll"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
_gtk_marshal_VOID__DOUBLE_DOUBLE,
G_TYPE_NONE, 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE);
g_signal_set_va_marshaller (signals[SCROLL],
G_TYPE_FROM_CLASS (klass),
_gtk_marshal_VOID__DOUBLE_DOUBLEv);
/**
* GtkGestureScroll::scroll-end:
* @gesture: the object which received the signal
*
* Emitted whenever the scrollging is finished.
*/
signals[SCROLL_END] =
g_signal_new (I_("scroll-end"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
}
static void
gtk_gesture_scroll_init (GtkGestureScroll *gesture)
{
}
/**
* gtk_gesture_scroll_new:
*
* Returns a newly created `GtkGesture` that recognizes scrolls.
*
* Returns: a newly created `GtkGestureScroll`
**/
GtkGesture *
gtk_gesture_scroll_new (void)
{
return g_object_new (GTK_TYPE_GESTURE_SCROLL,
NULL);
}

46
gtk/gtkgesturescroll.h Normal file
View File

@@ -0,0 +1,46 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 202, Purism SPC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author(s): Alexander Mikhaylenko <alexm@gnome.org>
*/
#pragma once
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#include <gtk/gtkwidget.h>
#include <gtk/gtkgesturesingle.h>
G_BEGIN_DECLS
#define GTK_TYPE_GESTURE_SCROLL (gtk_gesture_scroll_get_type ())
#define GTK_GESTURE_SCROLL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_GESTURE_SCROLL, GtkGestureScroll))
#define GTK_GESTURE_SCROLL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_GESTURE_SCROLL, GtkGestureScrollClass))
#define GTK_IS_GESTURE_SCROLL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_GESTURE_SCROLL))
#define GTK_IS_GESTURE_SCROLL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_GESTURE_SCROLL))
#define GTK_GESTURE_SCROLL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_GESTURE_SCROLL, GtkGestureScrollClass))
typedef struct _GtkGestureScroll GtkGestureScroll;
typedef struct _GtkGestureScrollClass GtkGestureScrollClass;
GDK_AVAILABLE_IN_ALL
GType gtk_gesture_scroll_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GtkGesture * gtk_gesture_scroll_new (void);
G_END_DECLS

View File

@@ -0,0 +1,35 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 202, Purism SPC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author(s): Alexander Mikhaylenko <alexm@gnome.org>
*/
#pragma once
#include "gtkgesturesingleprivate.h"
#include "gtkgesturescroll.h"
struct _GtkGestureScroll
{
GtkGesture parent_instance;
};
struct _GtkGestureScrollClass
{
GtkGestureClass parent_class;
/*< private >*/
gpointer padding[10];
};

View File

@@ -196,6 +196,9 @@ gtk_gesture_single_handle_event (GtkEventController *controller,
}
}
if (button == 0)
return FALSE;
break;
case GDK_TOUCHPAD_HOLD:
if (gdk_touchpad_event_get_n_fingers (event) == 1)
@@ -204,6 +207,7 @@ gtk_gesture_single_handle_event (GtkEventController *controller,
case GDK_TOUCH_CANCEL:
case GDK_GRAB_BROKEN:
case GDK_TOUCHPAD_SWIPE:
case GDK_SCROLL:
return GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_single_parent_class)->handle_event (controller, event, x, y);
break;
default:
@@ -504,3 +508,4 @@ gtk_gesture_single_get_current_sequence (GtkGestureSingle *gesture)
return priv->current_sequence;
}

View File

@@ -58,6 +58,7 @@ struct _EventData
struct _GtkGestureSwipePrivate
{
GArray *events;
gboolean cancelled;
};
enum {
@@ -80,7 +81,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 +97,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);
@@ -149,6 +150,16 @@ gtk_gesture_swipe_append_event (GtkGestureSwipe *swipe,
g_array_append_val (priv->events, new);
}
static void
gtk_gesture_swipe_begin (GtkGesture *gesture,
GdkEventSequence *sequence)
{
GtkGestureSwipe *swipe = GTK_GESTURE_SWIPE (gesture);
GtkGestureSwipePrivate *priv = gtk_gesture_swipe_get_instance_private (swipe);
priv->cancelled = FALSE;
}
static void
gtk_gesture_swipe_update (GtkGesture *gesture,
GdkEventSequence *sequence)
@@ -199,10 +210,13 @@ gtk_gesture_swipe_end (GtkGesture *gesture,
GdkEventSequence *sequence)
{
GtkGestureSwipe *swipe = GTK_GESTURE_SWIPE (gesture);
GtkGestureSwipePrivate *priv;
GtkGestureSwipePrivate *priv = gtk_gesture_swipe_get_instance_private (swipe);
double velocity_x, velocity_y;
GdkEventSequence *seq;
if (priv->cancelled)
return;
seq = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
if (gtk_gesture_get_sequence_state (gesture, seq) == GTK_EVENT_SEQUENCE_DENIED)
@@ -213,7 +227,6 @@ gtk_gesture_swipe_end (GtkGesture *gesture,
gtk_gesture_swipe_append_event (swipe, sequence);
priv = gtk_gesture_swipe_get_instance_private (swipe);
_gtk_gesture_swipe_calculate_velocity (swipe, &velocity_x, &velocity_y);
g_signal_emit (gesture, signals[SWIPE], 0, velocity_x, velocity_y);
@@ -221,6 +234,18 @@ gtk_gesture_swipe_end (GtkGesture *gesture,
g_array_remove_range (priv->events, 0, priv->events->len);
}
static void
gtk_gesture_swipe_cancel (GtkGesture *gesture,
GdkEventSequence *sequence)
{
GtkGestureSwipe *swipe = GTK_GESTURE_SWIPE (gesture);
GtkGestureSwipePrivate *priv = gtk_gesture_swipe_get_instance_private (swipe);
priv->cancelled = TRUE;
GTK_GESTURE_CLASS (gtk_gesture_swipe_parent_class)->cancel (gesture, sequence);
}
static void
gtk_gesture_swipe_class_init (GtkGestureSwipeClass *klass)
{
@@ -232,8 +257,10 @@ gtk_gesture_swipe_class_init (GtkGestureSwipeClass *klass)
event_controller_class->filter_event = gtk_gesture_swipe_filter_event;
gesture_class->begin = gtk_gesture_swipe_begin;
gesture_class->update = gtk_gesture_swipe_update;
gesture_class->end = gtk_gesture_swipe_end;
gesture_class->cancel = gtk_gesture_swipe_cancel;
/**
* GtkGestureSwipe::swipe:

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

@@ -31,11 +31,11 @@
#include "gtkbuildable.h"
#include "gtkdragsourceprivate.h"
#include "gtkeventcontrollermotion.h"
#include "gtkeventcontrollerscroll.h"
#include "gtkeventcontrollerprivate.h"
#include "gtkgesturedrag.h"
#include "gtkgesturelongpress.h"
#include "gtkgesturepan.h"
#include "gtkgesturescroll.h"
#include "gtkgesturesingle.h"
#include "gtkgestureswipe.h"
#include "gtkgestureprivate.h"
@@ -265,7 +265,6 @@ typedef struct
guint auto_added_viewport : 1;
guint propagate_natural_width : 1;
guint propagate_natural_height : 1;
guint smooth_scroll : 1;
int min_content_width;
int min_content_height;
@@ -287,9 +286,12 @@ typedef struct
double drag_start_x;
double drag_start_y;
double last_drag_offset_x;
double last_drag_offset_y;
guint kinetic_scrolling : 1;
guint in_drag : 1;
guint drag_active : 1;
guint deceleration_id;
@@ -402,11 +404,6 @@ static void indicator_start_fade (Indicator *indicator,
static void indicator_set_over (Indicator *indicator,
gboolean over);
static void scrolled_window_scroll (GtkScrolledWindow *scrolled_window,
double delta_x,
double delta_y,
GtkEventControllerScroll *scroll);
static guint signals[LAST_SIGNAL] = {0};
static GParamSpec *properties[NUM_PROPERTIES];
@@ -955,7 +952,8 @@ scrolled_window_drag_begin_cb (GtkScrolledWindow *scrolled_window,
priv->in_drag = FALSE;
priv->drag_start_x = priv->unclamped_hadj_value;
priv->drag_start_y = priv->unclamped_vadj_value;
gtk_scrolled_window_cancel_deceleration (scrolled_window);
priv->last_drag_offset_x = 0;
priv->last_drag_offset_y = 0;
sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
event_widget = gtk_gesture_get_last_target (gesture, sequence);
@@ -993,10 +991,21 @@ scrolled_window_drag_update_cb (GtkScrolledWindow *scrolled_window,
GtkAdjustment *hadjustment;
GtkAdjustment *vadjustment;
double dx, dy;
GdkEventType event_type;
gboolean scroll;
sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
event_type = gdk_event_get_event_type (gtk_event_controller_get_current_event (GTK_EVENT_CONTROLLER (gesture)));
scroll = event_type == GDK_SCROLL;
if (gtk_gesture_get_sequence_state (gesture, sequence) != GTK_EVENT_SEQUENCE_CLAIMED &&
if (!priv->drag_active)
{
gtk_scrolled_window_cancel_deceleration (scrolled_window);
priv->drag_active = TRUE;
}
if (!scroll &&
gtk_gesture_get_sequence_state (gesture, sequence) != GTK_EVENT_SEQUENCE_CLAIMED &&
!gtk_drag_check_threshold_double (GTK_WIDGET (scrolled_window),
0, 0, offset_x, offset_y))
return;
@@ -1007,7 +1016,11 @@ scrolled_window_drag_update_cb (GtkScrolledWindow *scrolled_window,
hadjustment = gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (priv->hscrollbar));
if (hadjustment && may_hscroll (scrolled_window))
{
dx = priv->drag_start_x - offset_x;
if (scroll)
dx = priv->unclamped_hadj_value - offset_x + priv->last_drag_offset_x;
else
dx = priv->drag_start_x - offset_x;
_gtk_scrolled_window_set_adjustment_value (scrolled_window,
hadjustment, dx);
}
@@ -1015,12 +1028,19 @@ scrolled_window_drag_update_cb (GtkScrolledWindow *scrolled_window,
vadjustment = gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (priv->vscrollbar));
if (vadjustment && may_vscroll (scrolled_window))
{
dy = priv->drag_start_y - offset_y;
if (scroll)
dy = priv->unclamped_vadj_value - offset_y + priv->last_drag_offset_y;
else
dy = priv->drag_start_y - offset_y;
_gtk_scrolled_window_set_adjustment_value (scrolled_window,
vadjustment, dy);
}
gtk_scrolled_window_invalidate_overshoot (scrolled_window);
priv->last_drag_offset_x = offset_x;
priv->last_drag_offset_y = offset_y;
}
static void
@@ -1032,6 +1052,8 @@ scrolled_window_drag_end_cb (GtkScrolledWindow *scrolled_window,
if (!priv->in_drag || !gtk_gesture_handles_sequence (gesture, sequence))
gtk_gesture_set_state (gesture, GTK_EVENT_SEQUENCE_DENIED);
priv->drag_active = FALSE;
}
static void
@@ -1068,8 +1090,25 @@ gtk_scrolled_window_decelerate (GtkScrolledWindow *scrolled_window,
static void
scrolled_window_swipe_cb (GtkScrolledWindow *scrolled_window,
double x_velocity,
double y_velocity)
double y_velocity,
GtkGesture *gesture)
{
/* FIXME
double unit_x, unit_y;
GdkEventType event_type;
event_type = gdk_event_get_event_type (gtk_event_controller_get_current_event (GTK_EVENT_CONTROLLER (gesture)));
if (event_type == GDK_SCROLL)
{
unit_x = get_scroll_unit (scrolled_window, GTK_ORIENTATION_HORIZONTAL);
unit_y = get_scroll_unit (scrolled_window, GTK_ORIENTATION_VERTICAL);
}
else
unit_x = unit_y = 1.0;
gtk_scrolled_window_decelerate (scrolled_window, -x_velocity * unit_x, -y_velocity * unit_y);
*/
gtk_scrolled_window_decelerate (scrolled_window, -x_velocity, -y_velocity);
}
@@ -1257,26 +1296,6 @@ get_wheel_detent_scroll_step (GtkScrolledWindow *sw,
return scroll_step;
}
static gboolean
captured_scroll_cb (GtkEventControllerScroll *scroll,
double delta_x,
double delta_y,
GtkScrolledWindow *scrolled_window)
{
GtkScrolledWindowPrivate *priv =
gtk_scrolled_window_get_instance_private (scrolled_window);
gtk_scrolled_window_cancel_deceleration (scrolled_window);
if (priv->smooth_scroll)
{
scrolled_window_scroll (scrolled_window, delta_x, delta_y, scroll);
return GDK_EVENT_STOP;
}
return GDK_EVENT_PROPAGATE;
}
static void
captured_motion (GtkEventController *controller,
double x,
@@ -1345,41 +1364,38 @@ start_scroll_deceleration_cb (gpointer user_data)
}
static void
scroll_controller_scroll_begin (GtkEventControllerScroll *scroll,
GtkScrolledWindow *scrolled_window)
scroll_controller_scroll_begin (GtkGestureScroll *gesture,
GtkScrolledWindow *scrolled_window)
{
GtkScrolledWindowPrivate *priv = gtk_scrolled_window_get_instance_private (scrolled_window);
priv->smooth_scroll = TRUE;
}
static void
stop_kinetic_scrolling_cb (GtkEventControllerScroll *scroll,
GtkScrolledWindow *scrolled_window)
{
GtkScrolledWindowPrivate *priv = gtk_scrolled_window_get_instance_private (scrolled_window);
if (priv->hscrolling)
gtk_kinetic_scrolling_stop (priv->hscrolling);
if (priv->vscrolling)
gtk_kinetic_scrolling_stop (priv->vscrolling);
}
static void
scrolled_window_scroll (GtkScrolledWindow *scrolled_window,
double delta_x,
double delta_y,
GtkEventControllerScroll *scroll)
scroll_controller_scroll (GtkGestureScroll *gesture,
double delta_x,
double delta_y,
GtkScrolledWindow *scrolled_window)
{
GtkScrolledWindowPrivate *priv =
gtk_scrolled_window_get_instance_private (scrolled_window);
gboolean shifted;
GdkModifierType state;
state = gtk_event_controller_get_current_event_state (GTK_EVENT_CONTROLLER (scroll));
if (may_hscroll (scrolled_window) && !may_vscroll (scrolled_window) && ABS (delta_x) > ABS (delta_y)) {
gtk_gesture_set_state (gesture, GTK_EVENT_SEQUENCE_CLAIMED);
// g_print ("claim horz\n");
}
if (may_vscroll (scrolled_window) && !may_hscroll (scrolled_window) && ABS (delta_y) > ABS (delta_x)) {
gtk_gesture_set_state (gesture, GTK_EVENT_SEQUENCE_CLAIMED);
// g_print ("claim vert\n");
}
// g_print ("WTF %p\n", gesture);
state = gtk_event_controller_get_current_event_state (GTK_EVENT_CONTROLLER (gesture));
shifted = (state & GDK_SHIFT_MASK) != 0;
gtk_scrolled_window_cancel_deceleration (scrolled_window);
gtk_scrolled_window_invalidate_overshoot (scrolled_window);
if (shifted)
@@ -1399,13 +1415,13 @@ scrolled_window_scroll (GtkScrolledWindow *scrolled_window,
GdkScrollUnit scroll_unit;
adj = gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (priv->hscrollbar));
scroll_unit = gtk_event_controller_scroll_get_unit (scroll);
/* scroll_unit = gtk_event_controller_wheel_get_unit (controller);
if (scroll_unit == GDK_SCROLL_UNIT_WHEEL)
{
delta_x *= get_wheel_detent_scroll_step (scrolled_window,
GTK_ORIENTATION_HORIZONTAL);
}
} FIXME */
new_value = priv->unclamped_hadj_value + delta_x;
_gtk_scrolled_window_set_adjustment_value (scrolled_window, adj,
@@ -1420,13 +1436,13 @@ scrolled_window_scroll (GtkScrolledWindow *scrolled_window,
GdkScrollUnit scroll_unit;
adj = gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (priv->vscrollbar));
scroll_unit = gtk_event_controller_scroll_get_unit (scroll);
/* scroll_unit = gtk_event_controller_wheel_get_unit (controller);
if (scroll_unit == GDK_SCROLL_UNIT_WHEEL)
{
delta_y *= get_wheel_detent_scroll_step (scrolled_window,
GTK_ORIENTATION_VERTICAL);
}
} FIXME */
new_value = priv->unclamped_vadj_value + delta_y;
_gtk_scrolled_window_set_adjustment_value (scrolled_window, adj,
@@ -1435,8 +1451,7 @@ scrolled_window_scroll (GtkScrolledWindow *scrolled_window,
g_clear_handle_id (&priv->scroll_events_overshoot_id, g_source_remove);
if (!priv->smooth_scroll &&
_gtk_scrolled_window_get_overshoot (scrolled_window, NULL, NULL))
if (_gtk_scrolled_window_get_overshoot (scrolled_window, NULL, NULL))
{
priv->scroll_events_overshoot_id =
g_timeout_add (50, start_scroll_deceleration_cb, scrolled_window);
@@ -1445,66 +1460,11 @@ scrolled_window_scroll (GtkScrolledWindow *scrolled_window,
}
}
static gboolean
scroll_controller_scroll (GtkEventControllerScroll *scroll,
double delta_x,
double delta_y,
GtkScrolledWindow *scrolled_window)
{
GtkScrolledWindowPrivate *priv =
gtk_scrolled_window_get_instance_private (scrolled_window);
if (!priv->smooth_scroll)
scrolled_window_scroll (scrolled_window, delta_x, delta_y, scroll);
return GDK_EVENT_STOP;
}
static void
scroll_controller_scroll_end (GtkEventControllerScroll *scroll,
GtkScrolledWindow *scrolled_window)
scroll_controller_scroll_end (GtkGestureScroll *gesture,
GtkScrolledWindow *scrolled_window)
{
GtkScrolledWindowPrivate *priv = gtk_scrolled_window_get_instance_private (scrolled_window);
priv->smooth_scroll = FALSE;
}
static void
scroll_controller_decelerate (GtkEventControllerScroll *scroll,
double initial_vel_x,
double initial_vel_y,
GtkScrolledWindow *scrolled_window)
{
GdkScrollUnit scroll_unit;
gboolean shifted;
GdkModifierType state;
scroll_unit = gtk_event_controller_scroll_get_unit (scroll);
state = gtk_event_controller_get_current_event_state (GTK_EVENT_CONTROLLER (scroll));
shifted = (state & GDK_SHIFT_MASK) != 0;
if (shifted)
{
double tmp;
tmp = initial_vel_x;
initial_vel_x = initial_vel_y;
initial_vel_y = tmp;
}
if (scroll_unit == GDK_SCROLL_UNIT_WHEEL)
{
initial_vel_x *= get_wheel_detent_scroll_step (scrolled_window,
GTK_ORIENTATION_HORIZONTAL);
initial_vel_y *= get_wheel_detent_scroll_step (scrolled_window,
GTK_ORIENTATION_VERTICAL);
}
gtk_scrolled_window_decelerate (scrolled_window,
initial_vel_x,
initial_vel_y);
}
static void
@@ -2136,8 +2096,7 @@ gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
gtk_css_node_set_state (priv->junction_node, gtk_css_node_get_state (widget_node));
g_object_unref (priv->junction_node);
controller = gtk_event_controller_scroll_new (GTK_EVENT_CONTROLLER_SCROLL_BOTH_AXES |
GTK_EVENT_CONTROLLER_SCROLL_KINETIC);
controller = GTK_EVENT_CONTROLLER (gtk_gesture_scroll_new ());
g_signal_connect (controller, "scroll-begin",
G_CALLBACK (scroll_controller_scroll_begin), scrolled_window);
g_signal_connect (controller, "scroll",
@@ -2146,17 +2105,6 @@ gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
G_CALLBACK (scroll_controller_scroll_end), scrolled_window);
gtk_widget_add_controller (widget, controller);
controller = gtk_event_controller_scroll_new (GTK_EVENT_CONTROLLER_SCROLL_BOTH_AXES |
GTK_EVENT_CONTROLLER_SCROLL_KINETIC);
gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
g_signal_connect (controller, "scroll-begin",
G_CALLBACK (stop_kinetic_scrolling_cb), scrolled_window);
g_signal_connect (controller, "scroll",
G_CALLBACK (captured_scroll_cb), scrolled_window);
g_signal_connect (controller, "decelerate",
G_CALLBACK (scroll_controller_decelerate), scrolled_window);
gtk_widget_add_controller (widget, controller);
controller = gtk_event_controller_motion_new ();
g_signal_connect (controller, "leave",
G_CALLBACK (motion_controller_leave), scrolled_window);

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;

View File

@@ -12934,3 +12934,4 @@ gtk_widget_set_active_state (GtkWidget *widget,
gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_ACTIVE);
}
}

View File

@@ -240,6 +240,7 @@ gtk_public_sources = files([
'gtkeventcontrollerlegacy.c',
'gtkeventcontrollermotion.c',
'gtkeventcontrollerscroll.c',
'gtkeventcontrollerwheel.c',
'gtkexpander.c',
'gtkexpression.c',
'gtkfilechooser.c',
@@ -265,6 +266,7 @@ gtk_public_sources = files([
'gtkgestureclick.c',
'gtkgesturepan.c',
'gtkgesturerotate.c',
'gtkgesturescroll.c',
'gtkgesturesingle.c',
'gtkgesturestylus.c',
'gtkgestureswipe.c',
@@ -529,6 +531,7 @@ gtk_public_headers = files([
'gtkeventcontrollerscroll.h',
'gtkeventcontrollermotion.h',
'gtkeventcontrollerlegacy.h',
'gtkeventcontrollerwheel.h',
'gtkexpander.h',
'gtkexpression.h',
'gtkfilechooser.h',
@@ -553,6 +556,7 @@ gtk_public_headers = files([
'gtkgestureclick.h',
'gtkgesturepan.h',
'gtkgesturerotate.h',
'gtkgesturescroll.h',
'gtkgesturesingle.h',
'gtkgesturestylus.h',
'gtkgestureswipe.h',