gesutures: allow to configure hold gestures
authorJosé Expósito <jose.exposito89@gmail.com>
Thu, 27 May 2021 17:19:49 +0000 (19:19 +0200)
committerPeter Hutterer <peter.hutterer@who-t.net>
Wed, 9 Jun 2021 01:18:58 +0000 (01:18 +0000)
Valgrind can be too slow to run some time based tests. In those cases, we
need to disable hold gestures.

Add the required functions to configure hold gestures: enable, disable,
get default state and get current state.

Keep them private as they are intended to be used only from the tests.

Signed-off-by: José Expósito <jose.exposito89@gmail.com>
meson.build
src/evdev-mt-touchpad-gestures.c
src/evdev-mt-touchpad.h
src/libinput-private-config.c [new file with mode: 0644]
src/libinput-private-config.h [new file with mode: 0644]
src/libinput-private.h
test/litest.h
test/test-gestures.c

index 6a6daaa1a9d2495408375cb5ff9e4ce74a4041c8..1e3066c928a000520258b1016578b0971bf0cf76 100644 (file)
@@ -345,6 +345,8 @@ install_headers('src/libinput.h')
 src_libinput = src_libfilter + [
        'src/libinput.c',
        'src/libinput.h',
+       'src/libinput-private-config.c',
+       'src/libinput-private-config.h',
        'src/libinput-private.h',
        'src/evdev.c',
        'src/evdev.h',
@@ -670,6 +672,8 @@ if get_option('tests')
        config_h.set10('HAVE_LIBSYSTEMD', dep_libsystemd.found())
 
        litest_sources = [
+               'src/libinput-private-config.c',
+               'src/libinput-private-config.h',
                'test/litest.h',
                'test/litest-int.h',
                'test/litest-device-absinfo-override.c',
index 8c239bd7a230cf8712bc476117c35630088fccef..b4fc7edbb92d3ebd9d4fbe9633006d8d91229607 100644 (file)
@@ -1185,17 +1185,59 @@ tp_gesture_are_gestures_enabled(struct tp_dispatch *tp)
        return (!tp->semi_mt && tp->num_slots > 1);
 }
 
+static enum libinput_config_status
+tp_gesture_set_hold_enabled(struct libinput_device *device,
+                           enum libinput_config_hold_state enabled)
+{
+       struct evdev_dispatch *dispatch = evdev_device(device)->dispatch;
+       struct tp_dispatch *tp = tp_dispatch(dispatch);
+
+       if (!tp_gesture_are_gestures_enabled(tp))
+               return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
+
+       tp->gesture.hold_enabled = (enabled == LIBINPUT_CONFIG_HOLD_ENABLED);
+
+       return LIBINPUT_CONFIG_STATUS_SUCCESS;
+}
+
+static enum libinput_config_hold_state
+tp_gesture_is_hold_enabled(struct libinput_device *device)
+{
+       struct evdev_dispatch *dispatch = evdev_device(device)->dispatch;
+       struct tp_dispatch *tp = tp_dispatch(dispatch);
+
+       return tp->gesture.hold_enabled ? LIBINPUT_CONFIG_HOLD_ENABLED :
+                                         LIBINPUT_CONFIG_HOLD_DISABLED;
+}
+
+static enum libinput_config_hold_state
+tp_gesture_get_hold_default(struct libinput_device *device)
+{
+       struct evdev_dispatch *dispatch = evdev_device(device)->dispatch;
+       struct tp_dispatch *tp = tp_dispatch(dispatch);
+
+       return tp_gesture_are_gestures_enabled(tp) ?
+              LIBINPUT_CONFIG_HOLD_ENABLED :
+              LIBINPUT_CONFIG_HOLD_DISABLED;
+}
+
 void
 tp_init_gesture(struct tp_dispatch *tp)
 {
        char timer_name[64];
 
+       tp->gesture.config.set_hold_enabled = tp_gesture_set_hold_enabled;
+       tp->gesture.config.get_hold_enabled = tp_gesture_is_hold_enabled;
+       tp->gesture.config.get_hold_default = tp_gesture_get_hold_default;
+       tp->device->base.config.gesture = &tp->gesture.config;
+
        /* two-finger scrolling is always enabled, this flag just
         * decides whether we detect pinch. semi-mt devices are too
         * unreliable to do pinch gestures. */
        tp->gesture.enabled = tp_gesture_are_gestures_enabled(tp);
 
        tp->gesture.state = GESTURE_STATE_NONE;
+       tp->gesture.hold_enabled = tp_gesture_are_gestures_enabled(tp);
 
        snprintf(timer_name,
                 sizeof(timer_name),
index a58ca7f726835d53674f1115ea0f88ce39ac2f53..2e8497065430bc9dad4b8b2d7bc2c162de407eb9 100644 (file)
@@ -346,6 +346,7 @@ struct tp_dispatch {
        } accel;
 
        struct {
+               struct libinput_device_config_gesture config;
                bool enabled;
                bool started;
                unsigned int finger_count;
@@ -358,6 +359,7 @@ struct tp_dispatch {
                double prev_scale;
                double angle;
                struct device_float_coords center;
+               bool hold_enabled;
        } gesture;
 
        struct {
diff --git a/src/libinput-private-config.c b/src/libinput-private-config.c
new file mode 100644 (file)
index 0000000..bd5cde3
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright © 2021 Red Hat, Inc.
+ * Copyright © 2021 José Expósito
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include "libinput-private-config.h"
+#include "libinput-private.h"
+
+int
+libinput_device_config_gesture_hold_is_available(struct libinput_device *device)
+{
+       if (!libinput_device_has_capability(device,
+                                           LIBINPUT_DEVICE_CAP_GESTURE))
+               return 0;
+
+       if (!device->config.gesture->get_hold_default(device))
+               return 0;
+
+       return 1;
+}
+
+enum libinput_config_status
+libinput_device_config_gesture_set_hold_enabled(struct libinput_device *device,
+                                               enum libinput_config_hold_state enable)
+{
+       if (enable != LIBINPUT_CONFIG_HOLD_ENABLED &&
+           enable != LIBINPUT_CONFIG_HOLD_DISABLED)
+               return LIBINPUT_CONFIG_STATUS_INVALID;
+
+       if (!libinput_device_config_gesture_hold_is_available(device)) {
+               return enable ? LIBINPUT_CONFIG_STATUS_UNSUPPORTED :
+                               LIBINPUT_CONFIG_STATUS_SUCCESS;
+       }
+
+       return device->config.gesture->set_hold_enabled(device, enable);
+}
+
+enum libinput_config_hold_state
+libinput_device_config_gesture_get_hold_enabled(struct libinput_device *device)
+{
+       if (!libinput_device_config_gesture_hold_is_available(device))
+               return LIBINPUT_CONFIG_HOLD_DISABLED;
+
+       return device->config.gesture->get_hold_enabled(device);
+}
+
+enum libinput_config_hold_state
+libinput_device_config_gesture_get_hold_default_enabled(struct libinput_device *device)
+{
+       if (!libinput_device_config_gesture_hold_is_available(device))
+               return LIBINPUT_CONFIG_HOLD_DISABLED;
+
+       return device->config.gesture->get_hold_default(device);
+}
diff --git a/src/libinput-private-config.h b/src/libinput-private-config.h
new file mode 100644 (file)
index 0000000..d1d6c8e
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright © 2021 Red Hat, Inc.
+ * Copyright © 2021 José Expósito
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef LIBINPUT_PRIVATE_CONFIG_H
+#define LIBINPUT_PRIVATE_CONFIG_H
+
+#include "config.h"
+
+#include "libinput.h"
+
+enum libinput_config_hold_state {
+       /** Hold gestures are to be disabled, or are currently disabled */
+       LIBINPUT_CONFIG_HOLD_DISABLED,
+       /** Hold gestures are to be enabled, or are currently disabled */
+       LIBINPUT_CONFIG_HOLD_ENABLED,
+};
+
+/**
+ * @ingroup config
+ *
+ * Check whether a device can perform hold gestures.
+ *
+ * @param device The device to configure
+ * @return Non-zero if a device can perform hold gestures, zero otherwise.
+ *
+ * @see libinput_device_config_gesture_set_hold_enabled
+ * @see libinput_device_config_gesture_get_hold_enabled
+ * @see libinput_device_config_gesture_get_hold_default_enabled
+ */
+int
+libinput_device_config_gesture_hold_is_available(struct libinput_device *device);
+
+/**
+ * @ingroup config
+ *
+ * Enable or disable hold gestures on this device.
+ *
+ * @param device The device to configure
+ * @param enable @ref LIBINPUT_CONFIG_HOLD_ENABLED to enable hold gestures or
+ * @ref LIBINPUT_CONFIG_HOLD_DISABLED to disable them
+ *
+ * @return A config status code. Disabling hold gestures on a device that does
+ * not support them always succeeds.
+ *
+ * @see libinput_device_config_gesture_hold_is_available
+ * @see libinput_device_config_gesture_get_hold_enabled
+ * @see libinput_device_config_gesture_get_hold_default_enabled
+ */
+enum libinput_config_status
+libinput_device_config_gesture_set_hold_enabled(struct libinput_device *device,
+                                               enum libinput_config_hold_state enable);
+
+/**
+ * @ingroup config
+ *
+ * Check if hold gestures are enabled on this device. If the device does not
+ * support hold gestures, this function always returns @ref
+ * LIBINPUT_CONFIG_HOLD_DISABLED.
+ *
+ * @param device The device to configure
+ *
+ * @retval LIBINPUT_CONFIG_HOLD_ENABLED If hold gestures are currently enabled
+ * @retval LIBINPUT_CONFIG_HOLD_DISABLED If hold gestures are currently disabled
+ *
+ * @see libinput_device_config_gesture_hold_is_available
+ * @see libinput_device_config_gesture_set_hold_enabled
+ * @see libinput_device_config_gesture_get_hold_default_enabled
+ */
+enum libinput_config_hold_state
+libinput_device_config_gesture_get_hold_enabled(struct libinput_device *device);
+
+/**
+ * @ingroup config
+ *
+ * Return the default setting for whether hold gestures are enabled on this
+ * device.
+ *
+ * @param device The device to configure
+ * @retval LIBINPUT_CONFIG_HOLD_ENABLED If hold gestures are enabled by default
+ * @retval LIBINPUT_CONFIG_HOLD_DISABLED If hold gestures are disabled by
+ * default
+ *
+ * @see libinput_device_config_gesture_hold_is_available
+ * @see libinput_device_config_gesture_set_hold_enabled
+ * @see libinput_device_config_gesture_get_hold_enabled
+ */
+enum libinput_config_hold_state
+libinput_device_config_gesture_get_hold_default_enabled(struct libinput_device *device);
+
+#endif /* LIBINPUT_PRIVATE_CONFIG_H */
index 8c7b77dd3172585781aa3e4bab8a3f19bcb52acf..172035abb2269e0e92e96ff74cdab5912f0628be 100644 (file)
@@ -38,6 +38,7 @@
 #include "linux/input.h"
 
 #include "libinput.h"
+#include "libinput-private-config.h"
 #include "libinput-util.h"
 #include "libinput-version.h"
 
@@ -307,6 +308,13 @@ struct libinput_device_config_rotation {
        unsigned int (*get_default_angle)(struct libinput_device *device);
 };
 
+struct libinput_device_config_gesture {
+       enum libinput_config_status (*set_hold_enabled)(struct libinput_device *device,
+                        enum libinput_config_hold_state enabled);
+       enum libinput_config_hold_state (*get_hold_enabled)(struct libinput_device *device);
+       enum libinput_config_hold_state (*get_hold_default)(struct libinput_device *device);
+};
+
 struct libinput_device_config {
        struct libinput_device_config_tap *tap;
        struct libinput_device_config_calibration *calibration;
@@ -319,6 +327,7 @@ struct libinput_device_config {
        struct libinput_device_config_middle_emulation *middle_emulation;
        struct libinput_device_config_dwt *dwt;
        struct libinput_device_config_rotation *rotation;
+       struct libinput_device_config_gesture *gesture;
 };
 
 struct libinput_device_group {
index 536765216cd3e486e8b97d587e9fad034ca5a439..fbd0746dd2925f9ecdc0c8594fb4d7fccdd63581 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "check-double-macros.h"
 
+#include "libinput-private-config.h"
 #include "libinput-util.h"
 #include "quirks.h"
 
@@ -1162,6 +1163,30 @@ litest_sendevents_ext_mouse(struct litest_device *dev)
        litest_assert_int_eq(status, expected);
 }
 
+static inline void
+litest_enable_hold_gestures(struct libinput_device *device)
+{
+       enum libinput_config_status status, expected;
+
+       expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
+       status = libinput_device_config_gesture_set_hold_enabled(device,
+                                                                LIBINPUT_CONFIG_HOLD_ENABLED);
+
+       litest_assert_int_eq(status, expected);
+}
+
+static inline void
+litest_disable_hold_gestures(struct libinput_device *device)
+{
+       enum libinput_config_status status, expected;
+
+       expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
+       status = libinput_device_config_gesture_set_hold_enabled(device,
+                                                                LIBINPUT_CONFIG_HOLD_DISABLED);
+
+       litest_assert_int_eq(status, expected);
+}
+
 static inline bool
 litest_touchpad_is_external(struct litest_device *dev)
 {
index cf378389727d6f05f5aae1ed92a0c373720a3ddf..21f53baf848cde875594ee591c92d11564b7bc1c 100644 (file)
@@ -1160,6 +1160,78 @@ START_TEST(gestures_swipe_3fg_unaccel)
 }
 END_TEST
 
+START_TEST(gestures_hold_config_default_disabled)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput_device *device = dev->libinput_device;
+
+       ck_assert_int_eq(libinput_device_config_gesture_hold_is_available(device),
+                        0);
+       ck_assert_int_eq(libinput_device_config_gesture_get_hold_default_enabled(device),
+                        LIBINPUT_CONFIG_HOLD_DISABLED);
+       ck_assert_int_eq(libinput_device_config_gesture_get_hold_default_enabled(device),
+                        LIBINPUT_CONFIG_HOLD_DISABLED);
+}
+END_TEST
+
+START_TEST(gestures_hold_config_default_enabled)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput_device *device = dev->libinput_device;
+
+       ck_assert_int_eq(libinput_device_config_gesture_hold_is_available(device),
+                        1);
+       ck_assert_int_eq(libinput_device_config_gesture_get_hold_default_enabled(device),
+                        LIBINPUT_CONFIG_HOLD_ENABLED);
+       ck_assert_int_eq(libinput_device_config_gesture_get_hold_enabled(device),
+                        LIBINPUT_CONFIG_HOLD_ENABLED);
+}
+END_TEST
+
+START_TEST(gestures_hold_config_set_invalid)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput_device *device = dev->libinput_device;
+
+       ck_assert_int_eq(libinput_device_config_gesture_set_hold_enabled(device, -1),
+                        LIBINPUT_CONFIG_STATUS_INVALID);
+       ck_assert_int_eq(libinput_device_config_gesture_set_hold_enabled(device, 2),
+                        LIBINPUT_CONFIG_STATUS_INVALID);
+}
+END_TEST
+
+START_TEST(gestures_hold_config_is_available)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput_device *device = dev->libinput_device;
+
+       ck_assert_int_eq(libinput_device_config_gesture_hold_is_available(device),
+                        1);
+       ck_assert_int_eq(libinput_device_config_gesture_get_hold_enabled(device),
+                        LIBINPUT_CONFIG_HOLD_ENABLED);
+       ck_assert_int_eq(libinput_device_config_gesture_set_hold_enabled(device, LIBINPUT_CONFIG_HOLD_DISABLED),
+                        LIBINPUT_CONFIG_STATUS_SUCCESS);
+       ck_assert_int_eq(libinput_device_config_gesture_get_hold_enabled(device),
+                        LIBINPUT_CONFIG_HOLD_DISABLED);
+}
+END_TEST
+
+START_TEST(gestures_hold_config_is_not_available)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput_device *device = dev->libinput_device;
+
+       ck_assert_int_eq(libinput_device_config_gesture_hold_is_available(device),
+                        0);
+       ck_assert_int_eq(libinput_device_config_gesture_get_hold_enabled(device),
+                        LIBINPUT_CONFIG_HOLD_DISABLED);
+       ck_assert_int_eq(libinput_device_config_gesture_set_hold_enabled(device, LIBINPUT_CONFIG_HOLD_ENABLED),
+                        LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
+       ck_assert_int_eq(libinput_device_config_gesture_set_hold_enabled(device, LIBINPUT_CONFIG_HOLD_DISABLED),
+                        LIBINPUT_CONFIG_STATUS_SUCCESS);
+}
+END_TEST
+
 TEST_COLLECTION(gestures)
 {
        struct range cardinals = { N, N + NCARDINALS };
@@ -1182,6 +1254,12 @@ TEST_COLLECTION(gestures)
 
        litest_add(gestures_time_usec, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
 
+       litest_add(gestures_hold_config_default_disabled, LITEST_TOUCHPAD|LITEST_SEMI_MT, LITEST_ANY);
+       litest_add(gestures_hold_config_default_enabled, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
+       litest_add(gestures_hold_config_set_invalid, LITEST_TOUCHPAD, LITEST_ANY);
+       litest_add(gestures_hold_config_is_available, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
+       litest_add(gestures_hold_config_is_not_available, LITEST_TOUCHPAD|LITEST_SEMI_MT, LITEST_ANY);
+
        /* Timing-sensitive test, valgrind is too slow */
        if (!RUNNING_ON_VALGRIND)
                litest_add(gestures_swipe_3fg_unaccel, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);