From 38b5c2e0cc4aa0a705b45d1f7337231798479bd7 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 28 Nov 2025 14:56:10 +1000 Subject: [PATCH] touchpad: add configurable timeouts to disable-while-trackpointing Same motivation as in commit "touchpad: add configurable timeouts to disable-while-typing" Part-of: --- src/evdev-mt-touchpad.c | 29 ++++++++++++++++++++++++-- src/evdev-mt-touchpad.h | 1 + src/libinput-private.h | 3 +++ src/libinput.c | 21 +++++++++++++++++++ src/libinput.h | 45 +++++++++++++++++++++++++++++++++++++++++ src/libinput.sym | 2 ++ test/test-trackpoint.c | 28 +++++++++++++++++++++---- 7 files changed, 123 insertions(+), 6 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 628fa979..dd09468b 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -2145,8 +2145,7 @@ tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data) tp->palm.trackpoint_active = true; } - libinput_timer_set(&tp->palm.trackpoint_timer, - time + DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT); + libinput_timer_set(&tp->palm.trackpoint_timer, time + tp->palm.timeout); } static void @@ -3244,6 +3243,29 @@ tp_dwtp_config_get_default(struct libinput_device *device) : LIBINPUT_CONFIG_DWTP_DISABLED; } +static enum libinput_config_status +tp_dwtp_config_set_timeout(struct libinput_device *device, uint64_t timeout) +{ + struct evdev_device *evdev = evdev_device(device); + struct tp_dispatch *tp = (struct tp_dispatch *)evdev->dispatch; + + if (timeout <= ms2us(100) || timeout >= ms2us(5000)) + return LIBINPUT_CONFIG_STATUS_INVALID; + + tp->palm.timeout = timeout; + + return LIBINPUT_CONFIG_STATUS_SUCCESS; +} + +static uint64_t +tp_dwtp_config_get_timeout(struct libinput_device *device) +{ + struct evdev_device *evdev = evdev_device(device); + struct tp_dispatch *tp = (struct tp_dispatch *)evdev->dispatch; + + return tp->palm.timeout; +} + static inline bool tp_is_tpkb_combo_below(struct evdev_device *device) { @@ -3299,6 +3321,9 @@ tp_init_dwtp(struct tp_dispatch *tp, struct evdev_device *device) tp->palm.config.set_enabled = tp_dwtp_config_set; tp->palm.config.get_enabled = tp_dwtp_config_get; tp->palm.config.get_default_enabled = tp_dwtp_config_get_default; + tp->palm.config.set_timeout = tp_dwtp_config_set_timeout; + tp->palm.config.get_timeout = tp_dwtp_config_get_timeout; + tp->palm.timeout = DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT; device->base.config.dwtp = &tp->palm.config; } diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index f7901555..3f9fb260 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -457,6 +457,7 @@ struct tp_dispatch { struct { struct libinput_device_config_dwtp config; bool dwtp_enabled; + uint64_t timeout; int32_t right_edge; /* in device coordinates */ int32_t left_edge; /* in device coordinates */ diff --git a/src/libinput-private.h b/src/libinput-private.h index 9bb5425d..4000bbed 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -476,6 +476,9 @@ struct libinput_device_config_dwtp { enum libinput_config_dwtp_state (*get_enabled)(struct libinput_device *device); enum libinput_config_dwtp_state (*get_default_enabled)( struct libinput_device *device); + enum libinput_config_status (*set_timeout)(struct libinput_device *device, + uint64_t timeout); + uint64_t (*get_timeout)(struct libinput_device *device); }; struct libinput_device_config_rotation { diff --git a/src/libinput.c b/src/libinput.c index 7036739f..e3bca724 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -4979,6 +4979,27 @@ libinput_device_config_dwtp_get_default_enabled(struct libinput_device *device) return device->config.dwtp->get_default_enabled(device); } +LIBINPUT_EXPORT enum libinput_config_status +libinput_device_config_dwtp_set_timeout(struct libinput_device *device, uint32_t millis) +{ + if (millis == 0) + return LIBINPUT_CONFIG_STATUS_INVALID; + + if (!libinput_device_config_dwtp_is_available(device)) + return LIBINPUT_CONFIG_STATUS_UNSUPPORTED; + + return device->config.dwtp->set_timeout(device, ms2us(millis)); +} + +LIBINPUT_EXPORT uint32_t +libinput_device_config_dwtp_get_timeout(struct libinput_device *device) +{ + if (!libinput_device_config_dwtp_is_available(device)) + return 0; + + return us2ms(device->config.dwtp->get_timeout(device)); +} + LIBINPUT_EXPORT int libinput_device_config_rotation_is_available(struct libinput_device *device) { diff --git a/src/libinput.h b/src/libinput.h index 541230d6..f9560cad 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -6807,6 +6807,8 @@ enum libinput_config_dwtp_state { * @see libinput_device_config_dwtp_set_enabled * @see libinput_device_config_dwtp_get_enabled * @see libinput_device_config_dwtp_get_default_enabled + * @see libinput_device_config_dwtp_get_timeout + * @see libinput_device_config_dwtp_set_timeout * * @since 1.21 */ @@ -6833,6 +6835,8 @@ libinput_device_config_dwtp_is_available(struct libinput_device *device); * @see libinput_device_config_dwtp_is_available * @see libinput_device_config_dwtp_get_enabled * @see libinput_device_config_dwtp_get_default_enabled + * @see libinput_device_config_dwtp_get_timeout + * @see libinput_device_config_dwtp_set_timeout * * @since 1.21 */ @@ -6854,6 +6858,8 @@ libinput_device_config_dwtp_set_enabled(struct libinput_device *device, * @see libinput_device_config_dwtp_is_available * @see libinput_device_config_dwtp_set_enabled * @see libinput_device_config_dwtp_get_default_enabled + * @see libinput_device_config_dwtp_get_timeout + * @see libinput_device_config_dwtp_set_timeout * * @since 1.21 */ @@ -6874,12 +6880,51 @@ libinput_device_config_dwtp_get_enabled(struct libinput_device *device); * @see libinput_device_config_dwtp_is_available * @see libinput_device_config_dwtp_set_enabled * @see libinput_device_config_dwtp_get_enabled + * @see libinput_device_config_dwtp_get_timeout + * @see libinput_device_config_dwtp_set_timeout * * @since 1.21 */ enum libinput_config_dwtp_state libinput_device_config_dwtp_get_default_enabled(struct libinput_device *device); +/** + * @ingroup config + * + * Set the disable-while-trackpointing timeout. This timeout denotes the time + * in milliseconds between the last trackpoint event and the touchpad re-enabling. + * + * The timeout only takes effect if disable-while-trackpointing is enabled. + * + * @note The timeout is not the only condition for disable-while-trackpointing, expiry + * of the timeout does not guarantee that the touchpad is re-enabled. + * + * @see libinput_device_config_dwtp_is_available + * @see libinput_device_config_dwtp_set_enabled + * @see libinput_device_config_dwtp_get_enabled + * @see libinput_device_config_dwtp_get_timeout + * + * @since 1.31 + */ +enum libinput_config_status +libinput_device_config_dwtp_set_timeout(struct libinput_device *device, + uint32_t millis); + +/** + * @ingroup config + * + * Get the current disable-while-trackpointing timeout. + * + * @see libinput_device_config_dwtp_is_available + * @see libinput_device_config_dwtp_set_enabled + * @see libinput_device_config_dwtp_get_enabled + * @see libinput_device_config_dwtp_set_timeout + * + * @since 1.31 + */ +uint32_t +libinput_device_config_dwtp_get_timeout(struct libinput_device *device); + /** * @ingroup config * diff --git a/src/libinput.sym b/src/libinput.sym index dd8a0575..054d66b9 100644 --- a/src/libinput.sym +++ b/src/libinput.sym @@ -384,4 +384,6 @@ LIBINPUT_1.30 { LIBINPUT_1.31 { libinput_device_config_dwt_get_timeout; libinput_device_config_dwt_set_timeout; + libinput_device_config_dwtp_get_timeout; + libinput_device_config_dwtp_set_timeout; } LIBINPUT_1.30; diff --git a/test/test-trackpoint.c b/test/test-trackpoint.c index c41d3b26..f0383633 100644 --- a/test/test-trackpoint.c +++ b/test/test-trackpoint.c @@ -283,12 +283,25 @@ START_TEST(trackpoint_topsoftbuttons_left_handed_both) END_TEST static inline void -enable_dwtp(struct litest_device *dev) +enable_dwtp_with_timeout(struct litest_device *dev, uint32_t timeout) { enum libinput_config_status status, expected = LIBINPUT_CONFIG_STATUS_SUCCESS; status = libinput_device_config_dwtp_set_enabled(dev->libinput_device, LIBINPUT_CONFIG_DWTP_ENABLED); litest_assert_enum_eq(status, expected); + + if (timeout) { + auto status = + libinput_device_config_dwtp_set_timeout(dev->libinput_device, + timeout); + litest_assert_enum_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + } +} + +static inline void +enable_dwtp(struct litest_device *dev) +{ + enable_dwtp_with_timeout(dev, 0); } static inline void @@ -305,11 +318,12 @@ START_TEST(trackpoint_palmdetect) struct litest_device *trackpoint = litest_current_device(); struct libinput *li = trackpoint->libinput; int i; + uint32_t timeout = litest_test_param_get_u32(test_env->params, "timeout"); _destroy_(litest_device) *touchpad = litest_add_device(li, LITEST_SYNAPTICS_I2C); if (has_disable_while_trackpointing(touchpad)) - enable_dwtp(touchpad); + enable_dwtp_with_timeout(touchpad, timeout); litest_disable_hold_gestures(touchpad->libinput_device); litest_drain_events(li); @@ -327,7 +341,11 @@ START_TEST(trackpoint_palmdetect) litest_touch_up(touchpad, 0); litest_assert_empty_queue(li); - litest_timeout_trackpoint(li); + if (timeout) { + litest_timeout(li, timeout); + } else { + litest_timeout_trackpoint(li); + } litest_touch_down(touchpad, 0, 30, 30); litest_touch_move_to(touchpad, 0, 30, 30, 80, 80, 10); @@ -472,7 +490,9 @@ TEST_COLLECTION(trackpoint) litest_add(trackpoint_topsoftbuttons_left_handed_touchpad, LITEST_TOPBUTTONPAD, LITEST_ANY); litest_add(trackpoint_topsoftbuttons_left_handed_both, LITEST_TOPBUTTONPAD, LITEST_ANY); - litest_add(trackpoint_palmdetect, LITEST_POINTINGSTICK, LITEST_ANY); + litest_with_parameters(params, "timeout", 'u', 4, 0, 120, 300, 900) { + litest_add_parametrized(trackpoint_palmdetect, LITEST_POINTINGSTICK, LITEST_ANY, params); + } litest_add(trackpoint_palmdetect_dwtp_disabled, LITEST_POINTINGSTICK, LITEST_ANY); litest_add(trackpoint_palmdetect_resume_touch, LITEST_POINTINGSTICK, LITEST_ANY); litest_add(trackpoint_palmdetect_require_min_events, LITEST_POINTINGSTICK, LITEST_ANY);