Compare commits
20 Commits
wip/matthi
...
wip/garnac
Author | SHA1 | Date | |
---|---|---|---|
|
6b25d07342 | ||
|
cc963ba9ba | ||
|
548a9d2d69 | ||
|
11cf38df32 | ||
|
b0e2269c36 | ||
|
2fc8ecd13b | ||
|
3f0024f238 | ||
|
b9afafa792 | ||
|
e86f078a54 | ||
|
6f4633846f | ||
|
a02e5575bf | ||
|
8d13607216 | ||
|
89647fd4cd | ||
|
d7aeefb764 | ||
|
61c205d3ae | ||
|
7a288fb3e2 | ||
|
5d6e1e5a49 | ||
|
221d650a03 | ||
|
e753ffd2ff | ||
|
1320c17bdc |
@@ -883,6 +883,8 @@ GdkEventWindowState
|
||||
GdkEventSetting
|
||||
GdkEventOwnerChange
|
||||
GdkEventGrabBroken
|
||||
GdkEventTouchpadSwipe
|
||||
GdkEventTouchpadPinch
|
||||
|
||||
<SUBSECTION>
|
||||
GdkScrollDirection
|
||||
|
@@ -570,6 +570,24 @@ gdk_event_new (GdkEventType type)
|
||||
new_event->crossing.x_root = 0.;
|
||||
new_event->crossing.y_root = 0.;
|
||||
break;
|
||||
case GDK_TOUCHPAD_SWIPE:
|
||||
new_event->touchpad_swipe.x = 0;
|
||||
new_event->touchpad_swipe.y = 0;
|
||||
new_event->touchpad_swipe.dx = 0;
|
||||
new_event->touchpad_swipe.dy = 0;
|
||||
new_event->touchpad_swipe.x_root = 0;
|
||||
new_event->touchpad_swipe.y_root = 0;
|
||||
break;
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
new_event->touchpad_pinch.x = 0;
|
||||
new_event->touchpad_pinch.y = 0;
|
||||
new_event->touchpad_pinch.dx = 0;
|
||||
new_event->touchpad_pinch.dy = 0;
|
||||
new_event->touchpad_pinch.angle_delta = 0;
|
||||
new_event->touchpad_pinch.scale = 0;
|
||||
new_event->touchpad_pinch.x_root = 0;
|
||||
new_event->touchpad_pinch.y_root = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -863,6 +881,10 @@ gdk_event_get_time (const GdkEvent *event)
|
||||
case GDK_TOUCH_END:
|
||||
case GDK_TOUCH_CANCEL:
|
||||
return event->touch.time;
|
||||
case GDK_TOUCHPAD_SWIPE:
|
||||
return event->touchpad_swipe.time;
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
return event->touchpad_pinch.time;
|
||||
case GDK_SCROLL:
|
||||
return event->scroll.time;
|
||||
case GDK_KEY_PRESS:
|
||||
@@ -946,6 +968,12 @@ gdk_event_get_state (const GdkEvent *event,
|
||||
case GDK_TOUCH_CANCEL:
|
||||
*state = event->touch.state;
|
||||
return TRUE;
|
||||
case GDK_TOUCHPAD_SWIPE:
|
||||
*state = event->touchpad_swipe.state;
|
||||
return TRUE;
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
*state = event->touchpad_pinch.state;
|
||||
return TRUE;
|
||||
case GDK_SCROLL:
|
||||
*state = event->scroll.state;
|
||||
return TRUE;
|
||||
@@ -1046,6 +1074,14 @@ gdk_event_get_coords (const GdkEvent *event,
|
||||
x = event->motion.x;
|
||||
y = event->motion.y;
|
||||
break;
|
||||
case GDK_TOUCHPAD_SWIPE:
|
||||
x = event->touchpad_swipe.x;
|
||||
y = event->touchpad_swipe.y;
|
||||
break;
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
x = event->touchpad_pinch.x;
|
||||
y = event->touchpad_pinch.y;
|
||||
break;
|
||||
default:
|
||||
fetched = FALSE;
|
||||
break;
|
||||
@@ -1117,6 +1153,14 @@ gdk_event_get_root_coords (const GdkEvent *event,
|
||||
x = event->dnd.x_root;
|
||||
y = event->dnd.y_root;
|
||||
break;
|
||||
case GDK_TOUCHPAD_SWIPE:
|
||||
x = event->touchpad_swipe.x_root;
|
||||
y = event->touchpad_swipe.y_root;
|
||||
break;
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
x = event->touchpad_pinch.x_root;
|
||||
y = event->touchpad_pinch.y_root;
|
||||
break;
|
||||
default:
|
||||
fetched = FALSE;
|
||||
break;
|
||||
|
127
gdk/gdkevents.h
127
gdk/gdkevents.h
@@ -139,6 +139,8 @@ typedef struct _GdkEventDND GdkEventDND;
|
||||
typedef struct _GdkEventWindowState GdkEventWindowState;
|
||||
typedef struct _GdkEventSetting GdkEventSetting;
|
||||
typedef struct _GdkEventGrabBroken GdkEventGrabBroken;
|
||||
typedef struct _GdkEventTouchpadSwipe GdkEventTouchpadSwipe;
|
||||
typedef struct _GdkEventTouchpadPinch GdkEventTouchpadPinch;
|
||||
|
||||
typedef struct _GdkEventSequence GdkEventSequence;
|
||||
|
||||
@@ -271,6 +273,10 @@ typedef GdkFilterReturn (*GdkFilterFunc) (GdkXEvent *xevent,
|
||||
* was added in 3.4.
|
||||
* @GDK_TOUCH_CANCEL: A touch event sequence has been canceled. This event type
|
||||
* was added in 3.4.
|
||||
* @GDK_TOUCHPAD_SWIPE: A touchpad swipe gesture event, the current state
|
||||
* is determined by its phase field. This event type was added in 3.18.
|
||||
* @GDK_TOUCHPAD_PINCH: A touchpad pinch gesture event, the current state
|
||||
* is determined by its phase field. This event type was added in 3.18.
|
||||
* @GDK_EVENT_LAST: marks the end of the GdkEventType enumeration. Added in 2.18
|
||||
*
|
||||
* Specifies the type of the event.
|
||||
@@ -331,6 +337,8 @@ typedef enum
|
||||
GDK_TOUCH_UPDATE = 38,
|
||||
GDK_TOUCH_END = 39,
|
||||
GDK_TOUCH_CANCEL = 40,
|
||||
GDK_TOUCHPAD_SWIPE = 41,
|
||||
GDK_TOUCHPAD_PINCH = 42,
|
||||
GDK_EVENT_LAST /* helper variable for decls */
|
||||
} GdkEventType;
|
||||
|
||||
@@ -349,6 +357,43 @@ typedef enum
|
||||
GDK_VISIBILITY_FULLY_OBSCURED
|
||||
} GdkVisibilityState;
|
||||
|
||||
/**
|
||||
* GdkTouchpadGesturePhase:
|
||||
* @GDK_TOUCHPAD_GESTURE_PHASE_BEGIN: The gesture has begun.
|
||||
* @GDK_TOUCHPAD_GESTURE_PHASE_UPDATE: The gesture has been updated.
|
||||
* @GDK_TOUCHPAD_GESTURE_PHASE_END: The gesture was finished, changes
|
||||
* should be permanently applied.
|
||||
* @GDK_TOUCHPAD_GESTURE_PHASE_CANCEL: The gesture was cancelled, all
|
||||
* changes should be undone.
|
||||
*
|
||||
* Specifies the current state of a touchpad gesture. All gestures are
|
||||
* guaranteed to begin with an event with phase %GDK_TOUCHPAD_GESTURE_PHASE_BEGIN,
|
||||
* followed by 0 or several events with phase %GDK_TOUCHPAD_GESTURE_PHASE_UPDATE.
|
||||
*
|
||||
* A finished gesture may have 2 possible outcomes, an event with phase
|
||||
* %GDK_TOUCHPAD_GESTURE_PHASE_END will be emitted when the gesture is
|
||||
* considered successful, this should be used as the hint to perform any
|
||||
* permanent changes.
|
||||
|
||||
* Cancelled gestures may be so for a variety of reasons, due to hardware
|
||||
* or the compositor, or due to the gesture recognition layers hinting the
|
||||
* gesture did not finish resolutely (eg. a 3rd finger being added during
|
||||
* a pinch gesture). In these cases, the last event will report the phase
|
||||
* %GDK_TOUCHPAD_GESTURE_PHASE_CANCEL, this should be used as a hint
|
||||
* to undo any visible/permanent changes that were done throughout the
|
||||
* progress of the gesture.
|
||||
*
|
||||
* See also #GdkEventTouchpadSwipe and #GdkEventTouchpadPinch.
|
||||
*
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GDK_TOUCHPAD_GESTURE_PHASE_BEGIN,
|
||||
GDK_TOUCHPAD_GESTURE_PHASE_UPDATE,
|
||||
GDK_TOUCHPAD_GESTURE_PHASE_END,
|
||||
GDK_TOUCHPAD_GESTURE_PHASE_CANCEL
|
||||
} GdkTouchpadGesturePhase;
|
||||
|
||||
/**
|
||||
* GdkScrollDirection:
|
||||
* @GDK_SCROLL_UP: the window is scrolled up.
|
||||
@@ -1113,6 +1158,86 @@ struct _GdkEventDND {
|
||||
gshort x_root, y_root;
|
||||
};
|
||||
|
||||
/**
|
||||
* GdkEventTouchpadSwipe:
|
||||
* @type: the type of the event (%GDK_TOUCHPAD_SWIPE)
|
||||
* @window: the window which received the event
|
||||
* @send_event: %TRUE if the event was sent explicitly
|
||||
* @phase: (type GdkTouchpadGesturePhase): the current phase of the gesture
|
||||
* @n_fingers: The number of fingers triggering the swipe
|
||||
* @time: the time of the event in milliseconds
|
||||
* @x: The X coordinate of the pointer
|
||||
* @y: The Y coordinate of the pointer
|
||||
* @dx: Movement delta in the X axis of the swipe focal point
|
||||
* @dy: Movement delta in the Y axis of the swipe focal point
|
||||
* @x_root: The X coordinate of the pointer, relative to the
|
||||
* root of the screen.
|
||||
* @y_root: The Y coordinate of the pointer, relative to the
|
||||
* root of the screen.
|
||||
* @state: (type GdkModifierType): a bit-mask representing the state of
|
||||
* the modifier keys (e.g. Control, Shift and Alt) and the pointer
|
||||
* buttons. See #GdkModifierType.
|
||||
*
|
||||
* Generated during touchpad swipe gestures.
|
||||
*/
|
||||
struct _GdkEventTouchpadSwipe {
|
||||
GdkEventType type;
|
||||
GdkWindow *window;
|
||||
gint8 send_event;
|
||||
gint8 phase;
|
||||
gint8 n_fingers;
|
||||
guint32 time;
|
||||
gdouble x;
|
||||
gdouble y;
|
||||
gdouble dx;
|
||||
gdouble dy;
|
||||
gdouble x_root, y_root;
|
||||
guint state;
|
||||
};
|
||||
|
||||
/**
|
||||
* GdkEventTouchpadPinch:
|
||||
* @type: the type of the event (%GDK_TOUCHPAD_PINCH)
|
||||
* @window: the window which received the event
|
||||
* @send_event: %TRUE if the event was sent explicitly
|
||||
* @phase: (type GdkTouchpadGesturePhase): the current phase of the gesture
|
||||
* @n_fingers: The number of fingers triggering the pinch
|
||||
* @time: the time of the event in milliseconds
|
||||
* @x: The X coordinate of the pointer
|
||||
* @y: The Y coordinate of the pointer
|
||||
* @dx: Movement delta in the X axis of the swipe focal point
|
||||
* @dy: Movement delta in the Y axis of the swipe focal point
|
||||
* @angle_delta: The angle change in radians, negative angles
|
||||
* denote counter-clockwise movements
|
||||
* @scale: The current scale, relative to that at the time of
|
||||
* the corresponding %GDK_TOUCHPAD_GESTURE_PHASE_BEGIN event
|
||||
* @x_root: The X coordinate of the pointer, relative to the
|
||||
* root of the screen.
|
||||
* @y_root: The Y coordinate of the pointer, relative to the
|
||||
* root of the screen.
|
||||
* @state: (type GdkModifierType): a bit-mask representing the state of
|
||||
* the modifier keys (e.g. Control, Shift and Alt) and the pointer
|
||||
* buttons. See #GdkModifierType.
|
||||
*
|
||||
* Generated during touchpad swipe gestures.
|
||||
*/
|
||||
struct _GdkEventTouchpadPinch {
|
||||
GdkEventType type;
|
||||
GdkWindow *window;
|
||||
gint8 send_event;
|
||||
gint8 phase;
|
||||
gint8 n_fingers;
|
||||
guint32 time;
|
||||
gdouble x;
|
||||
gdouble y;
|
||||
gdouble dx;
|
||||
gdouble dy;
|
||||
gdouble angle_delta;
|
||||
gdouble scale;
|
||||
gdouble x_root, y_root;
|
||||
guint state;
|
||||
};
|
||||
|
||||
/**
|
||||
* GdkEvent:
|
||||
* @type: the #GdkEventType
|
||||
@@ -1189,6 +1314,8 @@ union _GdkEvent
|
||||
GdkEventWindowState window_state;
|
||||
GdkEventSetting setting;
|
||||
GdkEventGrabBroken grab_broken;
|
||||
GdkEventTouchpadSwipe touchpad_swipe;
|
||||
GdkEventTouchpadPinch touchpad_pinch;
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
@@ -440,6 +440,7 @@ typedef enum
|
||||
GDK_SCROLL_MASK = 1 << 21,
|
||||
GDK_TOUCH_MASK = 1 << 22,
|
||||
GDK_SMOOTH_SCROLL_MASK = 1 << 23,
|
||||
GDK_TOUCHPAD_GESTURE_MASK = 1 << 24,
|
||||
GDK_ALL_EVENTS_MASK = 0xFFFFFE
|
||||
} GdkEventMask;
|
||||
|
||||
|
105
gdk/gdkwindow.c
105
gdk/gdkwindow.c
@@ -7565,7 +7565,9 @@ static const guint type_masks[] = {
|
||||
GDK_TOUCH_MASK, /* GDK_TOUCH_BEGIN = 37 */
|
||||
GDK_TOUCH_MASK, /* GDK_TOUCH_UPDATE = 38 */
|
||||
GDK_TOUCH_MASK, /* GDK_TOUCH_END = 39 */
|
||||
GDK_TOUCH_MASK /* GDK_TOUCH_CANCEL = 40 */
|
||||
GDK_TOUCH_MASK, /* GDK_TOUCH_CANCEL = 40 */
|
||||
GDK_TOUCHPAD_GESTURE_MASK, /* GDK_TOUCHPAD_SWIPE = 41 */
|
||||
GDK_TOUCHPAD_GESTURE_MASK, /* GDK_TOUCHPAD_PINCH = 42 */
|
||||
};
|
||||
G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
|
||||
|
||||
@@ -7602,6 +7604,13 @@ is_button_type (GdkEventType type)
|
||||
type == GDK_SCROLL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_gesture_type (GdkEventType type)
|
||||
{
|
||||
return (type == GDK_TOUCHPAD_SWIPE ||
|
||||
type == GDK_TOUCHPAD_PINCH);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_motion_type (GdkEventType type)
|
||||
{
|
||||
@@ -7743,6 +7752,16 @@ _gdk_make_event (GdkWindow *window,
|
||||
event->dnd.time = the_time;
|
||||
break;
|
||||
|
||||
case GDK_TOUCHPAD_SWIPE:
|
||||
event->touchpad_swipe.time = the_time;
|
||||
event->touchpad_swipe.state = the_state;
|
||||
break;
|
||||
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
event->touchpad_pinch.time = the_time;
|
||||
event->touchpad_pinch.state = the_state;
|
||||
break;
|
||||
|
||||
case GDK_FOCUS_CHANGE:
|
||||
case GDK_CONFIGURE:
|
||||
case GDK_MAP:
|
||||
@@ -9269,6 +9288,85 @@ proxy_button_event (GdkEvent *source_event,
|
||||
return TRUE; /* Always unlink original, we want to obey the emulated event mask */
|
||||
}
|
||||
|
||||
static gboolean
|
||||
proxy_gesture_event (GdkEvent *source_event,
|
||||
gulong serial)
|
||||
{
|
||||
GdkWindow *toplevel_window, *pointer_window, *event_win;
|
||||
GdkDevice *device, *source_device;
|
||||
gdouble toplevel_x, toplevel_y;
|
||||
GdkDisplay *display;
|
||||
GdkEventMask evmask;
|
||||
GdkEventType evtype;
|
||||
GdkEvent *event;
|
||||
guint state;
|
||||
|
||||
evtype = source_event->any.type;
|
||||
gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
|
||||
gdk_event_get_state (source_event, &state);
|
||||
device = gdk_event_get_device (source_event);
|
||||
source_device = gdk_event_get_source_device (source_event);
|
||||
display = gdk_window_get_display (source_event->any.window);
|
||||
toplevel_window = convert_native_coords_to_toplevel (source_event->any.window,
|
||||
toplevel_x, toplevel_y,
|
||||
&toplevel_x, &toplevel_y);
|
||||
|
||||
pointer_window = get_pointer_window (display, toplevel_window, device,
|
||||
toplevel_x, toplevel_y,
|
||||
serial);
|
||||
|
||||
event_win = get_event_window (display, device, NULL,
|
||||
pointer_window, evtype, state,
|
||||
&evmask, FALSE, serial);
|
||||
if (!event_win)
|
||||
return TRUE;
|
||||
|
||||
if ((evmask & GDK_TOUCHPAD_GESTURE_MASK) == 0)
|
||||
return TRUE;
|
||||
|
||||
event = _gdk_make_event (event_win, evtype, source_event, FALSE);
|
||||
gdk_event_set_device (event, device);
|
||||
gdk_event_set_source_device (event, source_device);
|
||||
|
||||
switch (evtype)
|
||||
{
|
||||
case GDK_TOUCHPAD_SWIPE:
|
||||
convert_toplevel_coords_to_window (event_win,
|
||||
toplevel_x, toplevel_y,
|
||||
&event->touchpad_swipe.x,
|
||||
&event->touchpad_swipe.y);
|
||||
gdk_event_get_root_coords (source_event,
|
||||
&event->touchpad_swipe.x_root,
|
||||
&event->touchpad_swipe.y_root);
|
||||
event->touchpad_swipe.dx = source_event->touchpad_swipe.dx;
|
||||
event->touchpad_swipe.dy = source_event->touchpad_swipe.dy;
|
||||
event->touchpad_swipe.n_fingers = source_event->touchpad_swipe.n_fingers;
|
||||
event->touchpad_swipe.phase = source_event->touchpad_swipe.phase;
|
||||
break;
|
||||
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
convert_toplevel_coords_to_window (event_win,
|
||||
toplevel_x, toplevel_y,
|
||||
&event->touchpad_pinch.x,
|
||||
&event->touchpad_pinch.y);
|
||||
gdk_event_get_root_coords (source_event,
|
||||
&event->touchpad_pinch.x_root,
|
||||
&event->touchpad_pinch.y_root);
|
||||
event->touchpad_pinch.dx = source_event->touchpad_pinch.dx;
|
||||
event->touchpad_pinch.dy = source_event->touchpad_pinch.dy;
|
||||
event->touchpad_pinch.scale = source_event->touchpad_pinch.scale;
|
||||
event->touchpad_pinch.angle_delta = source_event->touchpad_pinch.angle_delta;
|
||||
event->touchpad_pinch.n_fingers = source_event->touchpad_pinch.n_fingers;
|
||||
event->touchpad_pinch.phase = source_event->touchpad_pinch.phase;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_WINDOW_PRINTING
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
@@ -9417,7 +9515,8 @@ _gdk_windowing_got_event (GdkDisplay *display,
|
||||
}
|
||||
|
||||
if (!(is_button_type (event->type) ||
|
||||
is_motion_type (event->type)) ||
|
||||
is_motion_type (event->type) ||
|
||||
is_gesture_type (event->type)) ||
|
||||
event_window->window_type == GDK_WINDOW_ROOT)
|
||||
goto out;
|
||||
|
||||
@@ -9516,6 +9615,8 @@ _gdk_windowing_got_event (GdkDisplay *display,
|
||||
unlink_event = proxy_pointer_event (display, event, serial);
|
||||
else if (is_button_type (event->type))
|
||||
unlink_event = proxy_button_event (event, serial);
|
||||
else if (is_gesture_type (event->type))
|
||||
unlink_event = proxy_gesture_event (event, serial);
|
||||
|
||||
if ((event->type == GDK_BUTTON_RELEASE ||
|
||||
event->type == GDK_TOUCH_END) &&
|
||||
|
@@ -20,6 +20,8 @@ noinst_LTLIBRARIES = \
|
||||
libgdk-wayland.la
|
||||
|
||||
BUILT_SOURCES = \
|
||||
pointer-gestures-client-protocol.h \
|
||||
pointer-gestures-protocol.c \
|
||||
xdg-shell-client-protocol.h \
|
||||
xdg-shell-protocol.c \
|
||||
gtk-shell-client-protocol.h \
|
||||
@@ -70,6 +72,7 @@ libgdkwaylandinclude_HEADERS = \
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
||||
|
||||
EXTRA_DIST += \
|
||||
protocol/pointer-gestures.xml \
|
||||
protocol/xdg-shell.xml \
|
||||
protocol/gtk-shell.xml
|
||||
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include "gdkkeysyms.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkdevicemanagerprivate.h"
|
||||
#include "pointer-gestures-client-protocol.h"
|
||||
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
@@ -54,6 +55,8 @@ struct _GdkWaylandDeviceData
|
||||
struct wl_pointer *wl_pointer;
|
||||
struct wl_keyboard *wl_keyboard;
|
||||
struct wl_touch *wl_touch;
|
||||
struct _wl_pointer_gesture_swipe *wl_pointer_gesture_swipe;
|
||||
struct _wl_pointer_gesture_pinch *wl_pointer_gesture_pinch;
|
||||
|
||||
GdkDisplay *display;
|
||||
GdkDeviceManager *device_manager;
|
||||
@@ -99,6 +102,10 @@ struct _GdkWaylandDeviceData
|
||||
|
||||
/* Source/dest for non-local dnd */
|
||||
GdkWindow *foreign_dnd_window;
|
||||
|
||||
/* Some tracking on gesture events */
|
||||
guint gesture_n_fingers;
|
||||
gdouble gesture_scale;
|
||||
};
|
||||
|
||||
struct _GdkWaylandDevice
|
||||
@@ -1653,6 +1660,213 @@ touch_handle_cancel (void *data,
|
||||
GDK_NOTE (EVENTS, g_message ("touch cancel"));
|
||||
}
|
||||
|
||||
static void
|
||||
emit_gesture_swipe_event (GdkWaylandDeviceData *device,
|
||||
GdkTouchpadGesturePhase phase,
|
||||
guint32 _time,
|
||||
guint32 n_fingers,
|
||||
gdouble dx,
|
||||
gdouble dy)
|
||||
{
|
||||
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (device->display);
|
||||
GdkEvent *event;
|
||||
|
||||
if (!device->pointer_focus)
|
||||
return;
|
||||
|
||||
device->time = _time;
|
||||
|
||||
event = gdk_event_new (GDK_TOUCHPAD_SWIPE);
|
||||
event->touchpad_swipe.phase = phase;
|
||||
event->touchpad_swipe.window = g_object_ref (device->pointer_focus);
|
||||
gdk_event_set_device (event, device->master_pointer);
|
||||
gdk_event_set_source_device (event, device->pointer);
|
||||
event->touchpad_swipe.time = _time;
|
||||
event->touchpad_swipe.state = device->button_modifiers | device->key_modifiers;
|
||||
gdk_event_set_screen (event, display->screen);
|
||||
event->touchpad_swipe.dx = dx;
|
||||
event->touchpad_swipe.dy = dy;
|
||||
event->touchpad_swipe.n_fingers = n_fingers;
|
||||
|
||||
get_coordinates (device,
|
||||
&event->touchpad_swipe.x,
|
||||
&event->touchpad_swipe.y,
|
||||
&event->touchpad_swipe.x_root,
|
||||
&event->touchpad_swipe.y_root);
|
||||
|
||||
GDK_NOTE (EVENTS,
|
||||
g_message ("swipe event %d, coords: %f %f, device %p state %d",
|
||||
event->type, event->touchpad_swipe.x,
|
||||
event->touchpad_swipe.y, device,
|
||||
event->touchpad_swipe.state));
|
||||
|
||||
_gdk_wayland_display_deliver_event (device->display, event);
|
||||
}
|
||||
|
||||
static void
|
||||
gesture_swipe_begin (void *data,
|
||||
struct _wl_pointer_gesture_swipe *swipe,
|
||||
uint32_t serial,
|
||||
uint32_t time,
|
||||
struct wl_surface *surface,
|
||||
uint32_t fingers)
|
||||
{
|
||||
GdkWaylandDeviceData *device = data;
|
||||
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (device->display);
|
||||
|
||||
_gdk_wayland_display_update_serial (display, serial);
|
||||
|
||||
emit_gesture_swipe_event (device,
|
||||
GDK_TOUCHPAD_GESTURE_PHASE_BEGIN,
|
||||
time, fingers, 0, 0);
|
||||
device->gesture_n_fingers = fingers;
|
||||
}
|
||||
|
||||
static void
|
||||
gesture_swipe_update (void *data,
|
||||
struct _wl_pointer_gesture_swipe *swipe,
|
||||
uint32_t time,
|
||||
wl_fixed_t dx,
|
||||
wl_fixed_t dy)
|
||||
{
|
||||
GdkWaylandDeviceData *device = data;
|
||||
|
||||
emit_gesture_swipe_event (device,
|
||||
GDK_TOUCHPAD_GESTURE_PHASE_UPDATE,
|
||||
time,
|
||||
device->gesture_n_fingers,
|
||||
wl_fixed_to_double (dx),
|
||||
wl_fixed_to_double (dy));
|
||||
}
|
||||
|
||||
static void
|
||||
gesture_swipe_end (void *data,
|
||||
struct _wl_pointer_gesture_swipe *swipe,
|
||||
uint32_t serial,
|
||||
uint32_t time,
|
||||
int32_t cancelled)
|
||||
{
|
||||
GdkWaylandDeviceData *device = data;
|
||||
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (device->display);
|
||||
GdkTouchpadGesturePhase phase;
|
||||
|
||||
_gdk_wayland_display_update_serial (display, serial);
|
||||
|
||||
phase = (cancelled) ?
|
||||
GDK_TOUCHPAD_GESTURE_PHASE_CANCEL :
|
||||
GDK_TOUCHPAD_GESTURE_PHASE_END;
|
||||
|
||||
emit_gesture_swipe_event (device, phase, time,
|
||||
device->gesture_n_fingers, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_gesture_pinch_event (GdkWaylandDeviceData *device,
|
||||
GdkTouchpadGesturePhase phase,
|
||||
guint32 _time,
|
||||
guint n_fingers,
|
||||
gdouble dx,
|
||||
gdouble dy,
|
||||
gdouble scale,
|
||||
gdouble angle_delta)
|
||||
{
|
||||
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (device->display);
|
||||
GdkEvent *event;
|
||||
|
||||
if (!device->pointer_focus)
|
||||
return;
|
||||
|
||||
device->time = _time;
|
||||
|
||||
event = gdk_event_new (GDK_TOUCHPAD_PINCH);
|
||||
event->touchpad_pinch.phase = phase;
|
||||
event->touchpad_pinch.window = g_object_ref (device->pointer_focus);
|
||||
gdk_event_set_device (event, device->master_pointer);
|
||||
gdk_event_set_source_device (event, device->pointer);
|
||||
event->touchpad_pinch.time = _time;
|
||||
event->touchpad_pinch.state = device->button_modifiers | device->key_modifiers;
|
||||
gdk_event_set_screen (event, display->screen);
|
||||
event->touchpad_pinch.dx = dx;
|
||||
event->touchpad_pinch.dy = dy;
|
||||
event->touchpad_pinch.scale = scale;
|
||||
event->touchpad_pinch.angle_delta = angle_delta * G_PI / 180;
|
||||
event->touchpad_pinch.n_fingers = n_fingers;
|
||||
|
||||
get_coordinates (device,
|
||||
&event->touchpad_pinch.x,
|
||||
&event->touchpad_pinch.y,
|
||||
&event->touchpad_pinch.x_root,
|
||||
&event->touchpad_pinch.y_root);
|
||||
|
||||
GDK_NOTE (EVENTS,
|
||||
g_message ("pinch event %d, coords: %f %f, device %p state %d",
|
||||
event->type, event->touchpad_pinch.x,
|
||||
event->touchpad_pinch.y, device,
|
||||
event->touchpad_pinch.state));
|
||||
|
||||
_gdk_wayland_display_deliver_event (device->display, event);
|
||||
}
|
||||
|
||||
static void
|
||||
gesture_pinch_begin (void *data,
|
||||
struct _wl_pointer_gesture_pinch *pinch,
|
||||
uint32_t serial,
|
||||
uint32_t time,
|
||||
struct wl_surface *surface,
|
||||
uint32_t fingers)
|
||||
{
|
||||
GdkWaylandDeviceData *device = data;
|
||||
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (device->display);
|
||||
|
||||
_gdk_wayland_display_update_serial (display, serial);
|
||||
emit_gesture_pinch_event (device,
|
||||
GDK_TOUCHPAD_GESTURE_PHASE_BEGIN,
|
||||
time, fingers, 0, 0, 1, 0);
|
||||
device->gesture_n_fingers = fingers;
|
||||
}
|
||||
|
||||
static void
|
||||
gesture_pinch_update (void *data,
|
||||
struct _wl_pointer_gesture_pinch *pinch,
|
||||
uint32_t time,
|
||||
wl_fixed_t dx,
|
||||
wl_fixed_t dy,
|
||||
wl_fixed_t scale,
|
||||
wl_fixed_t rotation)
|
||||
{
|
||||
GdkWaylandDeviceData *device = data;
|
||||
|
||||
emit_gesture_pinch_event (device,
|
||||
GDK_TOUCHPAD_GESTURE_PHASE_UPDATE, time,
|
||||
device->gesture_n_fingers,
|
||||
wl_fixed_to_double (dx),
|
||||
wl_fixed_to_double (dy),
|
||||
wl_fixed_to_double (scale),
|
||||
wl_fixed_to_double (rotation));
|
||||
}
|
||||
|
||||
static void
|
||||
gesture_pinch_end (void *data,
|
||||
struct _wl_pointer_gesture_pinch *pinch,
|
||||
uint32_t serial,
|
||||
uint32_t time,
|
||||
int32_t cancelled)
|
||||
{
|
||||
GdkWaylandDeviceData *device = data;
|
||||
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (device->display);
|
||||
GdkTouchpadGesturePhase phase;
|
||||
|
||||
_gdk_wayland_display_update_serial (display, serial);
|
||||
|
||||
phase = (cancelled) ?
|
||||
GDK_TOUCHPAD_GESTURE_PHASE_CANCEL :
|
||||
GDK_TOUCHPAD_GESTURE_PHASE_END;
|
||||
|
||||
emit_gesture_pinch_event (device, phase,
|
||||
time, device->gesture_n_fingers,
|
||||
0, 0, 1, 0);
|
||||
}
|
||||
|
||||
static const struct wl_pointer_listener pointer_listener = {
|
||||
pointer_handle_enter,
|
||||
pointer_handle_leave,
|
||||
@@ -1678,6 +1892,18 @@ static const struct wl_touch_listener touch_listener = {
|
||||
touch_handle_cancel
|
||||
};
|
||||
|
||||
static const struct _wl_pointer_gesture_swipe_listener gesture_swipe_listener = {
|
||||
gesture_swipe_begin,
|
||||
gesture_swipe_update,
|
||||
gesture_swipe_end
|
||||
};
|
||||
|
||||
static const struct _wl_pointer_gesture_pinch_listener gesture_pinch_listener = {
|
||||
gesture_pinch_begin,
|
||||
gesture_pinch_update,
|
||||
gesture_pinch_end
|
||||
};
|
||||
|
||||
static void
|
||||
seat_handle_capabilities (void *data,
|
||||
struct wl_seat *seat,
|
||||
@@ -1685,6 +1911,7 @@ seat_handle_capabilities (void *data,
|
||||
{
|
||||
GdkWaylandDeviceData *device = data;
|
||||
GdkWaylandDeviceManager *device_manager = GDK_WAYLAND_DEVICE_MANAGER (device->device_manager);
|
||||
GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (device->display);
|
||||
|
||||
GDK_NOTE (MISC,
|
||||
g_message ("seat %p with %s%s%s", seat,
|
||||
@@ -1715,6 +1942,24 @@ seat_handle_capabilities (void *data,
|
||||
|
||||
device->drop_context = _gdk_wayland_drop_context_new (device->master_pointer,
|
||||
device->data_device);
|
||||
if (wayland_display->pointer_gestures)
|
||||
{
|
||||
device->wl_pointer_gesture_swipe =
|
||||
_wl_pointer_gestures_get_swipe_gesture (wayland_display->pointer_gestures,
|
||||
device->wl_pointer);
|
||||
_wl_pointer_gesture_swipe_set_user_data (device->wl_pointer_gesture_swipe,
|
||||
device);
|
||||
_wl_pointer_gesture_swipe_add_listener (device->wl_pointer_gesture_swipe,
|
||||
&gesture_swipe_listener, device);
|
||||
|
||||
device->wl_pointer_gesture_pinch =
|
||||
_wl_pointer_gestures_get_pinch_gesture (wayland_display->pointer_gestures,
|
||||
device->wl_pointer);
|
||||
_wl_pointer_gesture_pinch_set_user_data (device->wl_pointer_gesture_pinch,
|
||||
device);
|
||||
_wl_pointer_gesture_pinch_add_listener (device->wl_pointer_gesture_pinch,
|
||||
&gesture_pinch_listener, device);
|
||||
}
|
||||
|
||||
g_signal_emit_by_name (device_manager, "device-added", device->pointer);
|
||||
}
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#include "gdkkeysprivate.h"
|
||||
#include "gdkprivate-wayland.h"
|
||||
#include "gdkglcontext-wayland.h"
|
||||
#include "pointer-gestures-client-protocol.h"
|
||||
|
||||
/**
|
||||
* SECTION:wayland_interaction
|
||||
@@ -357,6 +358,11 @@ gdk_registry_handle_global (void *data,
|
||||
display_wayland->subcompositor =
|
||||
wl_registry_bind (display_wayland->wl_registry, id, &wl_subcompositor_interface, 1);
|
||||
}
|
||||
else if (strcmp (interface, "_wl_pointer_gestures") == 0)
|
||||
{
|
||||
display_wayland->pointer_gestures =
|
||||
wl_registry_bind (display_wayland->wl_registry, id, &_wl_pointer_gestures_interface, 1);
|
||||
}
|
||||
else
|
||||
handled = FALSE;
|
||||
|
||||
|
@@ -71,6 +71,7 @@ struct _GdkWaylandDisplay
|
||||
struct wl_input_device *input_device;
|
||||
struct wl_data_device_manager *data_device_manager;
|
||||
struct wl_subcompositor *subcompositor;
|
||||
struct _wl_pointer_gestures *pointer_gestures;
|
||||
|
||||
GList *async_roundtrips;
|
||||
|
||||
|
172
gdk/wayland/protocol/pointer-gestures.xml
Normal file
172
gdk/wayland/protocol/pointer-gestures.xml
Normal file
@@ -0,0 +1,172 @@
|
||||
<protocol name="pointer_gestures">
|
||||
<interface name="_wl_pointer_gestures" version="1">
|
||||
<description summary="touchpad gestures">
|
||||
A global interface to provide semantic touchpad gestures for a given
|
||||
pointer.
|
||||
|
||||
Two gestures are currently supported: swipe and zoom/rotate.
|
||||
All gestures follow a three-stage cycle: begin, update, end and
|
||||
are identified by a unique id.
|
||||
|
||||
Warning! The protocol described in this file is experimental. Each
|
||||
version of this protocol should be considered incompatible with any
|
||||
other version, and a client binding to a version different to the one
|
||||
advertised will be terminated. Once the protocol is declared stable,
|
||||
compatibility is guaranteed, the '_' prefix will be removed from the
|
||||
name and the version will be reset to 1.
|
||||
</description>
|
||||
|
||||
<request name="get_swipe_gesture">
|
||||
<description summary="get swipe gesture">
|
||||
Create a swipe gesture object. See the
|
||||
wl_pointer_gesture_swipe interface for details.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="_wl_pointer_gesture_swipe"/>
|
||||
<arg name="pointer" type="object" interface="wl_pointer"/>
|
||||
</request>
|
||||
|
||||
<request name="get_pinch_gesture">
|
||||
<description summary="get pinch gesture">
|
||||
Create a pinch gesture object. See the
|
||||
wl_pointer_gesture_pinch interface for details.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="_wl_pointer_gesture_pinch"/>
|
||||
<arg name="pointer" type="object" interface="wl_pointer"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="_wl_pointer_gesture_swipe" version="1">
|
||||
<description summary="a swipe gesture object">
|
||||
A swipe gesture object notifies a client about a multi-finger swipe
|
||||
gesture detected on an indirect input device such as a touchpad.
|
||||
The gesture is usually initiated by multiple fingers moving in the
|
||||
same direction but once initiated the direction may change.
|
||||
The precise conditions of when such a gesture is detected are
|
||||
implementation-dependent.
|
||||
|
||||
A gesture consists of three stages: begin, update (optional) and end.
|
||||
There cannot be multiple simultaneous pinch or swipe gestures on a
|
||||
same pointer/seat, how compositors prevent these situations is
|
||||
implementation-dependent.
|
||||
|
||||
A gesture may be cancelled by the compositor or the hardware.
|
||||
Clients should not consider performing permanent or irreversible
|
||||
actions until the end of a gesture has been received.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the pointer swipe gesture object"/>
|
||||
</request>
|
||||
|
||||
<event name="begin">
|
||||
<description summary="multi-finger swipe begin">
|
||||
This event is sent when a multi-finger swipe gesture is detected
|
||||
on the device.
|
||||
</description>
|
||||
<arg name="serial" type="uint"/>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
<arg name="fingers" type="uint" summary="number of fingers"/>
|
||||
</event>
|
||||
|
||||
<event name="update">
|
||||
<description summary="multi-finger swipe motion">
|
||||
This event is sent when a multi-finger swipe gesture changes the
|
||||
position of the logical center.
|
||||
|
||||
The dx and dy coordinates are relative coordinates of the logical
|
||||
center of the gesture compared to the previous event.
|
||||
</description>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="dx" type="fixed" summary="delta x coordinate in surface coordinate space"/>
|
||||
<arg name="dy" type="fixed" summary="delta y coordinate in surface coordinate space"/>
|
||||
</event>
|
||||
|
||||
<event name="end">
|
||||
<description summary="multi-finger swipe end">
|
||||
This event is sent when a multi-finger swipe gesture ceases to
|
||||
be valid. This may happen when one or more finger is lifted or
|
||||
the gesture is cancelled.
|
||||
|
||||
When a gesture is cancelled, the client should undo state changes
|
||||
caused by this gesture. What causes a gesture to be cancelled is
|
||||
implementation-dependent.
|
||||
</description>
|
||||
<arg name="serial" type="uint"/>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="cancelled" type="int" summary="1 if the gesture was cancelled, 0 otherwise"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="_wl_pointer_gesture_pinch" version="1">
|
||||
<description summary="a pinch gesture object">
|
||||
A pinch gesture object notifies a client about a multi-finger pinch
|
||||
gesture detected on an indirect input device such as a touchpad.
|
||||
The gesture is usually initiated by multiple fingers moving towards
|
||||
each other or away from each other, or by two or more fingers rotating
|
||||
around a logical center of gravity. The precise conditions of when
|
||||
such a gesture is detected are implementation-dependent.
|
||||
|
||||
A gesture consists of three stages: begin, update (optional) and end.
|
||||
There cannot be multiple simultaneous pinch or swipe gestures on a
|
||||
same pointer/seat, how compositors prevent these situations is
|
||||
implementation-dependent.
|
||||
|
||||
A gesture may be cancelled by the compositor or the hardware.
|
||||
Clients should not consider performing permanent or irreversible
|
||||
actions until the end of a gesture has been received.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the pinch gesture object"/>
|
||||
</request>
|
||||
|
||||
<event name="begin">
|
||||
<description summary="multi-finger pinch begin">
|
||||
This event is sent when a multi-finger pinch gesture is detected
|
||||
on the device.
|
||||
</description>
|
||||
<arg name="serial" type="uint"/>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
<arg name="fingers" type="uint" summary="number of fingers"/>
|
||||
</event>
|
||||
|
||||
<event name="update">
|
||||
<description summary="multi-finger pinch motion">
|
||||
This event is sent when a multi-finger pinch gesture changes the
|
||||
position of the logical center, the rotation or the relative scale.
|
||||
|
||||
The dx and dy coordinates are relative coordinates in the
|
||||
surface coordinate space of the logical center of the gesture.
|
||||
|
||||
The scale factor is an absolute scale compared to the
|
||||
pointer_gesture_pinch.begin event, e.g. a scale of 2 means the fingers
|
||||
are now twice as far apart as on pointer_gesture_pinch.begin.
|
||||
|
||||
The rotation is the relative angle in degrees clockwise compared to the previous
|
||||
pointer_gesture_pinch.begin or pointer_gesture_pinch.update event.
|
||||
</description>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="dx" type="fixed" summary="delta x coordinate in surface coordinate space"/>
|
||||
<arg name="dy" type="fixed" summary="delta y coordinate in surface coordinate space"/>
|
||||
<arg name="scale" type="fixed" summary="scale relative to the initial finger position"/>
|
||||
<arg name="rotation" type="fixed" summary="angle in degrees cw relative to the previous event"/>
|
||||
</event>
|
||||
|
||||
<event name="end">
|
||||
<description summary="multi-finger pinch end">
|
||||
This event is sent when a multi-finger pinch gesture ceases to
|
||||
be valid. This may happen when one or more finger is lifted or
|
||||
the gesture is cancelled.
|
||||
|
||||
When a gesture is cancelled, the client should undo state changes
|
||||
caused by this gesture. What causes a gesture to be cancelled is
|
||||
implementation-dependent.
|
||||
</description>
|
||||
<arg name="serial" type="uint"/>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="cancelled" type="int" summary="1 if the gesture was cancelled, 0 otherwise"/>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
@@ -145,6 +145,7 @@ gtk_event_controller_class_init (GtkEventControllerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
klass->filter_event = gtk_event_controller_handle_event_default;
|
||||
klass->handle_event = gtk_event_controller_handle_event_default;
|
||||
|
||||
object_class->set_property = gtk_event_controller_set_property;
|
||||
@@ -218,6 +219,9 @@ gtk_event_controller_handle_event (GtkEventController *controller,
|
||||
|
||||
controller_class = GTK_EVENT_CONTROLLER_GET_CLASS (controller);
|
||||
|
||||
if (controller_class->filter_event (controller, event))
|
||||
return retval;
|
||||
|
||||
if (controller_class->handle_event)
|
||||
{
|
||||
g_object_ref (controller);
|
||||
|
@@ -36,6 +36,9 @@ struct _GtkEventControllerClass
|
||||
void (* reset) (GtkEventController *controller);
|
||||
|
||||
/*<private>*/
|
||||
|
||||
gboolean (* filter_event) (GtkEventController *controller,
|
||||
const GdkEvent *event);
|
||||
gpointer padding[10];
|
||||
};
|
||||
|
||||
|
248
gtk/gtkgesture.c
248
gtk/gtkgesture.c
@@ -104,6 +104,15 @@
|
||||
*
|
||||
* Sequence states can't be changed freely, see gtk_gesture_set_sequence_state()
|
||||
* to know about the possible lifetimes of a #GdkEventSequence.
|
||||
*
|
||||
* ## Touchpad gestures
|
||||
*
|
||||
* On the platforms that support it, #GtkGesture will handle transparently
|
||||
* touchpad gesture events. The only precautions users of #GtkGesture should do
|
||||
* to enable this support are:
|
||||
* - Enabling %GDK_TOUCHPAD_GESTURE_MASK on their #GdkWindows
|
||||
* - If the gesture has %GTK_PHASE_NONE, ensuring events of type
|
||||
* %GDK_TOUCHPAD_SWIPE and %GDK_TOUCHPAD_PINCH are handled by the #GtkGesture
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -138,6 +147,11 @@ struct _PointData
|
||||
GdkEvent *event;
|
||||
gdouble widget_x;
|
||||
gdouble widget_y;
|
||||
|
||||
/* Acummulators for touchpad events */
|
||||
gdouble accum_dx;
|
||||
gdouble accum_dy;
|
||||
|
||||
guint press_handled : 1;
|
||||
guint state : 2;
|
||||
};
|
||||
@@ -152,12 +166,16 @@ struct _GtkGesturePrivate
|
||||
GList *group_link;
|
||||
guint n_points;
|
||||
guint recognized : 1;
|
||||
guint touchpad : 1;
|
||||
};
|
||||
|
||||
static guint signals[N_SIGNALS] = { 0 };
|
||||
|
||||
#define BUTTONS_MASK (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)
|
||||
|
||||
#define EVENT_IS_TOUCHPAD_GESTURE(e) ((e)->type == GDK_TOUCHPAD_SWIPE || \
|
||||
(e)->type == GDK_TOUCHPAD_PINCH)
|
||||
|
||||
GList * _gtk_gesture_get_group_link (GtkGesture *gesture);
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkGesture, gtk_gesture, GTK_TYPE_EVENT_CONTROLLER)
|
||||
@@ -220,7 +238,44 @@ gtk_gesture_finalize (GObject *object)
|
||||
}
|
||||
|
||||
static guint
|
||||
_gtk_gesture_effective_n_points (GtkGesture *gesture)
|
||||
_gtk_gesture_get_n_touchpad_points (GtkGesture *gesture,
|
||||
gboolean only_active)
|
||||
{
|
||||
GtkGesturePrivate *priv;
|
||||
PointData *data;
|
||||
|
||||
priv = gtk_gesture_get_instance_private (gesture);
|
||||
|
||||
if (!priv->touchpad)
|
||||
return 0;
|
||||
|
||||
data = g_hash_table_lookup (priv->points, NULL);
|
||||
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
if (only_active &&
|
||||
(data->state == GTK_EVENT_SEQUENCE_DENIED ||
|
||||
(data->event->type == GDK_TOUCHPAD_SWIPE &&
|
||||
data->event->touchpad_swipe.phase == GDK_TOUCHPAD_GESTURE_PHASE_END) ||
|
||||
(data->event->type == GDK_TOUCHPAD_PINCH &&
|
||||
data->event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_END)))
|
||||
return 0;
|
||||
|
||||
switch (data->event->type)
|
||||
{
|
||||
case GDK_TOUCHPAD_SWIPE:
|
||||
return data->event->touchpad_swipe.n_fingers;
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
return data->event->touchpad_pinch.n_fingers;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static guint
|
||||
_gtk_gesture_get_n_touch_points (GtkGesture *gesture,
|
||||
gboolean only_active)
|
||||
{
|
||||
GtkGesturePrivate *priv;
|
||||
GHashTableIter iter;
|
||||
@@ -232,9 +287,10 @@ _gtk_gesture_effective_n_points (GtkGesture *gesture)
|
||||
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &data))
|
||||
{
|
||||
if (data->state == GTK_EVENT_SEQUENCE_DENIED ||
|
||||
data->event->type == GDK_TOUCH_END ||
|
||||
data->event->type == GDK_BUTTON_RELEASE)
|
||||
if (only_active &&
|
||||
(data->state == GTK_EVENT_SEQUENCE_DENIED ||
|
||||
data->event->type == GDK_TOUCH_END ||
|
||||
data->event->type == GDK_BUTTON_RELEASE))
|
||||
continue;
|
||||
|
||||
n_points++;
|
||||
@@ -243,6 +299,20 @@ _gtk_gesture_effective_n_points (GtkGesture *gesture)
|
||||
return n_points;
|
||||
}
|
||||
|
||||
static guint
|
||||
_gtk_gesture_get_n_physical_points (GtkGesture *gesture,
|
||||
gboolean only_active)
|
||||
{
|
||||
GtkGesturePrivate *priv;
|
||||
|
||||
priv = gtk_gesture_get_instance_private (gesture);
|
||||
|
||||
if (priv->touchpad)
|
||||
return _gtk_gesture_get_n_touchpad_points (gesture, only_active);
|
||||
else
|
||||
return _gtk_gesture_get_n_touch_points (gesture, only_active);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_gesture_check_impl (GtkGesture *gesture)
|
||||
{
|
||||
@@ -250,7 +320,7 @@ gtk_gesture_check_impl (GtkGesture *gesture)
|
||||
guint n_points;
|
||||
|
||||
priv = gtk_gesture_get_instance_private (gesture);
|
||||
n_points = _gtk_gesture_effective_n_points (gesture);
|
||||
n_points = _gtk_gesture_get_n_physical_points (gesture, TRUE);
|
||||
|
||||
return n_points == priv->n_points;
|
||||
}
|
||||
@@ -294,12 +364,13 @@ static gboolean
|
||||
_gtk_gesture_has_matching_touchpoints (GtkGesture *gesture)
|
||||
{
|
||||
GtkGesturePrivate *priv = gtk_gesture_get_instance_private (gesture);
|
||||
guint current_n_points;
|
||||
guint active_n_points, current_n_points;
|
||||
|
||||
current_n_points = _gtk_gesture_effective_n_points (gesture);
|
||||
current_n_points = _gtk_gesture_get_n_physical_points (gesture, FALSE);
|
||||
active_n_points = _gtk_gesture_get_n_physical_points (gesture, TRUE);
|
||||
|
||||
return (current_n_points == priv->n_points &&
|
||||
g_hash_table_size (priv->points) == priv->n_points);
|
||||
return (active_n_points == priv->n_points &&
|
||||
current_n_points == priv->n_points);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -343,6 +414,55 @@ _find_widget_window (GtkGesture *gesture,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_update_touchpad_deltas (PointData *data)
|
||||
{
|
||||
GdkEvent *event = data->event;
|
||||
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
if (event->type == GDK_TOUCHPAD_SWIPE)
|
||||
{
|
||||
if (event->touchpad_swipe.phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN)
|
||||
data->accum_dx = data->accum_dy = 0;
|
||||
else if (event->touchpad_swipe.phase == GDK_TOUCHPAD_GESTURE_PHASE_UPDATE)
|
||||
{
|
||||
data->accum_dx += event->touchpad_swipe.dx;
|
||||
data->accum_dy += event->touchpad_swipe.dy;
|
||||
}
|
||||
}
|
||||
else if (event->type == GDK_TOUCHPAD_PINCH)
|
||||
{
|
||||
if (event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN)
|
||||
data->accum_dx = data->accum_dy = 0;
|
||||
else if (event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_UPDATE)
|
||||
{
|
||||
data->accum_dx += event->touchpad_pinch.dx;
|
||||
data->accum_dy += event->touchpad_pinch.dy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_get_event_coordinates (PointData *data,
|
||||
gdouble *x,
|
||||
gdouble *y)
|
||||
{
|
||||
gdouble event_x, event_y;
|
||||
|
||||
g_assert (data->event != NULL);
|
||||
|
||||
gdk_event_get_coords (data->event, &event_x, &event_y);
|
||||
event_x += data->accum_dx;
|
||||
event_y += data->accum_dy;
|
||||
|
||||
if (x)
|
||||
*x = event_x;
|
||||
if (y)
|
||||
*y = event_y;
|
||||
}
|
||||
|
||||
static void
|
||||
_update_widget_coordinates (GtkGesture *gesture,
|
||||
PointData *data)
|
||||
@@ -356,7 +476,7 @@ _update_widget_coordinates (GtkGesture *gesture,
|
||||
event_widget = gtk_get_event_widget (data->event);
|
||||
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
|
||||
event_widget_window = gtk_widget_get_window (event_widget);
|
||||
gdk_event_get_coords (data->event, &event_x, &event_y);
|
||||
_get_event_coordinates (data, &event_x, &event_y);
|
||||
window = data->event->any.window;
|
||||
|
||||
while (window && window != event_widget_window)
|
||||
@@ -415,7 +535,7 @@ _gtk_gesture_update_point (GtkGesture *gesture,
|
||||
GdkWindow *widget_window;
|
||||
GtkGesturePrivate *priv;
|
||||
GdkDevice *device;
|
||||
gboolean existed;
|
||||
gboolean existed, touchpad;
|
||||
PointData *data;
|
||||
|
||||
if (!gdk_event_get_coords (event, NULL, NULL))
|
||||
@@ -432,6 +552,8 @@ _gtk_gesture_update_point (GtkGesture *gesture,
|
||||
if (!widget_window)
|
||||
return FALSE;
|
||||
|
||||
touchpad = EVENT_IS_TOUCHPAD_GESTURE (event);
|
||||
|
||||
if (add)
|
||||
{
|
||||
/* If the event happens with the wrong device, or
|
||||
@@ -443,6 +565,12 @@ _gtk_gesture_update_point (GtkGesture *gesture,
|
||||
return FALSE;
|
||||
if (priv->user_window && priv->user_window != widget_window)
|
||||
return FALSE;
|
||||
|
||||
/* Make touchpad and touchscreen gestures mutually exclusive */
|
||||
if (touchpad && g_hash_table_size (priv->points) > 0)
|
||||
return FALSE;
|
||||
else if (!touchpad && priv->touchpad)
|
||||
return FALSE;
|
||||
}
|
||||
else if (!priv->device || !priv->window)
|
||||
return FALSE;
|
||||
@@ -461,6 +589,7 @@ _gtk_gesture_update_point (GtkGesture *gesture,
|
||||
{
|
||||
priv->window = widget_window;
|
||||
priv->device = device;
|
||||
priv->touchpad = touchpad;
|
||||
}
|
||||
|
||||
data = g_new0 (PointData, 1);
|
||||
@@ -474,13 +603,14 @@ _gtk_gesture_update_point (GtkGesture *gesture,
|
||||
gdk_event_free (data->event);
|
||||
|
||||
data->event = gdk_event_copy (event);
|
||||
_update_touchpad_deltas (data);
|
||||
_update_widget_coordinates (gesture, data);
|
||||
|
||||
/* Deny the sequence right away if the expected
|
||||
* number of points is exceeded, so this sequence
|
||||
* can be tracked with gtk_gesture_handles_sequence().
|
||||
*/
|
||||
if (!existed && g_hash_table_size (priv->points) > priv->n_points)
|
||||
if (!existed && _gtk_gesture_get_n_physical_points (gesture, FALSE) > priv->n_points)
|
||||
gtk_gesture_set_sequence_state (gesture, sequence,
|
||||
GTK_EVENT_SEQUENCE_DENIED);
|
||||
|
||||
@@ -498,6 +628,7 @@ _gtk_gesture_check_empty (GtkGesture *gesture)
|
||||
{
|
||||
priv->window = NULL;
|
||||
priv->device = NULL;
|
||||
priv->touchpad = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -561,6 +692,18 @@ gesture_within_window (GtkGesture *gesture,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_gesture_filter_event (GtkEventController *controller,
|
||||
const 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.
|
||||
*/
|
||||
return EVENT_IS_TOUCHPAD_GESTURE (event);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_gesture_handle_event (GtkEventController *controller,
|
||||
const GdkEvent *event)
|
||||
@@ -583,10 +726,13 @@ gtk_gesture_handle_event (GtkEventController *controller,
|
||||
if (gtk_gesture_get_sequence_state (gesture, sequence) != GTK_EVENT_SEQUENCE_DENIED)
|
||||
priv->last_sequence = sequence;
|
||||
|
||||
switch (event->type)
|
||||
if (event->type == GDK_BUTTON_PRESS ||
|
||||
event->type == GDK_TOUCH_BEGIN ||
|
||||
(event->type == GDK_TOUCHPAD_SWIPE &&
|
||||
event->touchpad_swipe.phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN) ||
|
||||
(event->type == GDK_TOUCHPAD_PINCH &&
|
||||
event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN))
|
||||
{
|
||||
case GDK_BUTTON_PRESS:
|
||||
case GDK_TOUCH_BEGIN:
|
||||
if (_gtk_gesture_update_point (gesture, event, TRUE))
|
||||
{
|
||||
gboolean triggered_recognition;
|
||||
@@ -613,10 +759,14 @@ gtk_gesture_handle_event (GtkEventController *controller,
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case GDK_BUTTON_RELEASE:
|
||||
case GDK_TOUCH_END:
|
||||
}
|
||||
else if (event->type == GDK_BUTTON_RELEASE ||
|
||||
event->type == GDK_TOUCH_END ||
|
||||
(event->type == GDK_TOUCHPAD_SWIPE &&
|
||||
event->touchpad_swipe.phase == GDK_TOUCHPAD_GESTURE_PHASE_END) ||
|
||||
(event->type == GDK_TOUCHPAD_PINCH &&
|
||||
event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_END))
|
||||
{
|
||||
if (_gtk_gesture_update_point (gesture, event, FALSE))
|
||||
{
|
||||
if (was_recognized &&
|
||||
@@ -625,30 +775,50 @@ gtk_gesture_handle_event (GtkEventController *controller,
|
||||
|
||||
_gtk_gesture_remove_point (gesture, event);
|
||||
}
|
||||
break;
|
||||
case GDK_MOTION_NOTIFY:
|
||||
if ((event->motion.state & BUTTONS_MASK) == 0)
|
||||
break;
|
||||
}
|
||||
else if (event->type == GDK_MOTION_NOTIFY ||
|
||||
event->type == GDK_TOUCH_UPDATE ||
|
||||
(event->type == GDK_TOUCHPAD_SWIPE &&
|
||||
event->touchpad_swipe.phase == GDK_TOUCHPAD_GESTURE_PHASE_UPDATE) ||
|
||||
(event->type == GDK_TOUCHPAD_PINCH &&
|
||||
event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_UPDATE))
|
||||
{
|
||||
if (event->type == GDK_MOTION_NOTIFY)
|
||||
{
|
||||
if ((event->motion.state & BUTTONS_MASK) == 0)
|
||||
return FALSE;
|
||||
|
||||
if (event->motion.is_hint)
|
||||
gdk_event_request_motions (&event->motion);
|
||||
if (event->motion.is_hint)
|
||||
gdk_event_request_motions (&event->motion);
|
||||
}
|
||||
|
||||
/* Fall through */
|
||||
case GDK_TOUCH_UPDATE:
|
||||
if (_gtk_gesture_update_point (gesture, event, FALSE) &&
|
||||
_gtk_gesture_check_recognized (gesture, sequence))
|
||||
g_signal_emit (gesture, signals[UPDATE], 0, sequence);
|
||||
break;
|
||||
case GDK_TOUCH_CANCEL:
|
||||
_gtk_gesture_cancel_sequence (gesture, sequence);
|
||||
break;
|
||||
case GDK_GRAB_BROKEN:
|
||||
}
|
||||
else if (event->type == GDK_TOUCH_CANCEL)
|
||||
{
|
||||
if (!priv->touchpad)
|
||||
_gtk_gesture_cancel_sequence (gesture, sequence);
|
||||
}
|
||||
else if ((event->type == GDK_TOUCHPAD_SWIPE &&
|
||||
event->touchpad_swipe.phase == GDK_TOUCHPAD_GESTURE_PHASE_CANCEL) ||
|
||||
(event->type == GDK_TOUCHPAD_PINCH &&
|
||||
event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_CANCEL))
|
||||
{
|
||||
if (priv->touchpad)
|
||||
_gtk_gesture_cancel_sequence (gesture, sequence);
|
||||
}
|
||||
else if (event->type == GDK_GRAB_BROKEN)
|
||||
{
|
||||
if (!event->grab_broken.grab_window ||
|
||||
!gesture_within_window (gesture, event->grab_broken.grab_window))
|
||||
_gtk_gesture_cancel_all (gesture);
|
||||
|
||||
return FALSE;
|
||||
default:
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unhandled event */
|
||||
return FALSE;
|
||||
}
|
||||
@@ -675,6 +845,7 @@ gtk_gesture_class_init (GtkGestureClass *klass)
|
||||
object_class->set_property = gtk_gesture_set_property;
|
||||
object_class->finalize = gtk_gesture_finalize;
|
||||
|
||||
controller_class->filter_event = gtk_gesture_filter_event;
|
||||
controller_class->handle_event = gtk_gesture_handle_event;
|
||||
controller_class->reset = gtk_gesture_reset;
|
||||
|
||||
@@ -827,7 +998,8 @@ gtk_gesture_init (GtkGesture *gesture)
|
||||
priv->points = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) g_free);
|
||||
gtk_event_controller_set_event_mask (GTK_EVENT_CONTROLLER (gesture),
|
||||
GDK_TOUCH_MASK);
|
||||
GDK_TOUCH_MASK |
|
||||
GDK_TOUCHPAD_GESTURE_MASK);
|
||||
|
||||
priv->group_link = g_list_prepend (NULL, gesture);
|
||||
}
|
||||
@@ -1180,6 +1352,12 @@ _gtk_gesture_get_last_update_time (GtkGesture *gesture,
|
||||
* box containing all active touches. Otherwise, %FALSE will be
|
||||
* returned.
|
||||
*
|
||||
* Note: This function will yield unexpected results on touchpad
|
||||
* gestures. Since there is no correlation between physical and
|
||||
* pixel distances, these will look as if constrained in an
|
||||
* infinitely small area, @rect width and height will thus be 0
|
||||
* regardless of the number of touchpoints.
|
||||
*
|
||||
* Returns: %TRUE if there are active touches, %FALSE otherwise
|
||||
*
|
||||
* Since: 3.14
|
||||
@@ -1283,7 +1461,7 @@ gtk_gesture_is_active (GtkGesture *gesture)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_GESTURE (gesture), FALSE);
|
||||
|
||||
return _gtk_gesture_effective_n_points (gesture) != 0;
|
||||
return _gtk_gesture_get_n_physical_points (gesture, TRUE) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -56,6 +56,26 @@ static guint signals[N_SIGNALS] = { 0 };
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkGestureDrag, gtk_gesture_drag, GTK_TYPE_GESTURE_SINGLE)
|
||||
|
||||
static gboolean
|
||||
gtk_gesture_drag_filter_event (GtkEventController *controller,
|
||||
const GdkEvent *event)
|
||||
{
|
||||
/* Let touchpad swipe events go through, only if they match n-points */
|
||||
if (event->type == GDK_TOUCHPAD_SWIPE)
|
||||
{
|
||||
guint n_points;
|
||||
|
||||
g_object_get (G_OBJECT (controller), "n-points", &n_points, NULL);
|
||||
|
||||
if (event->touchpad_swipe.n_fingers == n_points)
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_drag_parent_class)->filter_event (controller, event);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_gesture_drag_begin (GtkGesture *gesture,
|
||||
GdkEventSequence *sequence)
|
||||
@@ -110,6 +130,9 @@ static void
|
||||
gtk_gesture_drag_class_init (GtkGestureDragClass *klass)
|
||||
{
|
||||
GtkGestureClass *gesture_class = GTK_GESTURE_CLASS (klass);
|
||||
GtkEventControllerClass *event_controller_class = GTK_EVENT_CONTROLLER_CLASS (klass);
|
||||
|
||||
event_controller_class->filter_event = gtk_gesture_drag_filter_event;
|
||||
|
||||
gesture_class->begin = gtk_gesture_drag_begin;
|
||||
gesture_class->update = gtk_gesture_drag_update;
|
||||
|
@@ -45,6 +45,7 @@ enum {
|
||||
struct _GtkGestureRotatePrivate
|
||||
{
|
||||
gdouble initial_angle;
|
||||
gdouble accum_touchpad_angle;
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
@@ -75,33 +76,52 @@ static gboolean
|
||||
_gtk_gesture_rotate_get_angle (GtkGestureRotate *rotate,
|
||||
gdouble *angle)
|
||||
{
|
||||
GtkGestureRotatePrivate *priv;
|
||||
const GdkEvent *last_event;
|
||||
gdouble x1, y1, x2, y2;
|
||||
GtkGesture *gesture;
|
||||
gdouble dx, dy;
|
||||
GList *sequences;
|
||||
|
||||
gesture = GTK_GESTURE (rotate);
|
||||
priv = gtk_gesture_rotate_get_instance_private (rotate);
|
||||
|
||||
if (!gtk_gesture_is_recognized (gesture))
|
||||
return FALSE;
|
||||
|
||||
sequences = gtk_gesture_get_sequences (gesture);
|
||||
g_assert (sequences && sequences->next);
|
||||
if (!sequences)
|
||||
return FALSE;
|
||||
|
||||
gtk_gesture_get_point (gesture, sequences->data, &x1, &y1);
|
||||
gtk_gesture_get_point (gesture, sequences->next->data, &x2, &y2);
|
||||
g_list_free (sequences);
|
||||
last_event = gtk_gesture_get_last_event (gesture, sequences->data);
|
||||
|
||||
dx = x1 - x2;
|
||||
dy = y1 - y2;
|
||||
if (last_event->type == GDK_TOUCHPAD_PINCH &&
|
||||
(last_event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN ||
|
||||
last_event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_UPDATE ||
|
||||
last_event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_END))
|
||||
{
|
||||
*angle = priv->accum_touchpad_angle;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sequences->next)
|
||||
return FALSE;
|
||||
|
||||
*angle = atan2 (dx, dy);
|
||||
gtk_gesture_get_point (gesture, sequences->data, &x1, &y1);
|
||||
gtk_gesture_get_point (gesture, sequences->next->data, &x2, &y2);
|
||||
g_list_free (sequences);
|
||||
|
||||
/* Invert angle */
|
||||
*angle = (2 * G_PI) - *angle;
|
||||
dx = x1 - x2;
|
||||
dy = y1 - y2;
|
||||
|
||||
/* And constraint it to 0°-360° */
|
||||
*angle = fmod (*angle, 2 * G_PI);
|
||||
*angle = atan2 (dx, dy);
|
||||
|
||||
/* Invert angle */
|
||||
*angle = (2 * G_PI) - *angle;
|
||||
|
||||
/* And constraint it to 0°-360° */
|
||||
*angle = fmod (*angle, 2 * G_PI);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -143,14 +163,55 @@ gtk_gesture_rotate_update (GtkGesture *gesture,
|
||||
_gtk_gesture_rotate_check_emit (GTK_GESTURE_ROTATE (gesture));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_gesture_rotate_filter_event (GtkEventController *controller,
|
||||
const GdkEvent *event)
|
||||
{
|
||||
/* Let 2-finger touchpad pinch events go through */
|
||||
if (event->type == GDK_TOUCHPAD_PINCH)
|
||||
{
|
||||
if (event->touchpad_pinch.n_fingers == 2)
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_rotate_parent_class)->filter_event (controller, event);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_gesture_rotate_handle_event (GtkEventController *controller,
|
||||
const GdkEvent *event)
|
||||
{
|
||||
GtkGestureRotate *rotate = GTK_GESTURE_ROTATE (controller);
|
||||
GtkGestureRotatePrivate *priv;
|
||||
|
||||
priv = gtk_gesture_rotate_get_instance_private (rotate);
|
||||
|
||||
if (event->type == GDK_TOUCHPAD_PINCH)
|
||||
{
|
||||
if (event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN ||
|
||||
event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_END)
|
||||
priv->accum_touchpad_angle = 0;
|
||||
else if (event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_UPDATE)
|
||||
priv->accum_touchpad_angle += event->touchpad_pinch.angle_delta;
|
||||
}
|
||||
|
||||
return GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_rotate_parent_class)->handle_event (controller, event);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_gesture_rotate_class_init (GtkGestureRotateClass *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_rotate_constructor;
|
||||
|
||||
event_controller_class->filter_event = gtk_gesture_rotate_filter_event;
|
||||
event_controller_class->handle_event = gtk_gesture_rotate_handle_event;
|
||||
|
||||
gesture_class->begin = gtk_gesture_rotate_begin;
|
||||
gesture_class->update = gtk_gesture_rotate_update;
|
||||
|
||||
|
@@ -77,6 +77,26 @@ gtk_gesture_swipe_finalize (GObject *object)
|
||||
G_OBJECT_CLASS (gtk_gesture_swipe_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_gesture_swipe_filter_event (GtkEventController *controller,
|
||||
const GdkEvent *event)
|
||||
{
|
||||
/* Let touchpad swipe events go through, only if they match n-points */
|
||||
if (event->type == GDK_TOUCHPAD_SWIPE)
|
||||
{
|
||||
guint n_points;
|
||||
|
||||
g_object_get (G_OBJECT (controller), "n-points", &n_points, NULL);
|
||||
|
||||
if (event->touchpad_swipe.n_fingers == n_points)
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_swipe_parent_class)->filter_event (controller, event);
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_gesture_swipe_clear_backlog (GtkGestureSwipe *gesture,
|
||||
guint32 evtime)
|
||||
@@ -188,10 +208,13 @@ static void
|
||||
gtk_gesture_swipe_class_init (GtkGestureSwipeClass *klass)
|
||||
{
|
||||
GtkGestureClass *gesture_class = GTK_GESTURE_CLASS (klass);
|
||||
GtkEventControllerClass *event_controller_class = GTK_EVENT_CONTROLLER_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_gesture_swipe_finalize;
|
||||
|
||||
event_controller_class->filter_event = gtk_gesture_swipe_filter_event;
|
||||
|
||||
gesture_class->update = gtk_gesture_swipe_update;
|
||||
gesture_class->end = gtk_gesture_swipe_end;
|
||||
|
||||
|
@@ -75,6 +75,7 @@ static gboolean
|
||||
_gtk_gesture_zoom_get_distance (GtkGestureZoom *zoom,
|
||||
gdouble *distance)
|
||||
{
|
||||
const GdkEvent *last_event;
|
||||
gdouble x1, y1, x2, y2;
|
||||
GtkGesture *gesture;
|
||||
GList *sequences;
|
||||
@@ -86,15 +87,32 @@ _gtk_gesture_zoom_get_distance (GtkGestureZoom *zoom,
|
||||
return FALSE;
|
||||
|
||||
sequences = gtk_gesture_get_sequences (gesture);
|
||||
g_assert (sequences && sequences->next);
|
||||
if (!sequences)
|
||||
return FALSE;
|
||||
|
||||
gtk_gesture_get_point (gesture, sequences->data, &x1, &y1);
|
||||
gtk_gesture_get_point (gesture, sequences->next->data, &x2, &y2);
|
||||
g_list_free (sequences);
|
||||
last_event = gtk_gesture_get_last_event (gesture, sequences->data);
|
||||
|
||||
dx = x1 - x2;
|
||||
dy = y1 - y2;;
|
||||
*distance = sqrt ((dx * dx) + (dy * dy));
|
||||
if (last_event->type == GDK_TOUCHPAD_PINCH &&
|
||||
(last_event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN ||
|
||||
last_event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_UPDATE ||
|
||||
last_event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_END))
|
||||
{
|
||||
/* Touchpad pinch */
|
||||
*distance = last_event->touchpad_pinch.scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sequences->next)
|
||||
return FALSE;
|
||||
|
||||
gtk_gesture_get_point (gesture, sequences->data, &x1, &y1);
|
||||
gtk_gesture_get_point (gesture, sequences->next->data, &x2, &y2);
|
||||
g_list_free (sequences);
|
||||
|
||||
dx = x1 - x2;
|
||||
dy = y1 - y2;;
|
||||
*distance = sqrt ((dx * dx) + (dy * dy));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -119,6 +137,22 @@ _gtk_gesture_zoom_check_emit (GtkGestureZoom *gesture)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_gesture_zoom_filter_event (GtkEventController *controller,
|
||||
const GdkEvent *event)
|
||||
{
|
||||
/* Let 2-finger touchpad pinch events go through */
|
||||
if (event->type == GDK_TOUCHPAD_PINCH)
|
||||
{
|
||||
if (event->touchpad_pinch.n_fingers == 2)
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_zoom_parent_class)->filter_event (controller, event);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_gesture_zoom_begin (GtkGesture *gesture,
|
||||
GdkEventSequence *sequence)
|
||||
@@ -141,10 +175,13 @@ static void
|
||||
gtk_gesture_zoom_class_init (GtkGestureZoomClass *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_zoom_constructor;
|
||||
|
||||
event_controller_class->filter_event = gtk_gesture_zoom_filter_event;
|
||||
|
||||
gesture_class->begin = gtk_gesture_zoom_begin;
|
||||
gesture_class->update = gtk_gesture_zoom_update;
|
||||
|
||||
|
@@ -1411,6 +1411,18 @@ rewrite_event_for_window (GdkEvent *event,
|
||||
new_window,
|
||||
&event->touch.x, &event->touch.y);
|
||||
break;
|
||||
case GDK_TOUCHPAD_SWIPE:
|
||||
rewrite_events_translate (event->any.window,
|
||||
new_window,
|
||||
&event->touchpad_swipe.x,
|
||||
&event->touchpad_swipe.y);
|
||||
break;
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
rewrite_events_translate (event->any.window,
|
||||
new_window,
|
||||
&event->touchpad_pinch.x,
|
||||
&event->touchpad_pinch.y);
|
||||
break;
|
||||
case GDK_KEY_PRESS:
|
||||
case GDK_KEY_RELEASE:
|
||||
case GDK_PROXIMITY_IN:
|
||||
@@ -1460,6 +1472,8 @@ rewrite_event_for_grabs (GdkEvent *event)
|
||||
case GDK_TOUCH_UPDATE:
|
||||
case GDK_TOUCH_END:
|
||||
case GDK_TOUCH_CANCEL:
|
||||
case GDK_TOUCHPAD_SWIPE:
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
display = gdk_window_get_display (event->any.window);
|
||||
device = gdk_event_get_device (event);
|
||||
|
||||
@@ -1819,6 +1833,8 @@ gtk_main_do_event (GdkEvent *event)
|
||||
case GDK_TOUCH_UPDATE:
|
||||
case GDK_TOUCH_END:
|
||||
case GDK_TOUCH_CANCEL:
|
||||
case GDK_TOUCHPAD_SWIPE:
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
if (!_gtk_propagate_captured_event (grab_widget, event, topmost_widget))
|
||||
gtk_propagate_event (grab_widget, event);
|
||||
break;
|
||||
|
@@ -7717,6 +7717,10 @@ gtk_widget_event_internal (GtkWidget *widget,
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case GDK_TOUCHPAD_SWIPE:
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
return_val |= _gtk_widget_run_controllers (widget, event, GTK_PHASE_BUBBLE);
|
||||
/* Fall through */
|
||||
case GDK_EXPOSE:
|
||||
case GDK_NOTHING:
|
||||
signal_num = -1;
|
||||
|
Reference in New Issue
Block a user