From 63e5372190606c5c124eafbc4cac753f59bb9f69 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 31 Jan 2018 16:04:09 +1000 Subject: [PATCH] Add libinput_device_touch_get_touch_count() This makes it possible for callers to detect whether a touch device is single or multitouch (or even check for things like dual-touch vs real multi-touch) and adjust the interface accordingly. Note that this is for touch devices only, not touchpads that are just pointer devices. https://bugs.freedesktop.org/show_bug.cgi?id=104867 Signed-off-by: Peter Hutterer --- src/evdev.c | 22 ++++++++++++++++++++++ src/evdev.h | 3 +++ src/libinput.c | 6 ++++++ src/libinput.h | 14 ++++++++++++++ src/libinput.sym | 4 ++++ test/test-touch.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 92 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index 2a36ef81..27c14713 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -2300,6 +2300,28 @@ evdev_device_has_key(struct evdev_device *device, uint32_t code) return libevdev_has_event_code(device->evdev, EV_KEY, code); } +int +evdev_device_get_touch_count(struct evdev_device *device) +{ + int ntouches; + + if (!(device->seat_caps & EVDEV_DEVICE_TOUCH)) + return -1; + + ntouches = libevdev_get_num_slots(device->evdev); + if (ntouches == -1) { + /* mtdev devices have multitouch but we don't know + * how many. Otherwise, any touch device with num_slots of + * -1 is a single-touch device */ + if (device->mtdev) + ntouches = 0; + else + ntouches = 1; + } + + return ntouches; +} + int evdev_device_has_switch(struct evdev_device *device, enum libinput_switch sw) diff --git a/src/evdev.h b/src/evdev.h index 0c602ea0..f22bbdb3 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -467,6 +467,9 @@ evdev_device_has_button(struct evdev_device *device, uint32_t code); int evdev_device_has_key(struct evdev_device *device, uint32_t code); +int +evdev_device_get_touch_count(struct evdev_device *device); + int evdev_device_has_switch(struct evdev_device *device, enum libinput_switch sw); diff --git a/src/libinput.c b/src/libinput.c index 8fb0ba92..5e675dd9 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -2941,6 +2941,12 @@ libinput_device_keyboard_has_key(struct libinput_device *device, uint32_t code) return evdev_device_has_key((struct evdev_device *)device, code); } +LIBINPUT_EXPORT int +libinput_device_touch_get_touch_count(struct libinput_device *device) +{ + return evdev_device_get_touch_count((struct evdev_device *)device); +} + LIBINPUT_EXPORT int libinput_device_switch_has_switch(struct libinput_device *device, enum libinput_switch sw) diff --git a/src/libinput.h b/src/libinput.h index f1a0a2a6..828cf6b4 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -3713,6 +3713,20 @@ int libinput_device_keyboard_has_key(struct libinput_device *device, uint32_t code); +/** + * @ingroup device + * + * Check how many touches a @ref LIBINPUT_DEVICE_CAP_TOUCH device supports + * simultaneously. + * + * @param device A current input device + * + * @return The number of simultaneous touches or 0 if unknown, -1 + * on error. + */ +int +libinput_device_touch_get_touch_count(struct libinput_device *device); + /** * @ingroup device * diff --git a/src/libinput.sym b/src/libinput.sym index bb283407..aa2794e9 100644 --- a/src/libinput.sym +++ b/src/libinput.sym @@ -293,3 +293,7 @@ LIBINPUT_1.7 { LIBINPUT_1.9 { libinput_device_switch_has_switch; } LIBINPUT_1.7; + +LIBINPUT_1.11 { + libinput_device_touch_get_touch_count; +} LIBINPUT_1.9; diff --git a/test/test-touch.c b/test/test-touch.c index 5ce97c23..7c1aa4cc 100644 --- a/test/test-touch.c +++ b/test/test-touch.c @@ -1023,6 +1023,44 @@ START_TEST(touch_invalid_range_under) } END_TEST +START_TEST(touch_count_st) +{ + struct litest_device *dev = litest_current_device(); + struct libinput_device *device = dev->libinput_device; + + ck_assert_int_eq(libinput_device_touch_get_touch_count(device), 1); +} +END_TEST + +START_TEST(touch_count_mt) +{ + struct litest_device *dev = litest_current_device(); + struct libinput_device *device = dev->libinput_device; + struct libevdev *evdev = dev->evdev; + + ck_assert_int_eq(libinput_device_touch_get_touch_count(device), + libevdev_get_num_slots(evdev)); +} +END_TEST + +START_TEST(touch_count_unknown) +{ + struct litest_device *dev = litest_current_device(); + struct libinput_device *device = dev->libinput_device; + + ck_assert_int_eq(libinput_device_touch_get_touch_count(device), 0); +} +END_TEST + +START_TEST(touch_count_invalid) +{ + struct litest_device *dev = litest_current_device(); + struct libinput_device *device = dev->libinput_device; + + ck_assert_int_eq(libinput_device_touch_get_touch_count(device), -1); +} +END_TEST + TEST_COLLECTION(touch) { struct range axes = { ABS_X, ABS_Y + 1}; @@ -1060,4 +1098,9 @@ TEST_COLLECTION(touch) litest_add_for_device("touch:range", touch_invalid_range_over, LITEST_TOUCHSCREEN_INVALID_RANGE); litest_add_for_device("touch:range", touch_invalid_range_under, LITEST_TOUCHSCREEN_INVALID_RANGE); + + litest_add("touch:count", touch_count_st, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD); + litest_add("touch:count", touch_count_mt, LITEST_TOUCH, LITEST_SINGLE_TOUCH|LITEST_PROTOCOL_A); + litest_add("touch:count", touch_count_unknown, LITEST_PROTOCOL_A, LITEST_ANY); + litest_add("touch:count", touch_count_invalid, LITEST_ANY, LITEST_TOUCH|LITEST_SINGLE_TOUCH|LITEST_PROTOCOL_A); }