summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPovilas Kanapickas <povilas@radix.lt>2021-12-03 02:40:58 +0200
committerPovilas Kanapickas <povilas@radix.lt>2021-12-04 15:55:21 +0000
commitff2de0b87ee9ab64fe4f07d019a4386f802492ca (patch)
tree74792c90dc686ae6b718538611f9d8272f4d38fa
parent04c93b98e9e4593aa2e6701bb08f5e27c3544d8a (diff)
xwayland: Implement support for touchpad gestures
The implementation is relatively straightforward because both wayland and Xorg use libinput semantics for touchpad gestures. Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
-rw-r--r--hw/xwayland/meson.build3
-rw-r--r--hw/xwayland/xwayland-input.c238
-rw-r--r--hw/xwayland/xwayland-input.h7
-rw-r--r--hw/xwayland/xwayland-screen.h1
4 files changed, 249 insertions, 0 deletions
diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build
index 1dea64bff..093d7552b 100644
--- a/hw/xwayland/meson.build
+++ b/hw/xwayland/meson.build
@@ -36,6 +36,7 @@ protodir = protocols_dep.get_pkgconfig_variable('pkgdatadir')
pointer_xml = join_paths(protodir, 'unstable', 'pointer-constraints', 'pointer-constraints-unstable-v1.xml')
relative_xml = join_paths(protodir, 'unstable', 'relative-pointer', 'relative-pointer-unstable-v1.xml')
+gestures_xml = join_paths(protodir, 'unstable', 'pointer-gestures', 'pointer-gestures-unstable-v1.xml')
tablet_xml = join_paths(protodir, 'unstable', 'tablet', 'tablet-unstable-v2.xml')
kbgrab_xml = join_paths(protodir, 'unstable', 'xwayland-keyboard-grab', 'xwayland-keyboard-grab-unstable-v1.xml')
xdg_output_xml = join_paths(protodir, 'unstable', 'xdg-output', 'xdg-output-unstable-v1.xml')
@@ -60,6 +61,7 @@ code = generator(scanner,
)
srcs += client_header.process(relative_xml)
srcs += client_header.process(pointer_xml)
+srcs += client_header.process(gestures_xml)
srcs += client_header.process(tablet_xml)
srcs += client_header.process(kbgrab_xml)
srcs += client_header.process(xdg_output_xml)
@@ -68,6 +70,7 @@ srcs += client_header.process(viewporter_xml)
srcs += client_header.process(xdg_shell_xml)
srcs += code.process(relative_xml)
srcs += code.process(pointer_xml)
+srcs += code.process(gestures_xml)
srcs += code.process(tablet_xml)
srcs += code.process(kbgrab_xml)
srcs += code.process(xdg_output_xml)
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index f5c24048f..db73c3528 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -47,6 +47,7 @@
#include "pointer-constraints-unstable-v1-client-protocol.h"
#include "relative-pointer-unstable-v1-client-protocol.h"
#include "tablet-unstable-v2-client-protocol.h"
+#include "pointer-gestures-unstable-v1-client-protocol.h"
#include "xwayland-keyboard-grab-unstable-v1-client-protocol.h"
struct axis_discrete_pending {
@@ -242,6 +243,51 @@ xwl_pointer_proc_relative(DeviceIntPtr device, int what)
#undef NAXES
}
+static int
+xwl_pointer_proc_pointer_gestures(DeviceIntPtr device, int what)
+{
+#define NTOUCHPOINTS 20
+#define NAXES 2
+ Atom axes_labels[NAXES] = { 0 };
+
+ switch (what) {
+ case DEVICE_INIT:
+ device->public.on = FALSE;
+
+ /* We need to setup a pointer device so that the device is attached to
+ master pointer device.
+ */
+ axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
+ axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
+
+ if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels,
+ GetMotionHistorySize(), Relative))
+ return BadValue;
+
+ InitValuatorAxisStruct(device, 0, axes_labels[0],
+ NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative);
+ InitValuatorAxisStruct(device, 1, axes_labels[1],
+ NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative);
+
+ InitGestureClassDeviceStruct(device, NTOUCHPOINTS);
+ return Success;
+
+ case DEVICE_ON:
+ device->public.on = TRUE;
+ return Success;
+
+ case DEVICE_OFF:
+ case DEVICE_CLOSE:
+ device->public.on = FALSE;
+ return Success;
+ }
+
+ return BadMatch;
+
+#undef NTOUCHPOINTS
+#undef NAXES
+}
+
static void
xwl_keyboard_control(DeviceIntPtr device, KeybdCtrl *ctrl)
{
@@ -756,6 +802,132 @@ static const struct zwp_relative_pointer_v1_listener relative_pointer_listener =
};
static void
+pointer_gesture_swipe_handle_begin(void *data,
+ struct zwp_pointer_gesture_swipe_v1 *swipe,
+ uint32_t serial,
+ uint32_t time,
+ struct wl_surface *surface,
+ uint32_t fingers)
+{
+ struct xwl_seat *xwl_seat = data;
+
+ xwl_seat->pointer_gesture_swipe_fingers = fingers;
+ QueueGestureSwipeEvents(xwl_seat->pointer_gestures,
+ XI_GestureSwipeBegin, fingers, 0, 0.0, 0.0, 0.0, 0.0);
+}
+
+static void
+pointer_gesture_swipe_handle_update(void *data,
+ struct zwp_pointer_gesture_swipe_v1 *swipe,
+ uint32_t time,
+ wl_fixed_t dxf,
+ wl_fixed_t dyf)
+{
+ struct xwl_seat *xwl_seat = data;
+ double dx = wl_fixed_to_double(dxf);
+ double dy = wl_fixed_to_double(dyf);
+
+ QueueGestureSwipeEvents(xwl_seat->pointer_gestures,
+ XI_GestureSwipeUpdate,
+ xwl_seat->pointer_gesture_swipe_fingers,
+ 0,
+ dx, dy,
+ dx, dy);
+}
+
+static void
+pointer_gesture_swipe_handle_end(void *data,
+ struct zwp_pointer_gesture_swipe_v1 *swipe,
+ uint32_t serial,
+ uint32_t time,
+ int32_t cancelled)
+{
+ struct xwl_seat *xwl_seat = data;
+ uint32_t flags = 0;
+
+ if (cancelled)
+ flags |= XIGestureSwipeEventCancelled;
+
+ QueueGestureSwipeEvents(xwl_seat->pointer_gestures,
+ XI_GestureSwipeEnd,
+ xwl_seat->pointer_gesture_swipe_fingers,
+ flags, 0.0, 0.0, 0.0, 0.0);
+}
+
+static const struct zwp_pointer_gesture_swipe_v1_listener pointer_gesture_swipe_listener = {
+ pointer_gesture_swipe_handle_begin,
+ pointer_gesture_swipe_handle_update,
+ pointer_gesture_swipe_handle_end
+};
+
+static void
+pointer_gesture_pinch_handle_begin(void *data,
+ struct zwp_pointer_gesture_pinch_v1 *pinch,
+ uint32_t serial,
+ uint32_t time,
+ struct wl_surface *surface,
+ uint32_t fingers)
+{
+ struct xwl_seat *xwl_seat = data;
+
+ xwl_seat->pointer_gesture_pinch_fingers = fingers;
+ xwl_seat->pointer_gesture_pinch_last_scale = 1.0;
+ QueueGesturePinchEvents(xwl_seat->pointer_gestures,
+ XI_GesturePinchBegin, fingers, 0, 0.0, 0.0, 0.0, 0.0,
+ 1.0, 0.0);
+}
+
+static void
+pointer_gesture_pinch_handle_update(void *data,
+ struct zwp_pointer_gesture_pinch_v1 *pinch,
+ uint32_t time,
+ wl_fixed_t dxf,
+ wl_fixed_t dyf,
+ wl_fixed_t scalef,
+ wl_fixed_t rotation)
+{
+ struct xwl_seat *xwl_seat = data;
+ double dx = wl_fixed_to_double(dxf);
+ double dy = wl_fixed_to_double(dyf);
+ double scale = wl_fixed_to_double(scalef);
+
+ xwl_seat->pointer_gesture_pinch_last_scale = scale;
+ QueueGesturePinchEvents(xwl_seat->pointer_gestures,
+ XI_GesturePinchUpdate,
+ xwl_seat->pointer_gesture_pinch_fingers,
+ 0,
+ dx, dy,
+ dx, dy,
+ scale, wl_fixed_to_double(rotation));
+}
+
+static void
+pointer_gesture_pinch_handle_end(void *data,
+ struct zwp_pointer_gesture_pinch_v1 *pinch,
+ uint32_t serial,
+ uint32_t time,
+ int32_t cancelled)
+{
+ struct xwl_seat *xwl_seat = data;
+ uint32_t flags = 0;
+
+ if (cancelled)
+ flags |= XIGesturePinchEventCancelled;
+
+ QueueGesturePinchEvents(xwl_seat->pointer_gestures,
+ XI_GesturePinchEnd,
+ xwl_seat->pointer_gesture_pinch_fingers,
+ flags, 0.0, 0.0, 0.0, 0.0,
+ xwl_seat->pointer_gesture_pinch_last_scale, 0.0);
+}
+
+static const struct zwp_pointer_gesture_pinch_v1_listener pointer_gesture_pinch_listener = {
+ pointer_gesture_pinch_handle_begin,
+ pointer_gesture_pinch_handle_update,
+ pointer_gesture_pinch_handle_end
+};
+
+static void
keyboard_handle_key(void *data, struct wl_keyboard *keyboard, uint32_t serial,
uint32_t time, uint32_t key, uint32_t state)
{
@@ -1332,6 +1504,58 @@ release_relative_pointer(struct xwl_seat *xwl_seat)
}
static void
+init_pointer_gestures_device(struct xwl_seat *xwl_seat)
+{
+ struct zwp_pointer_gestures_v1 *pointer_gestures =
+ xwl_seat->xwl_screen->pointer_gestures;
+
+ if (pointer_gestures) {
+ xwl_seat->wp_pointer_gesture_swipe =
+ zwp_pointer_gestures_v1_get_swipe_gesture(pointer_gestures,
+ xwl_seat->wl_pointer);
+ zwp_pointer_gesture_swipe_v1_set_user_data(xwl_seat->wp_pointer_gesture_swipe,
+ xwl_seat);
+ zwp_pointer_gesture_swipe_v1_add_listener(xwl_seat->wp_pointer_gesture_swipe,
+ &pointer_gesture_swipe_listener,
+ xwl_seat);
+
+ xwl_seat->wp_pointer_gesture_pinch =
+ zwp_pointer_gestures_v1_get_pinch_gesture(pointer_gestures,
+ xwl_seat->wl_pointer);
+ zwp_pointer_gesture_pinch_v1_set_user_data(xwl_seat->wp_pointer_gesture_pinch,
+ xwl_seat);
+ zwp_pointer_gesture_pinch_v1_add_listener(xwl_seat->wp_pointer_gesture_pinch,
+ &pointer_gesture_pinch_listener,
+ xwl_seat);
+ }
+
+ if (xwl_seat->pointer_gestures == NULL) {
+ xwl_seat->pointer_gestures =
+ add_device(xwl_seat, "xwayland-pointer-gestures",
+ xwl_pointer_proc_pointer_gestures);
+ ActivateDevice(xwl_seat->pointer_gestures, TRUE);
+ }
+ enable_device(xwl_seat, xwl_seat->pointer_gestures);
+}
+
+static void
+release_pointer_gestures_device(struct xwl_seat *xwl_seat)
+{
+ if (xwl_seat->wp_pointer_gesture_swipe) {
+ zwp_pointer_gesture_swipe_v1_destroy(xwl_seat->wp_pointer_gesture_swipe);
+ xwl_seat->wp_pointer_gesture_swipe = NULL;
+ }
+
+ if (xwl_seat->wp_pointer_gesture_pinch) {
+ zwp_pointer_gesture_pinch_v1_destroy(xwl_seat->wp_pointer_gesture_pinch);
+ xwl_seat->wp_pointer_gesture_pinch = NULL;
+ }
+
+ if (xwl_seat->pointer_gestures)
+ disable_device(xwl_seat->pointer_gestures);
+}
+
+static void
init_keyboard(struct xwl_seat *xwl_seat)
{
DeviceIntPtr master;
@@ -1403,9 +1627,11 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
if (caps & WL_SEAT_CAPABILITY_POINTER && xwl_seat->wl_pointer == NULL) {
init_pointer(xwl_seat);
init_relative_pointer(xwl_seat);
+ init_pointer_gestures_device(xwl_seat);
} else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && xwl_seat->wl_pointer) {
release_pointer(xwl_seat);
release_relative_pointer(xwl_seat);
+ release_pointer_gestures_device(xwl_seat);
}
if (caps & WL_SEAT_CAPABILITY_KEYBOARD && xwl_seat->wl_keyboard == NULL) {
@@ -2556,6 +2782,16 @@ init_pointer_constraints(struct xwl_screen *xwl_screen,
}
static void
+init_pointer_gestures(struct xwl_screen *xwl_screen,
+ uint32_t id, uint32_t version)
+{
+ xwl_screen->pointer_gestures =
+ wl_registry_bind(xwl_screen->registry, id,
+ &zwp_pointer_gestures_v1_interface,
+ 1);
+}
+
+static void
init_keyboard_grab(struct xwl_screen *xwl_screen,
uint32_t id, uint32_t version)
{
@@ -2589,6 +2825,8 @@ input_handler(void *data, struct wl_registry *registry, uint32_t id,
init_relative_pointer_manager(xwl_screen, id, version);
} else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0) {
init_pointer_constraints(xwl_screen, id, version);
+ } else if (strcmp(interface, "zwp_pointer_gestures_v1") == 0) {
+ init_pointer_gestures(xwl_screen, id, version);
} else if (strcmp(interface, "zwp_tablet_manager_v2") == 0) {
init_tablet_manager(xwl_screen, id, version);
} else if (strcmp(interface, "zwp_xwayland_keyboard_grab_manager_v1") == 0) {
diff --git a/hw/xwayland/xwayland-input.h b/hw/xwayland/xwayland-input.h
index 0c6591b5e..dbe215bdb 100644
--- a/hw/xwayland/xwayland-input.h
+++ b/hw/xwayland/xwayland-input.h
@@ -56,6 +56,7 @@ struct xwl_cursor {
struct xwl_seat {
DeviceIntPtr pointer;
DeviceIntPtr relative_pointer;
+ DeviceIntPtr pointer_gestures;
DeviceIntPtr keyboard;
DeviceIntPtr touch;
DeviceIntPtr stylus;
@@ -65,6 +66,8 @@ struct xwl_seat {
struct wl_seat *seat;
struct wl_pointer *wl_pointer;
struct zwp_relative_pointer_v1 *wp_relative_pointer;
+ struct zwp_pointer_gesture_swipe_v1 *wp_pointer_gesture_swipe;
+ struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch;
struct wl_keyboard *wl_keyboard;
struct wl_touch *wl_touch;
struct zwp_tablet_seat_v2 *tablet_seat;
@@ -80,6 +83,10 @@ struct xwl_seat {
struct xwl_cursor cursor;
WindowPtr last_xwindow;
+ uint32_t pointer_gesture_swipe_fingers;
+ uint32_t pointer_gesture_pinch_fingers;
+ double pointer_gesture_pinch_last_scale;
+
struct xorg_list touches;
size_t keymap_size;
diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h
index b965dddd7..137e94b55 100644
--- a/hw/xwayland/xwayland-screen.h
+++ b/hw/xwayland/xwayland-screen.h
@@ -82,6 +82,7 @@ struct xwl_screen {
struct xdg_wm_base *xdg_wm_base;
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
struct zwp_pointer_constraints_v1 *pointer_constraints;
+ struct zwp_pointer_gestures_v1 *pointer_gestures;
struct zwp_xwayland_keyboard_grab_manager_v1 *wp_grab;
struct zwp_linux_dmabuf_v1 *dmabuf;
struct zxdg_output_manager_v1 *xdg_output_manager;