diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c index fbf3178b9..9d4d36ec3 100644 --- a/clutter/clutter/clutter-actor.c +++ b/clutter/clutter/clutter-actor.c @@ -13994,6 +13994,7 @@ clutter_actor_event (ClutterActor *actor, break; case CLUTTER_TOUCHPAD_PINCH: case CLUTTER_TOUCHPAD_SWIPE: + case CLUTTER_TOUCHPAD_HOLD: detail = quark_touchpad; break; case CLUTTER_PROXIMITY_IN: diff --git a/clutter/clutter/clutter-enums.h b/clutter/clutter/clutter-enums.h index a12e7ec63..92bac41fd 100644 --- a/clutter/clutter/clutter-enums.h +++ b/clutter/clutter/clutter-enums.h @@ -896,6 +896,11 @@ typedef enum /*< flags prefix=CLUTTER_EVENT >*/ * determined by its phase field; event added in 1.24 * @CLUTTER_TOUCHPAD_SWIPE: A swipe gesture event, the current state is * determined by its phase field; event added in 1.24 + * @CLUTTER_TOUCHPAD_HOLD: A hold gesture event, the current state is + * determined by its phase field. A hold gesture starts when the user places a + * finger on the touchpad and ends when all fingers are lifted. It is + * cancelled when the finger(s) move past a certain threshold. + * Event added in 6.5 * @CLUTTER_PROXIMITY_IN: A tool entered in proximity to a tablet; * event added in 1.28 * @CLUTTER_PROXIMITY_OUT: A tool left from the proximity area of a tablet; @@ -928,6 +933,7 @@ typedef enum /*< prefix=CLUTTER >*/ CLUTTER_TOUCH_CANCEL, CLUTTER_TOUCHPAD_PINCH, CLUTTER_TOUCHPAD_SWIPE, + CLUTTER_TOUCHPAD_HOLD, CLUTTER_PROXIMITY_IN, CLUTTER_PROXIMITY_OUT, CLUTTER_PAD_BUTTON_PRESS, diff --git a/clutter/clutter/clutter-event.c b/clutter/clutter/clutter-event.c index 43ca0e5de..ebc7e8f2f 100644 --- a/clutter/clutter/clutter-event.c +++ b/clutter/clutter/clutter-event.c @@ -457,6 +457,11 @@ clutter_event_get_position (const ClutterEvent *event, graphene_point_init (position, event->touchpad_swipe.x, event->touchpad_swipe.y); break; + + case CLUTTER_TOUCHPAD_HOLD: + graphene_point_init (position, event->touchpad_hold.x, + event->touchpad_hold.y); + break; } } @@ -540,6 +545,11 @@ clutter_event_set_coords (ClutterEvent *event, event->touchpad_swipe.x = x; event->touchpad_swipe.y = y; break; + + case CLUTTER_TOUCHPAD_HOLD: + event->touchpad_hold.x = x; + event->touchpad_hold.y = y; + break; } } @@ -1154,6 +1164,7 @@ clutter_event_set_device (ClutterEvent *event, case CLUTTER_TOUCHPAD_PINCH: case CLUTTER_TOUCHPAD_SWIPE: + case CLUTTER_TOUCHPAD_HOLD: /* Rely on priv data for these */ break; @@ -1259,6 +1270,7 @@ clutter_event_get_device (const ClutterEvent *event) case CLUTTER_TOUCHPAD_PINCH: case CLUTTER_TOUCHPAD_SWIPE: + case CLUTTER_TOUCHPAD_HOLD: /* Rely on priv data for these */ break; @@ -1814,6 +1826,7 @@ clutter_event_get_axes (const ClutterEvent *event, case CLUTTER_TOUCHPAD_PINCH: case CLUTTER_TOUCHPAD_SWIPE: + case CLUTTER_TOUCHPAD_HOLD: case CLUTTER_PAD_BUTTON_PRESS: case CLUTTER_PAD_BUTTON_RELEASE: case CLUTTER_PAD_STRIP: @@ -2073,12 +2086,15 @@ clutter_event_get_touchpad_gesture_finger_count (const ClutterEvent *event) { g_return_val_if_fail (event != NULL, 0); g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_SWIPE || - event->type == CLUTTER_TOUCHPAD_PINCH, 0); + event->type == CLUTTER_TOUCHPAD_PINCH || + event->type == CLUTTER_TOUCHPAD_HOLD, 0); if (event->type == CLUTTER_TOUCHPAD_SWIPE) return event->touchpad_swipe.n_fingers; else if (event->type == CLUTTER_TOUCHPAD_PINCH) return event->touchpad_pinch.n_fingers; + else if (event->type == CLUTTER_TOUCHPAD_HOLD) + return event->touchpad_hold.n_fingers; return 0; } @@ -2137,12 +2153,15 @@ clutter_event_get_gesture_phase (const ClutterEvent *event) { g_return_val_if_fail (event != NULL, 0); g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH || - event->type == CLUTTER_TOUCHPAD_SWIPE, 0); + event->type == CLUTTER_TOUCHPAD_SWIPE || + event->type == CLUTTER_TOUCHPAD_HOLD, 0); if (event->type == CLUTTER_TOUCHPAD_PINCH) return event->touchpad_pinch.phase; else if (event->type == CLUTTER_TOUCHPAD_SWIPE) return event->touchpad_swipe.phase; + else if (event->type == CLUTTER_TOUCHPAD_HOLD) + return event->touchpad_hold.phase; /* Shouldn't ever happen */ return CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN; @@ -2168,7 +2187,8 @@ clutter_event_get_gesture_motion_delta (const ClutterEvent *event, { g_return_if_fail (event != NULL); g_return_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH || - event->type == CLUTTER_TOUCHPAD_SWIPE); + event->type == CLUTTER_TOUCHPAD_SWIPE || + event->type == CLUTTER_TOUCHPAD_HOLD); if (event->type == CLUTTER_TOUCHPAD_PINCH) { @@ -2184,6 +2204,13 @@ clutter_event_get_gesture_motion_delta (const ClutterEvent *event, if (dy) *dy = event->touchpad_swipe.dy; } + else if (event->type == CLUTTER_TOUCHPAD_HOLD) + { + if (dx) + *dx = 0; + if (dy) + *dy = 0; + } } /** diff --git a/clutter/clutter/clutter-event.h b/clutter/clutter/clutter-event.h index 7afdb4a6d..78bd7f42d 100644 --- a/clutter/clutter/clutter-event.h +++ b/clutter/clutter/clutter-event.h @@ -117,6 +117,7 @@ typedef struct _ClutterCrossingEvent ClutterCrossingEvent; typedef struct _ClutterTouchEvent ClutterTouchEvent; typedef struct _ClutterTouchpadPinchEvent ClutterTouchpadPinchEvent; typedef struct _ClutterTouchpadSwipeEvent ClutterTouchpadSwipeEvent; +typedef struct _ClutterTouchpadHoldEvent ClutterTouchpadHoldEvent; typedef struct _ClutterProximityEvent ClutterProximityEvent; typedef struct _ClutterPadButtonEvent ClutterPadButtonEvent; typedef struct _ClutterPadStripEvent ClutterPadStripEvent; @@ -500,6 +501,43 @@ struct _ClutterTouchpadSwipeEvent gfloat dy; }; +/** + * ClutterTouchpadHoldEvent + * @type: event type + * @time: event time + * @flags: event flags + * @stage: event source stage + * @source: event source actor (unused) + * @phase: the current phase of the gesture + * @n_fingers: the number of fingers triggering the swipe + * @x: the X coordinate of the pointer, relative to the stage + * @y: the Y coordinate of the pointer, relative to the stage + * + * Used for touchpad hold gesture events. The current state of the + * gesture will be determined by the @phase field. + * + * A hold gesture starts when the user places one or many fingers on the + * touchpad and ends when all fingers are lifted. It is cancelled when the + * finger(s) move past a certain threshold. + * Unlike swipe and pinch, @phase can only be + * CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN, CLUTTER_TOUCHPAD_GESTURE_PHASE_END and + * CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL. + */ +struct _ClutterTouchpadHoldEvent +{ + ClutterEventType type; + guint32 time; + ClutterEventFlags flags; + ClutterStage *stage; + ClutterActor *source; + + ClutterTouchpadGesturePhase phase; + uint32_t n_fingers; + float x; + float y; +}; + + struct _ClutterPadButtonEvent { ClutterEventType type; @@ -592,6 +630,7 @@ union _ClutterEvent ClutterTouchEvent touch; ClutterTouchpadPinchEvent touchpad_pinch; ClutterTouchpadSwipeEvent touchpad_swipe; + ClutterTouchpadHoldEvent touchpad_hold; ClutterProximityEvent proximity; ClutterPadButtonEvent pad_button; ClutterPadStripEvent pad_strip; diff --git a/clutter/clutter/clutter-main.c b/clutter/clutter/clutter-main.c index b61e45cd2..27c48574d 100644 --- a/clutter/clutter/clutter-main.c +++ b/clutter/clutter/clutter-main.c @@ -1892,6 +1892,7 @@ _clutter_process_event_details (ClutterActor *stage, case CLUTTER_SCROLL: case CLUTTER_TOUCHPAD_PINCH: case CLUTTER_TOUCHPAD_SWIPE: + case CLUTTER_TOUCHPAD_HOLD: { ClutterActor *actor; gfloat x, y; diff --git a/meson.build b/meson.build index ee2c89b16..f9bf3b5d0 100644 --- a/meson.build +++ b/meson.build @@ -38,10 +38,10 @@ gudev_req = '>= 232' # wayland version requirements wayland_server_req = '>= 1.20' -wayland_protocols_req = '>= 1.19' +wayland_protocols_req = '>= 1.23' # native backend version requirements -libinput_req = '>= 1.7' +libinput_req = '>= 1.19.0' gbm_req = '>= 10.3' # screen cast version requirements diff --git a/src/backends/native/meta-seat-native.c b/src/backends/native/meta-seat-native.c index b4f1b3f57..51f0225f7 100644 --- a/src/backends/native/meta-seat-native.c +++ b/src/backends/native/meta-seat-native.c @@ -1094,6 +1094,48 @@ notify_swipe_gesture_event (ClutterInputDevice *input_device, queue_event (event); } +static void +notify_hold_gesture_event (ClutterInputDevice *input_device, + ClutterTouchpadGesturePhase phase, + uint64_t time_us, + uint32_t n_fingers) +{ + MetaInputDeviceNative *device_evdev; + MetaSeatNative *seat; + ClutterStage *stage; + ClutterEvent *event = NULL; + graphene_point_t pos; + + /* We can drop the event on the floor if no stage has been + * associated with the device yet. */ + stage = _clutter_input_device_get_stage (input_device); + if (stage == NULL) + return; + + device_evdev = META_INPUT_DEVICE_NATIVE (input_device); + seat = meta_input_device_native_get_seat (device_evdev); + + event = clutter_event_new (CLUTTER_TOUCHPAD_HOLD); + + meta_event_native_set_time_usec (event, time_us); + event->touchpad_hold.phase = phase; + event->touchpad_hold.time = us2ms (time_us); + event->touchpad_hold.stage = CLUTTER_STAGE (stage); + + clutter_input_device_get_coords (seat->core_pointer, NULL, &pos); + event->touchpad_hold.x = pos.x; + event->touchpad_hold.y = pos.y; + event->touchpad_hold.n_fingers = n_fingers; + + meta_xkb_translate_state (event, seat->xkb, seat->button_state); + + clutter_event_set_device (event, seat->core_pointer); + clutter_event_set_source_device (event, input_device); + + queue_event (event); +} + + static void notify_proximity (ClutterInputDevice *input_device, uint64_t time_us, @@ -2187,6 +2229,28 @@ process_device_event (MetaSeatNative *seat, time_us, n_fingers, dx, dy); break; } + case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN: + case LIBINPUT_EVENT_GESTURE_HOLD_END: + { + struct libinput_event_gesture *gesture_event = + libinput_event_get_gesture_event (event); + ClutterTouchpadGesturePhase phase; + uint32_t n_fingers; + uint64_t time_us; + + device = libinput_device_get_user_data (libinput_device); + time_us = libinput_event_gesture_get_time_usec (gesture_event); + n_fingers = libinput_event_gesture_get_finger_count (gesture_event); + + if (libinput_event_get_type (event) == LIBINPUT_EVENT_GESTURE_HOLD_BEGIN) + phase = CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN; + else + phase = libinput_event_gesture_get_cancelled (gesture_event) ? + CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL : CLUTTER_TOUCHPAD_GESTURE_PHASE_END; + + notify_hold_gesture_event (device, phase, time_us, n_fingers); + break; + } case LIBINPUT_EVENT_TABLET_TOOL_AXIS: { process_tablet_axis (seat, event); diff --git a/src/core/events.c b/src/core/events.c index e16927cde..35839bd94 100644 --- a/src/core/events.c +++ b/src/core/events.c @@ -42,6 +42,7 @@ #define IS_GESTURE_EVENT(e) ((e)->type == CLUTTER_TOUCHPAD_SWIPE || \ (e)->type == CLUTTER_TOUCHPAD_PINCH || \ + (e)->type == CLUTTER_TOUCHPAD_HOLD || \ (e)->type == CLUTTER_TOUCH_BEGIN || \ (e)->type == CLUTTER_TOUCH_UPDATE || \ (e)->type == CLUTTER_TOUCH_END || \ diff --git a/src/meson.build b/src/meson.build index 838407eb4..e4be36537 100644 --- a/src/meson.build +++ b/src/meson.build @@ -530,6 +530,8 @@ if have_wayland 'wayland/meta-wayland-pointer.c', 'wayland/meta-wayland-pointer-constraints.c', 'wayland/meta-wayland-pointer-constraints.h', + 'wayland/meta-wayland-pointer-gesture-hold.c', + 'wayland/meta-wayland-pointer-gesture-hold.h', 'wayland/meta-wayland-pointer-gesture-pinch.c', 'wayland/meta-wayland-pointer-gesture-pinch.h', 'wayland/meta-wayland-pointer-gestures.c', diff --git a/src/tests/clutter/conform/actor-event-hold.c b/src/tests/clutter/conform/actor-event-hold.c new file mode 100644 index 000000000..3d0e01c80 --- /dev/null +++ b/src/tests/clutter/conform/actor-event-hold.c @@ -0,0 +1,137 @@ +/* + * 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 . + * + * Author: José Expósito + */ +#include +#include + +#include + +#include "tests/clutter-test-utils.h" + +#define EVENT_TIME 1000 + +typedef struct { + ClutterTouchpadGesturePhase phase; + guint n_fingers; + gfloat x; + gfloat y; +} HoldTestCase; + +static const HoldTestCase test_cases[] = { + { + .phase = CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN, + .n_fingers = 1, + .x = 100, + .y = 150, + }, + { + .phase = CLUTTER_TOUCHPAD_GESTURE_PHASE_END, + .n_fingers = 2, + .x = 200, + .y = 250, + }, + { + .phase = CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL, + .n_fingers = 3, + .x = 300, + .y = 350, + }, +}; + +static gboolean +on_stage_captured_event (ClutterActor *stage, + ClutterEvent *event, + ClutterEvent **captured_event) +{ + *captured_event = clutter_event_copy (event); + return TRUE; +} + +static void +actor_event_hold (void) +{ + ClutterActor *stage; + ClutterBackend *backend; + ClutterSeat *seat; + ClutterInputDevice *device; + ClutterEvent *event; + ClutterEvent *captured_event; + size_t n_test_case; + + /* Get the stage and listen for touchpad events */ + stage = clutter_test_get_stage (); + g_signal_connect (stage, "captured-event::touchpad", + G_CALLBACK (on_stage_captured_event), + &captured_event); + clutter_actor_show (stage); + + /* Get the input device*/ + backend = clutter_get_default_backend (); + seat = clutter_backend_get_default_seat (backend); + device = clutter_seat_get_pointer (seat); + + for (n_test_case = 0; n_test_case < G_N_ELEMENTS (test_cases); n_test_case++) + { + graphene_point_t actual_position; + gdouble *actual_axes; + ClutterTouchpadGesturePhase actual_phase; + guint actual_n_fingers; + gdouble dx, dy, udx, udy; + + const HoldTestCase *test_case = test_cases + n_test_case; + + /* Create a synthetic hold event */ + event = clutter_event_new (CLUTTER_TOUCHPAD_HOLD); + event->touchpad_hold.phase = test_case->phase; + event->touchpad_hold.time = EVENT_TIME; + event->touchpad_hold.n_fingers = test_case->n_fingers; + event->touchpad_hold.stage = (ClutterStage *) stage; + event->touchpad_hold.source = stage; + clutter_event_set_coords (event, test_case->x, test_case->y); + clutter_event_set_device (event, device); + + clutter_event_put (event); + clutter_event_free (event); + + /* Capture the event received by the stage */ + captured_event = NULL; + while (captured_event == NULL) + g_main_context_iteration (NULL, FALSE); + + /* Check that expected the event params match the actual values */ + clutter_event_get_position (captured_event, &actual_position); + actual_axes = clutter_event_get_axes (captured_event, 0); + actual_phase = clutter_event_get_gesture_phase (captured_event); + actual_n_fingers = clutter_event_get_touchpad_gesture_finger_count (captured_event); + clutter_event_get_gesture_motion_delta (captured_event, &dx, &dy); + + g_assert (actual_position.x == test_case->x); + g_assert (actual_position.y == test_case->y); + g_assert_null (actual_axes); + g_assert (actual_phase == test_case->phase); + g_assert (actual_n_fingers == test_case->n_fingers); + g_assert (dx == 0); + g_assert (dy == 0); + g_assert (udx == 0); + g_assert (udy == 0); + + clutter_event_free (captured_event); + } +} + +CLUTTER_TEST_SUITE ( + CLUTTER_TEST_UNIT ("/actor/event/hold", actor_event_hold) +) diff --git a/src/tests/clutter/conform/meson.build b/src/tests/clutter/conform/meson.build index 35221bb8d..31f51e016 100644 --- a/src/tests/clutter/conform/meson.build +++ b/src/tests/clutter/conform/meson.build @@ -12,6 +12,7 @@ clutter_conform_tests_actor_tests = [ 'actor-anchors', 'actor-clone', 'actor-destroy', + 'actor-event-hold', 'actor-graph', 'actor-invariants', 'actor-iter', diff --git a/src/tests/clutter/interactive/test-events.c b/src/tests/clutter/interactive/test-events.c index f31c7d228..7baa1dce5 100644 --- a/src/tests/clutter/interactive/test-events.c +++ b/src/tests/clutter/interactive/test-events.c @@ -361,6 +361,9 @@ input_cb (ClutterActor *actor, case CLUTTER_TOUCHPAD_SWIPE: g_print ("[%s] TOUCHPAD SWIPE", clutter_actor_get_name (source_actor)); break; + case CLUTTER_TOUCHPAD_HOLD: + g_print ("[%s] TOUCHPAD HOLD", clutter_actor_get_name (source_actor)); + break; case CLUTTER_PROXIMITY_IN: g_print ("[%s] PROXIMITY IN", clutter_actor_get_name (source_actor)); break; diff --git a/src/tests/clutter/interactive/test-grab.c b/src/tests/clutter/interactive/test-grab.c index eabec8778..cf8b25600 100644 --- a/src/tests/clutter/interactive/test-grab.c +++ b/src/tests/clutter/interactive/test-grab.c @@ -87,6 +87,9 @@ debug_event_cb (ClutterActor *actor, case CLUTTER_TOUCHPAD_SWIPE: g_print ("[%s] TOUCHPAD SWIPE", source); break; + case CLUTTER_TOUCHPAD_HOLD: + g_print ("[%s] TOUCHPAD HOLD", source); + break; case CLUTTER_PROXIMITY_IN: g_print ("[%s] PROXIMITY IN", source); break; diff --git a/src/wayland/meta-wayland-pointer-gesture-hold.c b/src/wayland/meta-wayland-pointer-gesture-hold.c new file mode 100644 index 000000000..17ba5cc4e --- /dev/null +++ b/src/wayland/meta-wayland-pointer-gesture-hold.c @@ -0,0 +1,135 @@ +/* + * Wayland Support + * + * 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 . + * + * Author: José Expósito + */ + +#include "config.h" + +#include "wayland/meta-wayland-pointer-gesture-hold.h" + +#include + +#include "wayland/meta-wayland-pointer.h" +#include "wayland/meta-wayland-seat.h" +#include "wayland/meta-wayland-surface.h" + +#include "pointer-gestures-unstable-v1-server-protocol.h" + +static void +handle_hold_begin (MetaWaylandPointer *pointer, + const ClutterEvent *event) +{ + MetaWaylandPointerClient *pointer_client; + MetaWaylandSeat *seat; + struct wl_resource *resource; + uint32_t serial, fingers; + + pointer_client = pointer->focus_client; + seat = meta_wayland_pointer_get_seat (pointer); + serial = wl_display_next_serial (seat->wl_display); + fingers = clutter_event_get_touchpad_gesture_finger_count (event); + + wl_resource_for_each (resource, &pointer_client->hold_gesture_resources) + { + zwp_pointer_gesture_hold_v1_send_begin (resource, serial, + clutter_event_get_time (event), + pointer->focus_surface->resource, + fingers); + } +} + +static void +handle_hold_end (MetaWaylandPointer *pointer, + const ClutterEvent *event) +{ + MetaWaylandPointerClient *pointer_client; + MetaWaylandSeat *seat; + struct wl_resource *resource; + gboolean cancelled = FALSE; + uint32_t serial; + + pointer_client = pointer->focus_client; + seat = meta_wayland_pointer_get_seat (pointer); + serial = wl_display_next_serial (seat->wl_display); + + if (event->touchpad_hold.phase == CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL) + cancelled = TRUE; + + wl_resource_for_each (resource, &pointer_client->hold_gesture_resources) + { + zwp_pointer_gesture_hold_v1_send_end (resource, serial, + clutter_event_get_time (event), + cancelled); + } +} + +gboolean +meta_wayland_pointer_gesture_hold_handle_event (MetaWaylandPointer *pointer, + const ClutterEvent *event) +{ + if (event->type != CLUTTER_TOUCHPAD_HOLD) + return FALSE; + + if (!pointer->focus_client) + return FALSE; + + switch (event->touchpad_hold.phase) + { + case CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN: + handle_hold_begin (pointer, event); + break; + case CLUTTER_TOUCHPAD_GESTURE_PHASE_END: + case CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL: + handle_hold_end (pointer, event); + break; + default: + return FALSE; + } + + return TRUE; +} + +static void +pointer_gesture_hold_release (struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + +static const struct zwp_pointer_gesture_hold_v1_interface pointer_gesture_hold_interface = { + pointer_gesture_hold_release +}; + +void +meta_wayland_pointer_gesture_hold_create_new_resource (MetaWaylandPointer *pointer, + struct wl_client *client, + struct wl_resource *pointer_resource, + uint32_t id) +{ + MetaWaylandPointerClient *pointer_client; + struct wl_resource *res; + + pointer_client = meta_wayland_pointer_get_pointer_client (pointer, client); + g_return_if_fail (pointer_client != NULL); + + res = wl_resource_create (client, &zwp_pointer_gesture_hold_v1_interface, + wl_resource_get_version (pointer_resource), id); + wl_resource_set_implementation (res, &pointer_gesture_hold_interface, pointer, + meta_wayland_pointer_unbind_pointer_client_resource); + wl_list_insert (&pointer_client->hold_gesture_resources, + wl_resource_get_link (res)); +} diff --git a/src/wayland/meta-wayland-pointer-gesture-hold.h b/src/wayland/meta-wayland-pointer-gesture-hold.h new file mode 100644 index 000000000..55846bff6 --- /dev/null +++ b/src/wayland/meta-wayland-pointer-gesture-hold.h @@ -0,0 +1,37 @@ +/* + * Wayland Support + * + * 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 . + * + * Author: José Expósito + */ + +#ifndef META_WAYLAND_POINTER_GESTURE_HOLD_H +#define META_WAYLAND_POINTER_GESTURE_HOLD_H + +#include +#include + +#include "clutter/clutter.h" +#include "wayland/meta-wayland-types.h" + +gboolean meta_wayland_pointer_gesture_hold_handle_event (MetaWaylandPointer *pointer, + const ClutterEvent *event); + +void meta_wayland_pointer_gesture_hold_create_new_resource (MetaWaylandPointer *pointer, + struct wl_client *client, + struct wl_resource *gestures_resource, + uint32_t id); + +#endif /* META_WAYLAND_POINTER_GESTURE_HOLD_H */ diff --git a/src/wayland/meta-wayland-pointer-gestures.c b/src/wayland/meta-wayland-pointer-gestures.c index 7222a8a8c..559531d34 100644 --- a/src/wayland/meta-wayland-pointer-gestures.c +++ b/src/wayland/meta-wayland-pointer-gestures.c @@ -54,9 +54,29 @@ gestures_get_pinch (struct wl_client *client, meta_wayland_pointer_gesture_pinch_create_new_resource (pointer, client, resource, id); } +static void +gestures_get_hold (struct wl_client *client, + struct wl_resource *resource, + uint32_t id, + struct wl_resource *pointer_resource) +{ + MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource); + + meta_wayland_pointer_gesture_hold_create_new_resource (pointer, client, resource, id); +} + +static void +gestures_release (struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + static const struct zwp_pointer_gestures_v1_interface pointer_gestures_interface = { gestures_get_swipe, - gestures_get_pinch + gestures_get_pinch, + gestures_release, + gestures_get_hold }; static void diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c index 397128b3c..43d8be9b5 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c @@ -104,6 +104,7 @@ meta_wayland_pointer_client_new (void) wl_list_init (&pointer_client->pointer_resources); wl_list_init (&pointer_client->swipe_gesture_resources); wl_list_init (&pointer_client->pinch_gesture_resources); + wl_list_init (&pointer_client->hold_gesture_resources); wl_list_init (&pointer_client->relative_pointer_resources); return pointer_client; @@ -133,6 +134,11 @@ meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client) wl_list_remove (wl_resource_get_link (resource)); wl_list_init (wl_resource_get_link (resource)); } + wl_resource_for_each_safe (resource, next, &pointer_client->hold_gesture_resources) + { + wl_list_remove (wl_resource_get_link (resource)); + wl_list_init (wl_resource_get_link (resource)); + } wl_resource_for_each_safe (resource, next, &pointer_client->relative_pointer_resources) { wl_list_remove (wl_resource_get_link (resource)); @@ -148,6 +154,7 @@ meta_wayland_pointer_client_is_empty (MetaWaylandPointerClient *pointer_client) return (wl_list_empty (&pointer_client->pointer_resources) && wl_list_empty (&pointer_client->swipe_gesture_resources) && wl_list_empty (&pointer_client->pinch_gesture_resources) && + wl_list_empty (&pointer_client->hold_gesture_resources) && wl_list_empty (&pointer_client->relative_pointer_resources)); } @@ -835,6 +842,10 @@ meta_wayland_pointer_handle_event (MetaWaylandPointer *pointer, meta_wayland_pointer_gesture_pinch_handle_event (pointer, event); break; + case CLUTTER_TOUCHPAD_HOLD: + meta_wayland_pointer_gesture_hold_handle_event (pointer, event); + break; + default: break; } diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h index 529177b8c..80087c0be 100644 --- a/src/wayland/meta-wayland-pointer.h +++ b/src/wayland/meta-wayland-pointer.h @@ -25,6 +25,7 @@ #include "meta/meta-cursor-tracker.h" #include "wayland/meta-wayland-pointer-constraints.h" +#include "wayland/meta-wayland-pointer-gesture-hold.h" #include "wayland/meta-wayland-pointer-gesture-pinch.h" #include "wayland/meta-wayland-pointer-gesture-swipe.h" #include "wayland/meta-wayland-seat.h" @@ -57,6 +58,7 @@ struct _MetaWaylandPointerClient { struct wl_list pointer_resources; struct wl_list swipe_gesture_resources; + struct wl_list hold_gesture_resources; struct wl_list pinch_gesture_resources; struct wl_list relative_pointer_resources; }; diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c index 2315fecee..782c798d0 100644 --- a/src/wayland/meta-wayland-seat.c +++ b/src/wayland/meta-wayland-seat.c @@ -387,6 +387,7 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat, case CLUTTER_SCROLL: case CLUTTER_TOUCHPAD_SWIPE: case CLUTTER_TOUCHPAD_PINCH: + case CLUTTER_TOUCHPAD_HOLD: if (meta_wayland_seat_has_pointer (seat)) return meta_wayland_pointer_handle_event (seat->pointer, event); diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h index af67cb4b5..1ba947a45 100644 --- a/src/wayland/meta-wayland-versions.h +++ b/src/wayland/meta-wayland-versions.h @@ -43,7 +43,7 @@ #define META_XSERVER_VERSION 1 #define META_GTK_SHELL1_VERSION 3 #define META_WL_SUBCOMPOSITOR_VERSION 1 -#define META_ZWP_POINTER_GESTURES_V1_VERSION 1 +#define META_ZWP_POINTER_GESTURES_V1_VERSION 3 #define META_ZXDG_EXPORTER_V1_VERSION 1 #define META_ZXDG_IMPORTER_V1_VERSION 1 #define META_ZXDG_EXPORTER_V2_VERSION 1