wayland: Implement touchpad gesture events

On wayland, the gestures protocol defines a wl_pointer_gestures global
object, that will match in number with wl_seats, swipe and pinch
interfaces can be obtained from it, which events are translated into
GdkEventTouchpadSwipe/Pinch events.
This commit is contained in:
Carlos Garnacho 2015-07-09 19:36:30 +02:00
parent b037d4d628
commit 45d15b302e
3 changed files with 252 additions and 0 deletions

View File

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

View File

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

View File

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