diff -Nru libinput-1.16.4/completion/zsh/_libinput libinput-1.17.2/completion/zsh/_libinput --- libinput-1.16.4/completion/zsh/_libinput 2020-11-27 01:38:59.339086000 +0000 +++ libinput-1.17.2/completion/zsh/_libinput 2021-04-30 04:25:41.513076300 +0000 @@ -163,12 +163,35 @@ ':device:_files -W /dev/input/ -P /dev/input/' } +(( $+functions[_libinput_analyze_per-slot-delta] )) || _libinput_analyze_per-slot-delta() +{ + _arguments \ + '--help[Show help message and exit]' \ + ':recording:_files' +} + +(( $+functions[_libinput_analyze_touch-down-state] )) || _libinput_analyze_touch-down-state() +{ + _arguments \ + '--help[Show help message and exit]' \ + ':recording:_files' +} + +(( $+functions[_libinput_analyze_recording] )) || _libinput_analyze_recording() +{ + _arguments \ + '--help[Show help message and exit]' \ + ':recording:_files' +} + (( $+functions[_libinput_analyze] )) || _libinput_analyze() { local curcontext=$curcontext state line ret=1 local features features=( "per-slot-delta:analyze relative movement per touch per slot" + "recording:analyze a recording by printing a pretty table" + "touch-down-state:analyze a recording for logical touch down states" ) _arguments -C \ @@ -196,7 +219,7 @@ '--help[Show help message and exit]' \ '--all[Record all /dev/input/event* devices available on the system]' \ '--autorestart=[Terminate the current recording after s seconds of device inactivity]' \ - {-o+,--output=}'[Speficy the output file to use]:file:_files -g "*.yml"' \ + {-o+,--output=}'[Specify the output file to use]:file:_files -g "*.yml"' \ '--multiple[Record multiple devices at once]' \ '--show-keycodes[Show keycodes as-is in the recording]' \ '--with-libinput[Record libinput events alongside device events]' \ diff -Nru libinput-1.16.4/debian/changelog libinput-1.17.2/debian/changelog --- libinput-1.16.4/debian/changelog 2021-02-26 12:51:13.000000000 +0000 +++ libinput-1.17.2/debian/changelog 2021-05-03 08:43:43.000000000 +0000 @@ -1,18 +1,11 @@ -libinput (1.16.4-3ubuntu2) hirsute; urgency=medium +libinput (1.17.2-1) experimental; urgency=medium + * New upstream release. * Allow to build without the udeb package. + * Update control build-dep libevdev-dev (>= 1.10.0) for + libevdev_disable_property API. - -- Matthias Klose Fri, 26 Feb 2021 13:51:13 +0100 - -libinput (1.16.4-3ubuntu1) hirsute; urgency=medium - - * Merge with Debian; remaining changes: - - quirks: Unset INPUT_PROP_BUTTONPAD for Dell Precision 7550/7750. - LP #1906341. - - Update control build-dep libevdev-dev (>= 1.10.0) for - libevdev_disable_property API. - - -- Matthias Klose Fri, 26 Feb 2021 13:01:07 +0100 + -- Timo Aaltonen Mon, 03 May 2021 11:43:43 +0300 libinput (1.16.4-3) unstable; urgency=medium @@ -26,21 +19,6 @@ -- Timo Aaltonen Thu, 10 Dec 2020 17:27:17 +0200 -libinput (1.16.4-1ubuntu2) hirsute; urgency=medium - - * No-change rebuild for libwacom soname change. - - -- Matthias Klose Fri, 01 Jan 2021 10:00:08 +0100 - -libinput (1.16.4-1ubuntu1) hirsute; urgency=medium - - * quirks: Unset INPUT_PROP_BUTTONPAD for Dell Precision 7550/7750. - (LP: #1906341) - * Update control build-dep libevdev-dev (>= 1.10.0) for - libevdev_disable_property API - - -- Sebastien Bacher Thu, 03 Dec 2020 16:32:27 +0100 - libinput (1.16.4-1) unstable; urgency=medium * control, rules: Enable building debug-gui and tests, add check and diff -Nru libinput-1.16.4/debian/patches/add-model-quirk-for-dell-precision-7x50.patch libinput-1.17.2/debian/patches/add-model-quirk-for-dell-precision-7x50.patch --- libinput-1.16.4/debian/patches/add-model-quirk-for-dell-precision-7x50.patch 2021-02-26 12:03:15.000000000 +0000 +++ libinput-1.17.2/debian/patches/add-model-quirk-for-dell-precision-7x50.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -quirks: add quirk for Dell Precision 7550/7750 touchpad - -Dell Precision 7550/7750 touchpad report device capability denoted by [1] is wrongly -configured as clickpad, so that kernel driver will set INPUT_PROP_BUTTONPAD bit, -unset it for keep handling BTN_RIGHT event in libinput. - -[1] https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-precision-touchpad-required-hid-top-level-collections ---- a/src/quirks.h -+++ b/src/quirks.h -@@ -89,6 +89,7 @@ - QUIRK_MODEL_TRACKBALL, - QUIRK_MODEL_WACOM_TOUCHPAD, - QUIRK_MODEL_DELL_CANVAS_TOTEM, -+ QUIRK_MODEL_DELL_PRECISION7X50_TOUCHPAD, - - _QUIRK_LAST_MODEL_QUIRK_, /* Guard: do not modify */ - ---- a/src/evdev.c -+++ b/src/evdev.c -@@ -2072,6 +2072,11 @@ - if (evdev_device_has_model_quirk(device, QUIRK_MODEL_HP_ZBOOK_STUDIO_G3)) - libevdev_set_abs_maximum(device->evdev, ABS_MT_SLOT, 1); - -+ /* Touchpad is not a clickpad but INPUT_PROP_BUTTONPAD is set */ -+ if (evdev_device_has_model_quirk(device, QUIRK_MODEL_DELL_PRECISION7X50_TOUCHPAD)) -+ libevdev_disable_property(device->evdev, -+ INPUT_PROP_BUTTONPAD); -+ - /* Generally we don't care about MSC_TIMESTAMP and it can cause - * unnecessary wakeups but on some devices we need to watch it for - * pointer jumps */ ---- a/src/quirks.c -+++ b/src/quirks.c -@@ -256,6 +256,7 @@ - case QUIRK_MODEL_TRACKBALL: return "ModelTrackball"; - case QUIRK_MODEL_WACOM_TOUCHPAD: return "ModelWacomTouchpad"; - case QUIRK_MODEL_DELL_CANVAS_TOTEM: return "ModelDellCanvasTotem"; -+ case QUIRK_MODEL_DELL_PRECISION7X50_TOUCHPAD: return "ModelDellPrecision7x50Touchpad"; - - case QUIRK_ATTR_SIZE_HINT: return "AttrSizeHint"; - case QUIRK_ATTR_TOUCH_SIZE_RANGE: return "AttrTouchSizeRange"; ---- a/quirks/50-system-dell.quirks -+++ b/quirks/50-system-dell.quirks -@@ -73,3 +73,8 @@ - MatchVendor=0x2575 - MatchProduct=0x0204 - ModelDellCanvasTotem=1 -+ -+[Latitude 7x50 Touchpad] -+MatchName=DELL09C?:00 0488:120A Touchpad -+MatchDMIModalias=dmi:*svnDellInc.:pnPrecision7?50:* -+ModelDellPrecision7x50Touchpad=1 diff -Nru libinput-1.16.4/debian/patches/series libinput-1.17.2/debian/patches/series --- libinput-1.16.4/debian/patches/series 2021-02-26 12:03:15.000000000 +0000 +++ libinput-1.17.2/debian/patches/series 2021-05-03 07:58:40.000000000 +0000 @@ -1,2 +1 @@ #placeholder -add-model-quirk-for-dell-precision-7x50.patch diff -Nru libinput-1.16.4/doc/api/libinput.doxygen.in libinput-1.17.2/doc/api/libinput.doxygen.in --- libinput-1.16.4/doc/api/libinput.doxygen.in 2020-11-27 01:38:59.340086000 +0000 +++ libinput-1.17.2/doc/api/libinput.doxygen.in 2021-04-30 04:25:41.513076300 +0000 @@ -11,8 +11,9 @@ QUIET = YES INPUT = "@builddir@" IMAGE_PATH = "@builddir@" +OUTPUT_DIRECTORY = doc GENERATE_HTML = YES -HTML_OUTPUT = api +HTML_OUTPUT = html SEARCHENGINE = NO USE_MATHJAX = YES MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest diff -Nru libinput-1.16.4/doc/api/meson.build libinput-1.17.2/doc/api/meson.build --- libinput-1.16.4/doc/api/meson.build 2020-11-27 01:38:59.340086000 +0000 +++ libinput-1.17.2/doc/api/meson.build 2021-04-30 04:25:41.513076300 +0000 @@ -9,26 +9,6 @@ error('Program "dot" not found or not executable. Try building with -Ddocumentation=false') endif -doxygen_version_cmd = run_command(doxygen.path(), '--version') -if doxygen_version_cmd.returncode() != 0 - error('Command "doxygen --version" failed.') -endif -doxygen_version = doxygen_version_cmd.stdout() -if doxygen_version.version_compare('< 1.8.3') - error('doxygen needs to be at least version 1.8.3 (have @0@)'.format(doxygen_version)) -endif -grep = find_program('grep') -dot_version_cmd = run_command(dot.path(), '-V') -if dot_version_cmd.returncode() != 0 - error('Command "dot -V" failed.') -endif -# dot -V output is (to stderr): -# dot - graphviz version 2.38.0 (20140413.2041) -dot_version = dot_version_cmd.stderr().split(' ')[4] -if dot_version.version_compare('< 2.26') - error('Graphviz dot needs to be at least version 2.26 (have @0@)'.format(dot_version)) -endif - mainpage = vcs_tag(command : ['git', 'log', '-1', '--format=%h'], fallback : 'unknown', input : 'mainpage.dox', @@ -46,19 +26,11 @@ 'style/libinputdoxygen.css', ) -config_noop = configuration_data() -# Set a dummy replacement to silence meson warnings: -# meson.build:487: WARNING: Got an empty configuration_data() object and -# found no substitutions in the input file 'foo'. If you -# want to copy a file to the build dir, use the 'copy:' -# keyword argument added in 0.47.0 -config_noop.set('dummy', 'dummy') - doxyfiles = [] foreach f : src_doxygen df = configure_file(input: f, output: '@PLAINNAME@', - configuration : config_noop) + copy : true) doxyfiles += [ df ] endforeach @@ -73,7 +45,7 @@ custom_target('doxygen', input : [ doxyfiles, doxyfile, mainpage ] + src_doxygen, - output : [ '.' ], + output : [ 'html' ], command : [ doxygen, doxyfile ], install : false, depends: [ mainpage ], diff -Nru libinput-1.16.4/doc/touchpad-tap-state-machine.svg libinput-1.17.2/doc/touchpad-tap-state-machine.svg --- libinput-1.16.4/doc/touchpad-tap-state-machine.svg 2020-11-27 01:38:59.347086000 +0000 +++ libinput-1.17.2/doc/touchpad-tap-state-machine.svg 2021-04-30 04:25:41.517076300 +0000 @@ -1,3 +1,3 @@ -IDLETOUCHfirstfinger downfinger upbutton 1presstimeoutmove > thresholdsecondfinger downTOUCH_2secondfinger upbutton 2pressmove > thresholdtimeoutbutton 1releasebutton 2releaseTAPPEDtimeoutfirstfinger downDRAGGINGfirstfinger upbtn1releaseIDLEthirdfinger downTOUCH_3button 3pressbutton 3releasemove > thresholdIDLEtimeoutfirstfinger upIDLEfourthfinger downDRAGGING_OR_DOUBLETAPtimeoutfirstfinger upbutton 1releasesecondfinger downmove > thresholdHOLDfirstfinger upsecondfinger downTOUCH_2_HOLDsecondfinger upfirstfinger upthirdfinger downTOUCH_3_HOLDfourthfinger downDEADany finger upfourthfinger upany finger upyesany finger upIDLEif fingercount == 0secondfinger upDRAGGING_2firstfinger upsecondfinger downthirdfinger downbtn1releasephysbuttonpressphysbuttonpressbutton 1releaseDRAGGING_WAITtimeoutfirstfinger downTOUCH_TOUCHTOUCH_IDLETOUCH_DEADTOUCH_DEADTOUCH_IDLETOUCH_TOUCHTOUCH_IDLETOUCH_IDLETOUCH_TOUCHthat fingerTOUCH_IDLETOUCH_DEADthat fingerTOUCH_IDLEnoTOUCH_TOUCHTOUCH_IDLETOUCH_TOUCHTOUCH_DEADTOUCH_IDLETOUCH_TOUCHTOUCH_TOUCHTOUCH_IDLETOUCH_IDLETOUCH_TOUCHTOUCH_IDLETOUCH_TOUCHthat fingerTOUCH_IDLETOUCH_DEADTOUCH_DEADTOUCH_DEADTOUCH_DEADTOUCH_DEADTOUCH_DEADthat finger state ==TOUCH_TOUCHTOUCH_DEADTOUCH_DEADTOUCH_DEADDRAGGING_OR_TAPfirstfinger uptimeoutmove > thresholdTOUCH_IDLE
drag lock
enabled?
[Not supported by viewer]
no
no
yes
yes<br>
thumbTOUCH_DEADTOUCH_2_RELEASEsecondfinger uptimeoutmove > thresholdfirstfinger downTOUCH_IDLEfirstfinger upsecondfinger downTOUCH_DEADTOUCH_DEAD
drag
disabled?
drag<br>disabled?<br>
no
no
yes
yes
palmeither fingerpalmremaining fingerpalmany fingerpalmthat fingerTOUCH_DEADthat fingerTOUCH_DEADpalmany fingerpalmthat fingerTOUCH_DEADTOUCH_DEADpalmTOUCH_DEADany fingerpalmthat fingerTOUCH_DEADeither fingerpalmthat fingerTOUCH_DEADpalmTOUCH_DEADany fingerpalmthat fingerTOUCH_DEADTOUCH_DEADmove > thresholdmove > thresholdbutton 1press
\ No newline at end of file +
(this section exists for [n] = 1, [n] = 2, and [n] = 3)
(this section exists for [n] = 1, [n] = 2, and [n] = 3)
IDLETOUCHfirstfinger downfinger upbutton 1presstimeoutmove > thresholdsecondfinger downTOUCH_2secondfinger upbutton 2pressmove > thresholdtimeoutbutton 1releasebutton 2release[n]FGTAP_TAPPEDtimeoutfirstfinger down[n]FGTAP_DRAGGINGfirstfinger upbutton [n]releaseIDLEthirdfinger downTOUCH_3button 3pressbutton 3releasemove > thresholdIDLEtimeoutfirstfinger upIDLEfourthfinger down[n]FGTAP_DRAGGING_OR_DOUBLETAPtimeoutfirstfinger upbutton [n]releasesecondfinger downmove > thresholdHOLDfirstfinger upsecondfinger downTOUCH_2_HOLDsecondfinger upthirdfinger downTOUCH_3_HOLDfourthfinger downDEADany finger upfourthfinger upany finger upany finger upIDLEif fingercount == 0[n]FGTAP_DRAGGING_2secondfinger downthirdfinger downphysbuttonpressphysbuttonpressbutton [n]release[n]FGTAP_DRAGGING_WAITtimeoutfirstfinger downTOUCH_TOUCHTOUCH_IDLETOUCH_DEADTOUCH_DEADTOUCH_IDLETOUCH_TOUCHTOUCH_IDLETOUCH_IDLETOUCH_TOUCHthat fingerTOUCH_IDLETOUCH_DEADthat fingerTOUCH_IDLETOUCH_TOUCHTOUCH_IDLETOUCH_TOUCHTOUCH_DEADTOUCH_IDLETOUCH_TOUCHTOUCH_TOUCHTOUCH_IDLETOUCH_TOUCHthat fingerTOUCH_IDLETOUCH_DEADTOUCH_DEADTOUCH_DEADTOUCH_DEADTOUCH_DEADTOUCH_DEADTOUCH_DEADTOUCH_DEADTOUCH_DEAD[n]FGTAP_DRAGGING_OR_TAPfirstfinger uptimeoutmove > thresholdTOUCH_IDLEdrag lockenabled?
no
no
yes
yes
thumbTOUCH_DEADTOUCH_2_RELEASEsecondfinger uptimeoutmove > thresholdfirstfinger downTOUCH_IDLEfirstfinger upsecondfinger downTOUCH_DEADTOUCH_DEADdragdisabled?
yes
yes
palmeither fingerpalmremaining fingerpalmany fingerpalmthat fingerTOUCH_DEADthat fingerTOUCH_DEADpalmany fingerpalmthat fingerTOUCH_DEADTOUCH_DEADpalmTOUCH_DEADany fingerpalmthat fingerTOUCH_DEADeither fingerpalmthat fingerTOUCH_DEADpalmTOUCH_DEADany fingerpalmthat fingerTOUCH_DEADTOUCH_DEADmove > thresholdmove > thresholdbutton 1press
[n] = 1
[n] = 1
[n] = 1
[n] = 1
no
no
button [n]releaseIDLEdragdisabled?
[n] = 2
[n] = 2
no
no
yes
yes
dragdisabled?
yes
yes
no
no
[n] = 3
[n] = 3
TOUCH_3_RELEASEtimeoutTOUCH_DEADTOUCH_DEADeither fingerpalmthat fingerTOUCH_DEADmove > thresholdthirdfinger downTOUCH_TOUCHTOUCH_3_RELEASE_2remainingfinger upthat fingerTOUCH_IDLEeither finger upthat fingerTOUCH_IDLEsecondfinger downremaining fingerpalmTOUCH_DEADtimeoutfirstfinger upbutton 3pressbutton 3releasebutton 3pressbutton 3releaseeither finger upthat fingerTOUCH_IDLEsecondfinger downbutton [n]releasebutton 3pressbutton 3releaseTOUCH_DEADbutton 3pressbutton 3releasebutton 3pressbutton 3release
Viewer does not support full SVG 1.1
\ No newline at end of file diff -Nru libinput-1.16.4/doc/user/building.rst libinput-1.17.2/doc/user/building.rst --- libinput-1.16.4/doc/user/building.rst 2020-11-27 01:38:59.347086000 +0000 +++ libinput-1.17.2/doc/user/building.rst 2021-04-30 04:25:41.517076300 +0000 @@ -16,6 +16,29 @@ system-provided libinput with one from the git repository, see see :ref:`reverting_install` to revert to the previous state. +.. _distribution_repos: + +------------------------------------------------------------------------------ +Distribution repositories for libinput from git +------------------------------------------------------------------------------ + +Some distributions provide package repositories for users that want to test +the latest libinput without building it manually. + +.. note:: The list below is provided for convenience. The libinput community + cannot provide any guarantees that the packages in those repositories are + correct, up-to-date and/or unmodified from the git branch. Due dilligence + is recommended. + +The following repositories provide an up-to-date package for libinput: + +- **Arch:** https://aur.archlinux.org/packages/libinput-git/ +- **Fedora:** https://copr.fedorainfracloud.org/coprs/whot/libinput-git/ + +Please follow the respective repositories for instructions on how to enable +the repository and install libinput. + + .. _building: ------------------------------------------------------------------------------ @@ -201,6 +224,14 @@ `this blog post here `_ for instructions on how to fix it. +.............................................................................. +Build dependencies per distribution +.............................................................................. + + +.. include:: dependencies.rst + + .. _building_conditional: ------------------------------------------------------------------------------ diff -Nru libinput-1.16.4/doc/user/configuration.rst libinput-1.17.2/doc/user/configuration.rst --- libinput-1.16.4/doc/user/configuration.rst 2020-11-27 01:38:59.347086000 +0000 +++ libinput-1.17.2/doc/user/configuration.rst 2021-04-30 04:25:41.518076400 +0000 @@ -135,8 +135,9 @@ ------------------------------------------------------------------------------ DWT is the most generic form of palm detection on touchpad. While the user -is typing the touchpad is disabled, the touchpad is enabled after a timeout. -See :ref:`disable-while-typing` for more info. +is typing on an internal keyboard the touchpad is disabled, the touchpad +is enabled again after a timeout. See :ref:`disable-while-typing` for more +info. Disable-while-typing can be enabled or disabled, it is enabled by default on most touchpads. diff -Nru libinput-1.16.4/doc/user/contributing.rst libinput-1.17.2/doc/user/contributing.rst --- libinput-1.16.4/doc/user/contributing.rst 2020-11-27 01:38:59.348086000 +0000 +++ libinput-1.17.2/doc/user/contributing.rst 2021-04-30 04:25:41.518076400 +0000 @@ -28,7 +28,7 @@ Contact ------------------------------------------------------------------------------ -Questions can be asked on ``#wayland-devel`` on freenode or on the +Questions can be asked on ``#wayland`` on freenode or on the `wayland-devel@lists.freedesktop.org `_ mailing list. @@ -50,7 +50,7 @@ then a good way of finding something is to search for the ``help needed`` tag in our `issue tracker `_. These are issues that have been triaged to some degree and deemed to be a -possible future feature to libinput. +possible future feature to libinput. .. note:: Some of these issue may require specific hardware to reproduce. @@ -79,11 +79,11 @@ Working on the code ------------------------------------------------------------------------------ -libinput has a roughly three-parts architecture: +libinput has a roughly three-parts architecture: - the front-end code which handles the ``libinput_some_function()`` API calls in ``libinput.c`` - the generic evdev interface handling which maps those API calls to the - backend calls (``evdev.c``). + backend calls (``evdev.c``). - there are device-specific backends which do most of the actual work - ``evdev-mt-touchpad.c`` is the one for touchpads for example. @@ -149,33 +149,76 @@ in the `libinput GitLab instance hosted by freedesktop.org `_. -To submit a merge request, you need to +Below are the steps required to submit a merge request. They do not +replace `learning git `__ but they should be +sufficient to make some of the more confusing steps obvious. - `Register an account `_ in the freedesktop.org GitLab instance. - `Fork libinput `_ into your username's namespace -- Get libinput's main repository: :: +- Get libinput's main repository. git will call this repository ``origin``. :: git clone https://gitlab.freedesktop.org/libinput/libinput.git - Add the forked git repository to your remotes (replace ``USERNAME`` - with your username): :: + with your username). git will call this repository ``gitlab``. :: cd /path/to/libinput.git git remote add gitlab git@gitlab.freedesktop.org:USERNAME/libinput.git git fetch gitlab -- Push your changes to your fork: :: +- Create a new branch and commit your changes to that branch. :: - git push gitlab BRANCHNAME + git switch -C mynewbranch + # edit files, make changes + git add file1 file2 + git commit -s + # edit commit message in the editor -- Submit a merge request. The URL for a merge request is: :: + Replace ``mynewbranch`` (here and in the commands below) with a meaningful + name. See :ref:`contributing_commit_messages` for details on the commit + message format. + +- Push your changes to your fork and submit a merge request :: + + git push gitlab mynewbranch + + This command will print the URL to file a merge request, you then only + have to click through. Alternatively you can go to: https://gitlab.freedesktop.org/USERNAME/libinput/merge_requests Select your branch name to merge and ``libinput/libinput`` ``master`` as target branch. +- Verify that the CI completes successfully by visiting the merge request + page. A successful pipeline shows only green ticks, failure is indicated + by a red cross or a yellow exclamation mark (see + the `GitLab Docs + `__). For + details about the failures, click on the failed jobs in the pipelines + and/or click the ``Expand`` button in the box for the test summaries. + + A merge request without a successful pipeline may never be looked at by a + maintainer. + +- If changes are requested by the maintainers, please **amend** the + commit(s) and **force-push** the updated branch. :: + + # edits in file foo.c + git add foo.c + git commit --amend + git push -f gitlab mynewbranch + + A force-push will re-trigger the CI and notify the merge request that new + changes are available. + + If the branch contains more than one commit, please look at + `git interactive rebases + `__ + to learn how to change multiple commits, or squash new changes into older + commits. + ------------------------------------------------------------------------------ Commit History ------------------------------------------------------------------------------ @@ -215,6 +258,8 @@ If in doubt what prefix to use, look at other commits that change the same file(s) as the patch being sent. +.. _contributing_commit_messages: + ------------------------------------------------------------------------------ Commit Messages ------------------------------------------------------------------------------ diff -Nru libinput-1.16.4/doc/user/dependencies.rst libinput-1.17.2/doc/user/dependencies.rst --- libinput-1.16.4/doc/user/dependencies.rst 1970-01-01 00:00:00.000000000 +0000 +++ libinput-1.17.2/doc/user/dependencies.rst 2021-04-30 04:25:41.518076400 +0000 @@ -0,0 +1,21 @@ +.. warning:: The package lists are autogenerated from the `CI `_. + +- Fedora: :: + + dnf install @FEDORA_PACKAGES@ + +- Ubuntu: :: + + apt install @UBUNTU_PACKAGES@ + +- Debian: :: + + apt install @DEBIAN_PACKAGES@ + +- Arch: :: + + pacman -S @ARCH_PACKAGES@ + +- Alpine: :: + + apk add @ALPINE_PACKAGES@ diff -Nru libinput-1.16.4/doc/user/device-configuration-via-udev.rst libinput-1.17.2/doc/user/device-configuration-via-udev.rst --- libinput-1.16.4/doc/user/device-configuration-via-udev.rst 2020-11-27 01:38:59.348086000 +0000 +++ libinput-1.17.2/doc/user/device-configuration-via-udev.rst 2021-04-30 04:25:41.518076400 +0000 @@ -150,7 +150,7 @@ user in a local hwdb file. This property designates the touchpad on a Lenovo x220 with a touchpad firmware version 8.1. When this firmware version is installed, the touchpad is imprecise. The touchpad device does not send -continuos x/y axis position updates, a behavior also observed on its +continuous x/y axis position updates, a behavior also observed on its successor model, the Lenovo x230 which has the same firmware version. If the above property is set, libinput adjusts its behavior to better suit this particular model. @@ -263,4 +263,4 @@ device-specific quirks must go in to the :ref:`device-quirks` system. For information about older libinput versions, please see the documentation -for your version avaialable in: https://wayland.freedesktop.org/libinput/doc/ +for your version available in: https://wayland.freedesktop.org/libinput/doc/ diff -Nru libinput-1.16.4/doc/user/device-quirks.rst libinput-1.17.2/doc/user/device-quirks.rst --- libinput-1.16.4/doc/user/device-quirks.rst 2020-11-27 01:38:59.348086000 +0000 +++ libinput-1.17.2/doc/user/device-quirks.rst 2021-04-30 04:25:41.518076400 +0000 @@ -6,7 +6,7 @@ libinput requires extra information from devices that is not always readily available. For example, some touchpads are known to have jumping cursors -under specific conditions. libinput ships a set of files containting the +under specific conditions. libinput ships a set of files containing the so-called model quirks to provide that information. Model quirks are usually installed under ``/usr/share/libinput/.quirks`` and are standard ``.ini`` files. A file may contain multiple section headers (``[some @@ -157,7 +157,7 @@ Specifies the touch size required to trigger a press (N) and to trigger a release (M). O > N > M. See :ref:`touchpad_touch_size_hwdb` for more details. -AttrTouchPressureRange=N:M, AttrPalmPressureThreshold=O, AttrThumbPressureThreshold=P +AttrPressureRange=N:M, AttrPalmPressureThreshold=O, AttrThumbPressureThreshold=P Specifies the touch pressure required to trigger a press (N) and to trigger a release (M), when a palm touch is triggered (O) and when a thumb touch is triggered (P). O > P > N > M. See @@ -177,6 +177,16 @@ Disables the evdev event type/code tuples on the device. Entries may be a named event type, or a named event code, or a named event type with a hexadecimal event code, separated by a single colon. +AttrEventCodeEnable=EV_ABS;BTN_STYLUS;EV_KEY:0x123; + Enables the evdev event type/code tuples on the device. Entries may be + a named event type, or a named event code, or a named event type with a + hexadecimal event code, separated by a single colon. +AttrInputPropDisable=INPUT_PROP_BUTTONPAD;INPUT_PROP_POINTER; + Disables the evdev input property on the device. Entries may be + a named input property or the hexadecimal value of that property. +AttrInputPropEnable=INPUT_PROP_BUTTONPAD;INPUT_PROP_POINTER; + Enables the evdev input property on the device. Entries may be + a named input property or the hexadecimal value of that property. AttrPointingStickIntegration=internal|external Indicates the integration of the pointing stick. This is a string enum. Only needed for external pointing sticks. These are rare. diff -Nru libinput-1.16.4/doc/user/faqs.rst libinput-1.17.2/doc/user/faqs.rst --- libinput-1.16.4/doc/user/faqs.rst 2020-11-27 01:38:59.348086000 +0000 +++ libinput-1.17.2/doc/user/faqs.rst 2021-04-30 04:25:41.518076400 +0000 @@ -218,7 +218,7 @@ Synclient and syndaemon rely on X input device properties that are specific to the xf86-input-synaptics X.Org input driver. Both were written when the -synaptics driver was the only commmon touchpad driver in existence. They +synaptics driver was the only common touchpad driver in existence. They assume that if the properties aren't available, no touchpad is available either. The xf86-input-libinput X.Org input driver does not export these driver-specific properties, synclient/syndaemon will thus not detect the diff -Nru libinput-1.16.4/doc/user/features.rst libinput-1.17.2/doc/user/features.rst --- libinput-1.16.4/doc/user/features.rst 2020-11-27 01:38:59.348086000 +0000 +++ libinput-1.17.2/doc/user/features.rst 2021-04-30 04:25:41.518076400 +0000 @@ -5,7 +5,7 @@ ============================================================================== Below is a list of features supported by libinput. The availability of -features usually depends on the device type and a device's capabilties. +features usually depends on the device type and a device's capabilities. Not all features are user-configurable, some rely on :ref:`device-quirks` to be useful. diff -Nru libinput-1.16.4/doc/user/meson.build libinput-1.17.2/doc/user/meson.build --- libinput-1.16.4/doc/user/meson.build 2020-11-27 01:38:59.349086000 +0000 +++ libinput-1.17.2/doc/user/meson.build 2021-04-30 04:25:41.518076400 +0000 @@ -4,6 +4,11 @@ error('Program "sphinx-build" not found or not executable. Try building with -Ddocumentation=false') endif +yq = find_program('yq', required : false) +if not yq.found() + warning('Program "yq" not found or not executable. Dependency list will not be built.') +endif + sphinx_config = configuration_data() sphinx_config.set('PROJECT_NAME', meson.project_name()) sphinx_config.set('PROJECT_VERSION', meson.project_version()) @@ -168,18 +173,11 @@ 'configuration.rst', ) -config_noop = configuration_data() -# Set a dummy replacement to silence meson warnings: -# meson.build:487: WARNING: Got an empty configuration_data() object and -# found no substitutions in the input file 'foo'. If you -# want to copy a file to the build dir, use the 'copy:' -# keyword argument added in 0.47.0 -config_noop.set('dummy', 'dummy') src_sphinx = [] foreach f : src_rst sf = configure_file(input: f, output: '@PLAINNAME@', - configuration : config_noop) + copy : true) src_sphinx += [ sf ] endforeach @@ -187,6 +185,19 @@ output: 'index.rst', configuration: sphinx_config) +dependencies_config = configuration_data() +if yq.found() + distributions = ['fedora', 'ubuntu', 'debian', 'arch', 'alpine'] + foreach distro : distributions + yq_filter = '.distributions[] | select(.name == "@0@") | .packages | join(" ")'.format(distro) + deps = run_command(yq, '-r', yq_filter, + join_paths(meson.source_root(), '.gitlab-ci', 'config.yml')).stdout() + dependencies_config.set('@0@_PACKAGES'.format(distro.to_upper()), deps) +endforeach +endif +configure_file(input: 'dependencies.rst', + output: 'dependencies.rst', + configuration: dependencies_config) # do not use -j, it breaks on Ubuntu sphinx_output_dir = 'Documentation' diff -Nru libinput-1.16.4/doc/user/normalization-of-relative-motion.rst libinput-1.17.2/doc/user/normalization-of-relative-motion.rst --- libinput-1.16.4/doc/user/normalization-of-relative-motion.rst 2020-11-27 01:38:59.349086000 +0000 +++ libinput-1.17.2/doc/user/normalization-of-relative-motion.rst 2021-04-30 04:25:41.518076400 +0000 @@ -27,6 +27,11 @@ movement speed increases, acceleration is applied - at high speeds a low-dpi device will roughly feel the same as a higher-dpi mouse. +The reason for the normalization is convenience: a caller can assume that a +delta of 1 should result in a movement of 1 pixel on a traditional +(low-dpi) screen. On screens with high resolutions, the caller must scale +according to the UI scale factors. + This normalization only applies to accelerated coordinates, unaccelerated coordinates are left in device-units. It is up to the caller to interpret those coordinates correctly. diff -Nru libinput-1.16.4/doc/user/palm-detection.rst libinput-1.17.2/doc/user/palm-detection.rst --- libinput-1.16.4/doc/user/palm-detection.rst 2020-11-27 01:38:59.349086000 +0000 +++ libinput-1.17.2/doc/user/palm-detection.rst 2021-04-30 04:25:41.518076400 +0000 @@ -157,6 +157,11 @@ typing. - Physical buttons work even while the touchpad is disabled. This includes :ref:`software-emulated buttons `. +- libinput pairs touchpads and keyboards for the disable-while-typing + feature. In the most common case, the internal touchpad is paired only + with the internal keyboard. Typing on an external keyboard will thus not + disable the touchpad. Some devices require a :ref:`quirk ` + to be correctly paired. Disable-while-typing can be enabled and disabled by calling **libinput_device_config_dwt_set_enabled()**. diff -Nru libinput-1.16.4/doc/user/reporting-bugs.rst libinput-1.17.2/doc/user/reporting-bugs.rst --- libinput-1.16.4/doc/user/reporting-bugs.rst 2020-11-27 01:38:59.349086000 +0000 +++ libinput-1.17.2/doc/user/reporting-bugs.rst 2021-04-30 04:25:41.519076300 +0000 @@ -305,7 +305,7 @@ Whether the bug fix ends up in your distribution depends on a number of things. Any given bug fix **may** be cherry-picked into the current stable -branch, depending on its severity, impact, and likelyhood to cause +branch, depending on its severity, impact, and likelihood to cause regressions. Once cherry-picked it will land in the next stable branch release. These are usually a few weeks apart. diff -Nru libinput-1.16.4/doc/user/switches.rst libinput-1.17.2/doc/user/switches.rst --- libinput-1.16.4/doc/user/switches.rst 2020-11-27 01:38:59.355086000 +0000 +++ libinput-1.17.2/doc/user/switches.rst 2021-04-30 04:25:41.524076200 +0000 @@ -28,15 +28,17 @@ the device is disabled while the lid is logically closed. This is to avoid ghost touches that can be caused by interference with touchpads and the closed lid. The touchpad is automatically re-enabled whenever the lid is -openend. +opened. This handling of lid switches is transparent to the user, no notifications are sent and the device appears as enabled at all times. On some devices, the device's lid state does not always reflect the physical -state and the lid state may report as closed even when the lid is physicall -open. libinput employs some heuristics to detect user input (specificially -typing) to re-enable the touchpad on those devices. +state and the lid state may report as closed even when the lid is physically +open. libinput employs some heuristics to detect user input (specifically +typing) to re-enable the touchpad on those devices. Where input is detected, +libinput updates the lid status of the kernel device so other consumers of +the kernel events also get the accurate state. .. _switches_tablet_mode: diff -Nru libinput-1.16.4/doc/user/tapping.rst libinput-1.17.2/doc/user/tapping.rst --- libinput-1.16.4/doc/user/tapping.rst 2020-11-27 01:38:59.355086000 +0000 +++ libinput-1.17.2/doc/user/tapping.rst 2021-04-30 04:25:41.524076200 +0000 @@ -49,6 +49,11 @@ **libinput_device_config_tap_set_drag_enabled()**. Most devices have tap-and-drag enabled by default. +.. note:: Dragging is always done with one finger. The number of fingers on + the initial tap decide the type of button click. For example, to + middle-click drag, tap with three fingers followed by a + single-finger drag. + Also optional is a feature called "drag lock". With drag lock disabled, lifting the finger will stop any drag process. When enabled, libinput will ignore a finger up event during a drag process, provided the finger is set down again diff -Nru libinput-1.16.4/doc/user/trackpoint-configuration.rst libinput-1.17.2/doc/user/trackpoint-configuration.rst --- libinput-1.16.4/doc/user/trackpoint-configuration.rst 2020-11-27 01:38:59.356086000 +0000 +++ libinput-1.17.2/doc/user/trackpoint-configuration.rst 2021-04-30 04:25:41.525076400 +0000 @@ -20,7 +20,7 @@ The magic trackpoint multiplier ------------------------------------------------------------------------------ -To accomodate for the wildly different input data on trackpoint, libinput +To accommodate for the wildly different input data on trackpoint, libinput uses a multiplier that is applied to input deltas. Trackpoints that send comparatively high deltas can be "slowed down", trackpoints that send low deltas can be "sped up" to match the expected range. The actual acceleration diff -Nru libinput-1.16.4/doc/user/trackpoints.rst libinput-1.17.2/doc/user/trackpoints.rst --- libinput-1.16.4/doc/user/trackpoints.rst 2020-11-27 01:38:59.356086000 +0000 +++ libinput-1.17.2/doc/user/trackpoints.rst 2021-04-30 04:25:41.525076400 +0000 @@ -5,7 +5,7 @@ ============================================================================== This page provides an overview of trackpoint handling in libinput, also -refered to as Pointing Stick or Trackstick. The device itself is usually a +referred to as Pointing Stick or Trackstick. The device itself is usually a round plastic stick between the G, H and B keys with a set of buttons below the space bar. diff -Nru libinput-1.16.4/meson.build libinput-1.17.2/meson.build --- libinput-1.16.4/meson.build 2020-11-27 01:38:59.360086000 +0000 +++ libinput-1.17.2/meson.build 2021-04-30 04:25:41.527076200 +0000 @@ -1,13 +1,14 @@ project('libinput', 'c', - version : '1.16.4', + version : '1.17.2', license : 'MIT/Expat', default_options : [ 'c_std=gnu99', 'warning_level=2' ], - meson_version : '>= 0.45.0') + meson_version : '>= 0.47.0') libinput_version = meson.project_version().split('.') dir_data = join_paths(get_option('prefix'), get_option('datadir'), 'libinput') -dir_sysconf = join_paths(get_option('prefix'), get_option('sysconfdir'), 'libinput') +dir_etc = join_paths(get_option('prefix'), get_option('sysconfdir')) +dir_overrides = join_paths(get_option('prefix'), get_option('sysconfdir'), 'libinput') dir_libexec = join_paths(get_option('prefix'), get_option('libexecdir'), 'libinput') dir_lib = join_paths(get_option('prefix'), get_option('libdir')) dir_man1 = join_paths(get_option('prefix'), get_option('mandir'), 'man1') @@ -22,8 +23,9 @@ endif dir_udev_callouts = dir_udev dir_udev_rules = join_paths(dir_udev, 'rules.d') -dir_udev_hwdb = join_paths(dir_udev, 'hwdb.d') +# Collection of man pages, we'll append to that +src_man = files() # We use libtool-version numbers because it's easier to understand. # Before making a release, the libinput_so_* @@ -43,19 +45,34 @@ # Compiler setup cc = meson.get_compiler('c') -cppflags = ['-Wno-unused-parameter', '-fvisibility=hidden'] -cflags = cppflags + ['-Wmissing-prototypes', '-Wstrict-prototypes'] -add_project_arguments(cflags, language : 'c') -add_project_arguments(cppflags, language : 'cpp') +cflags = [ + '-Wno-unused-parameter', + '-Wmissing-prototypes', + '-Wstrict-prototypes', + '-Wundef', + '-Wlogical-op', + '-Wpointer-arith', + '-Wuninitialized', + '-Winit-self', + '-Wstrict-prototypes', + '-Wimplicit-fallthrough', + '-Wredundant-decls', + '-Wincompatible-pointer-types', + '-Wformat=2', + '-Wmissing-declarations', + + '-fvisibility=hidden', +] +add_project_arguments(cc.get_supported_arguments(cflags), language : 'c') # config.h config_h = configuration_data() doc_url_base = 'https://wayland.freedesktop.org/libinput/doc' if libinput_version[2].to_int() >= 90 - doc_url = '@0@/latest/'.format(doc_url_base) + doc_url = '@0@/latest'.format(doc_url_base) else - doc_url = '@0@/@1@/'.format(doc_url_base, meson.project_version()) + doc_url = '@0@/@1@'.format(doc_url_base, meson.project_version()) endif config_h.set_quoted('HTTP_DOC_LINK', doc_url) @@ -125,6 +142,9 @@ dep_udev = dependency('libudev') dep_mtdev = dependency('mtdev', version : '>= 1.1.0') dep_libevdev = dependency('libevdev') +config_h.set10('HAVE_LIBEVDEV_DISABLE_PROPERTY', + dep_libevdev.version().version_compare('>= 1.9.902')) + dep_lm = cc.find_library('m', required : false) dep_rt = cc.find_library('rt', required : false) @@ -137,15 +157,7 @@ have_libwacom = get_option('libwacom') config_h.set10('HAVE_LIBWACOM', have_libwacom) if have_libwacom - dep_libwacom = dependency('libwacom', version : '>= 0.20') - - result = cc.has_function('libwacom_get_paired_device', - dependencies: dep_libwacom) - config_h.set10('HAVE_LIBWACOM_GET_PAIRED_DEVICE', result) - - result = cc.has_function('libwacom_get_button_evdev_code', - dependencies: dep_libwacom) - config_h.set10('HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE', result) + dep_libwacom = dependency('libwacom', version : '>= 0.27') else dep_libwacom = declare_dependency() endif @@ -303,7 +315,7 @@ ############ libquirks.a ############# libinput_data_path = dir_data -libinput_data_override_path = join_paths(dir_sysconf, 'local-overrides.quirks') +libinput_data_override_path = join_paths(dir_overrides, 'local-overrides.quirks') config_h.set_quoted('LIBINPUT_QUIRKS_DIR', dir_data) config_h.set_quoted('LIBINPUT_QUIRKS_OVERRIDE_FILE', libinput_data_override_path) @@ -325,6 +337,9 @@ include_directories : includes_include) dep_libquirks = declare_dependency(link_with : libquirks) +# Create /etc/libinput +install_subdir('libinput', install_dir : dir_etc) + ############ libinput.so ############ install_headers('src/libinput.h') src_libinput = src_libfilter + [ @@ -411,13 +426,6 @@ input : 'src/libinput-git-version.h.in', output :'libinput-git-version.h') -if meson.version().version_compare('<0.43.0') - # Restore the SELinux context for the libinput.so.a.b.c on install - # meson bug https://github.com/mesonbuild/meson/issues/1967 - meson.add_install_script('src/libinput-restore-selinux-context.sh', - dir_lib, lib_libinput.full_path()) -endif - ############ documentation ############ if get_option('documentation') @@ -443,10 +451,6 @@ dep_tools_shared = declare_dependency(link_with : lib_tools_shared, dependencies : deps_tools_shared) -man_config = configuration_data() -man_config.set('LIBINPUT_VERSION', meson.project_version()) -man_config.set('LIBINPUT_DATA_DIR', dir_data) - deps_tools = [ dep_tools_shared, dep_libinput ] libinput_debug_events_sources = [ 'tools/libinput-debug-events.c', @@ -459,11 +463,6 @@ install_dir : libinput_tool_path, install : true ) -configure_file(input : 'tools/libinput-debug-events.man', - output : 'libinput-debug-events.1', - configuration : man_config, - install_dir : dir_man1, - ) libinput_debug_tablet_sources = [ 'tools/libinput-debug-tablet.c' ] executable('libinput-debug-tablet', @@ -473,11 +472,6 @@ install_dir : libinput_tool_path, install : true) -configure_file(input : 'tools/libinput-debug-tablet.man', - output : 'libinput-debug-tablet.1', - configuration : man_config, - install_dir : dir_man1, - ) libinput_quirks_sources = [ 'tools/libinput-quirks.c' ] libinput_quirks = executable('libinput-quirks', @@ -493,23 +487,6 @@ suite : ['all'] ) -configure_file(input : 'tools/libinput-quirks.man', - output : 'libinput-quirks.1', - configuration : man_config, - install_dir : dir_man1, - ) -# Same man page for the subtools to stay consistent with the other tools -configure_file(input : 'tools/libinput-quirks.man', - output : 'libinput-quirks-list.1', - configuration : man_config, - install_dir : dir_man1, - ) -configure_file(input : 'tools/libinput-quirks.man', - output : 'libinput-quirks-validate.1', - configuration : man_config, - install_dir : dir_man1, - ) - libinput_list_devices_sources = [ 'tools/libinput-list-devices.c' ] libinput_list_devices = executable('libinput-list-devices', libinput_list_devices_sources, @@ -522,12 +499,6 @@ libinput_list_devices, suite : ['all', 'root', 'hardware']) -configure_file(input : 'tools/libinput-list-devices.man', - output : 'libinput-list-devices.1', - configuration : man_config, - install_dir : dir_man1, - ) - libinput_measure_sources = [ 'tools/libinput-measure.c' ] executable('libinput-measure', libinput_measure_sources, @@ -536,11 +507,6 @@ install_dir : libinput_tool_path, install : true, ) -configure_file(input : 'tools/libinput-measure.man', - output : 'libinput-measure.1', - configuration : man_config, - install_dir : dir_man1, - ) libinput_analyze_sources = [ 'tools/libinput-analyze.c' ] executable('libinput-analyze', @@ -550,52 +516,27 @@ install_dir : libinput_tool_path, install : true, ) -configure_file(input : 'tools/libinput-analyze.man', - output : 'libinput-analyze.1', - configuration : man_config, - install_dir : dir_man1, - ) src_python_tools = files( 'tools/libinput-analyze-per-slot-delta.py', + 'tools/libinput-analyze-recording.py', + 'tools/libinput-analyze-touch-down-state.py', 'tools/libinput-measure-fuzz.py', 'tools/libinput-measure-touchpad-size.py', 'tools/libinput-measure-touchpad-tap.py', 'tools/libinput-measure-touchpad-pressure.py', 'tools/libinput-measure-touch-size.py', + 'tools/libinput-replay.py' ) -config_noop = configuration_data() -# Set a dummy replacement to silence meson warnings: -# meson.build:487: WARNING: Got an empty configuration_data() object and -# found no substitutions in the input file 'foo'. If you -# want to copy a file to the build dir, use the 'copy:' -# keyword argument added in 0.47.0 -config_noop.set('dummy', 'dummy') foreach t : src_python_tools configure_file(input: t, output: '@BASENAME@', - configuration : config_noop, + copy: true, install_dir : libinput_tool_path ) endforeach -src_man = files( - 'tools/libinput-measure-fuzz.man', - 'tools/libinput-measure-touchpad-size.man', - 'tools/libinput-measure-touchpad-tap.man', - 'tools/libinput-measure-touchpad-pressure.man', - 'tools/libinput-measure-touch-size.man', - 'tools/libinput-analyze-per-slot-delta.man', -) - -foreach m : src_man - configure_file(input : m, - output : '@BASENAME@.1', - configuration : man_config, - install_dir : dir_man1) -endforeach - libinput_record_sources = [ 'tools/libinput-record.c', git_version_h ] executable('libinput-record', libinput_record_sources, @@ -604,19 +545,6 @@ install_dir : libinput_tool_path, install : true, ) -configure_file(input : 'tools/libinput-record.man', - output : 'libinput-record.1', - configuration : man_config, - install_dir : dir_man1, - ) - -install_data('tools/libinput-replay', - install_dir : libinput_tool_path) -configure_file(input : 'tools/libinput-replay.man', - output : 'libinput-replay.1', - configuration : man_config, - install_dir : dir_man1, - ) if get_option('debug-gui') dep_gtk = dependency('gtk+-3.0', version : '>= 3.20') @@ -636,11 +564,7 @@ install_dir : libinput_tool_path, install : true ) - configure_file(input : 'tools/libinput-debug-gui.man', - output : 'libinput-debug-gui.1', - configuration : man_config, - install_dir : dir_man1, - ) + src_man += files('tools/libinput-debug-gui.man') endif libinput_sources = [ 'tools/libinput-tool.c' ] @@ -651,11 +575,6 @@ include_directories : [includes_src, includes_include], install : true ) -configure_file(input : 'tools/libinput.man', - output : 'libinput.1', - configuration : man_config, - install_dir : dir_man1, - ) ptraccel_debug_sources = [ 'tools/ptraccel-debug.c' ] executable('ptraccel-debug', @@ -773,6 +692,7 @@ 'test/litest-device-dell-canvas-totem-touch.c', 'test/litest-device-elantech-touchpad.c', 'test/litest-device-elan-tablet.c', + 'test/litest-device-generic-pressurepad.c', 'test/litest-device-generic-singletouch.c', 'test/litest-device-gpio-keys.c', 'test/litest-device-huion-pentablet.c', @@ -780,6 +700,7 @@ 'test/litest-device-ignored-mouse.c', 'test/litest-device-keyboard.c', 'test/litest-device-keyboard-all-codes.c', + 'test/litest-device-keyboard-quirked.c', 'test/litest-device-keyboard-razer-blackwidow.c', 'test/litest-device-keyboard-razer-blade-stealth.c', 'test/litest-device-keyboard-razer-blade-stealth-videoswitch.c', @@ -803,6 +724,7 @@ 'test/litest-device-synaptics-x220.c', 'test/litest-device-synaptics-hover.c', 'test/litest-device-synaptics-i2c.c', + 'test/litest-device-synaptics-pressurepad.c', 'test/litest-device-synaptics-rmi4.c', 'test/litest-device-synaptics-st.c', 'test/litest-device-synaptics-t440.c', @@ -911,8 +833,8 @@ test_utils, suite : ['all']) - libinput_test_runner_sources = litest_sources + [ - 'src/libinput-util.h', + # When adding new files to this list, update the CI + tests_sources = [ 'test/test-udev.c', 'test/test-path.c', 'test/test-pointer.c', @@ -933,31 +855,25 @@ 'test/test-switch.c', 'test/test-quirks.c', ] + libinput_test_runner_sources = litest_sources + tests_sources + [ + 'src/libinput-util.h', + ] libinput_test_runner = executable('libinput-test-suite', libinput_test_runner_sources, include_directories : [includes_src, includes_include], dependencies : deps_litest, install_dir : libinput_tool_path, install : get_option('install-tests')) - configure_file(input : 'test/libinput-test-suite.man', - output : 'libinput-test-suite.1', - configuration : man_config, - install_dir : dir_man1, - ) - # Update this list and the one in litest.c when new group names are - # required - groups = [ - 'config', 'context', 'device', 'events', 'gestures', 'keyboard', 'lid', - 'log', 'misc', 'pad', 'path', 'pointer', 'quirks', 'switch', 'tablet', - 'tablet-mode', 'tap', 'timer', 'totem', 'touch', 'touchpad', 'trackball', - 'trackpoint', 'udev', - ] - foreach group : groups + src_man += 'test/libinput-test-suite.man' + + foreach testfile : tests_sources + tfile = testfile.split('test/test-')[1] + group = tfile.split('.c')[0] test('libinput-test-suite-@0@'.format(group), libinput_test_runner, suite : ['all', 'valgrind', 'root', 'hardware'], - args : ['--filter-group=@0@:*'.format(group), + args : ['--filter-group=@0@'.format(group), '--xml-output=junit-@0@-XXXXXX.xml'.format(group)], is_parallel : false, timeout : 1200) @@ -987,5 +903,50 @@ configure_file(output : 'litest-config.h', configuration : litest_config_h) endif + + +############ man pages ############ +man_config = configuration_data() +man_config.set('LIBINPUT_VERSION', meson.project_version()) +man_config.set('LIBINPUT_DATA_DIR', dir_data) +src_man += files( + 'tools/libinput.man', + 'tools/libinput-analyze.man', + 'tools/libinput-analyze-per-slot-delta.man', + 'tools/libinput-analyze-recording.man', + 'tools/libinput-analyze-touch-down-state.man', + 'tools/libinput-debug-events.man', + 'tools/libinput-debug-tablet.man', + 'tools/libinput-list-devices.man', + 'tools/libinput-measure.man', + 'tools/libinput-measure-fuzz.man', + 'tools/libinput-measure-touchpad-size.man', + 'tools/libinput-measure-touchpad-tap.man', + 'tools/libinput-measure-touchpad-pressure.man', + 'tools/libinput-measure-touch-size.man', + 'tools/libinput-quirks.man', + 'tools/libinput-record.man', + 'tools/libinput-replay.man', +) + +foreach m : src_man + configure_file(input : m, + output : '@BASENAME@.1', + configuration : man_config, + install_dir : dir_man1) +endforeach + +# Same man page for the subtools to stay consistent with the other tools +configure_file(input : 'tools/libinput-quirks.man', + output : 'libinput-quirks-list.1', + configuration : man_config, + install_dir : dir_man1, + ) +configure_file(input : 'tools/libinput-quirks.man', + output : 'libinput-quirks-validate.1', + configuration : man_config, + install_dir : dir_man1, + ) + ############ output files ############ configure_file(output : 'config.h', configuration : config_h) diff -Nru libinput-1.16.4/quirks/30-vendor-microsoft.quirks libinput-1.17.2/quirks/30-vendor-microsoft.quirks --- libinput-1.16.4/quirks/30-vendor-microsoft.quirks 2020-11-27 01:38:59.362086000 +0000 +++ libinput-1.17.2/quirks/30-vendor-microsoft.quirks 2021-04-30 04:25:41.527076200 +0000 @@ -5,9 +5,14 @@ MatchDMIModalias=dmi:*svnMicrosoftCorporation:pnSurface3:* AttrLidSwitchReliability=write_open -[Microsoft Surface 3 Type Cover Keyboard] -MatchName=*Microsoft Surface Type Cover Keyboard* -MatchDMIModalias=dmi:*svnMicrosoftCorporation:pnSurface3:* +# Matches both Surface Laptop keyboards as well as type covers. +# i.e. +# - Surface 3: Microsoft Surface 3 Type Cover Keyboard +# - Surface Laptop 3: Microsoft Surface 045E:09AE Keyboard +# - Surface Book 2: Microsoft Surface Keyboard +[Microsoft Surface Keyboard] +MatchName=*Microsoft Surface *Keyboard* +MatchDMIModalias=dmi:*svnMicrosoftCorporation:* AttrKeyboardIntegration=internal [Microsoft Nano Transceiver v2.0] diff -Nru libinput-1.16.4/quirks/30-vendor-razer.quirks libinput-1.17.2/quirks/30-vendor-razer.quirks --- libinput-1.16.4/quirks/30-vendor-razer.quirks 2020-11-27 01:38:59.363086000 +0000 +++ libinput-1.17.2/quirks/30-vendor-razer.quirks 2021-04-30 04:25:41.527076200 +0000 @@ -14,6 +14,13 @@ MatchProduct=0x0233 AttrKeyboardIntegration=internal +[Razer Blade Stealth Keyboard] +MatchUdevType=keyboard +MatchBus=usb +MatchVendor=0x1532 +MatchProduct=0x0252 +AttrKeyboardIntegration=internal + [Razer Blade Lid Switch] MatchName=*Lid Switch* MatchDMIModalias=dmi:*svnRazer:pnBlade* diff -Nru libinput-1.16.4/quirks/50-system-apple.quirks libinput-1.17.2/quirks/50-system-apple.quirks --- libinput-1.16.4/quirks/50-system-apple.quirks 2020-11-27 01:38:59.363086000 +0000 +++ libinput-1.17.2/quirks/50-system-apple.quirks 2021-04-30 04:25:41.527076200 +0000 @@ -27,6 +27,12 @@ MatchName=*Apple Inc. Apple Internal Keyboard* AttrKeyboardIntegration=internal +[Apple Internal Keyboard (SPI)] +MatchUdevType=keyboard +MatchBus=spi +MatchVendor=0x5AC +AttrKeyboardIntegration=internal + # The Apple MagicMouse has a touchpad built-in but the kernel still # emulates a full 2/3 button mouse for us. Ignore anything from the # ABS interface @@ -89,3 +95,22 @@ MatchVendor=0x5AC MatchProduct=0x0262 AttrPalmSizeThreshold=1600 + +[Apple Laptop Touchpad (SPI)] +MatchUdevType=touchpad +MatchBus=spi +MatchVendor=0x5AC +ModelAppleTouchpad=1 +AttrSizeHint=104x75 +AttrTouchSizeRange=150:130 +AttrPalmSizeThreshold=1600 + +# The Linux applespi driver currently uses the Synaptics vendor for some reason +[Apple Laptop Touchpad (SPI)] +MatchUdevType=touchpad +MatchBus=spi +MatchVendor=0x6CB +ModelAppleTouchpad=1 +AttrSizeHint=104x75 +AttrTouchSizeRange=150:130 +AttrPalmSizeThreshold=1600 diff -Nru libinput-1.16.4/quirks/50-system-dell.quirks libinput-1.17.2/quirks/50-system-dell.quirks --- libinput-1.16.4/quirks/50-system-dell.quirks 2020-11-27 01:38:59.363086000 +0000 +++ libinput-1.17.2/quirks/50-system-dell.quirks 2021-04-30 04:25:41.528076400 +0000 @@ -11,7 +11,19 @@ MatchDMIModalias=dmi:*svnDellInc.:* AttrMscTimestamp=watch -[Dell Lattitude E6220 Touchpad] +[Dell Inspiron 15R N5110 Touchpad] +MatchUdevType=touchpad +MatchName=*AlpsPS/2 ALPS GlidePoint +MatchDMIModalias=dmi:*svnDellInc.:*pnInspironN5110* +AttrPressureRange=100:95 + +[Dell Latitude E5510 Touchpad] +MatchUdevType=touchpad +MatchName=*AlpsPS/2 ALPS GlidePoint +MatchDMIModalias=dmi:*svnDellInc.:pnLatitudeE5510:* +AttrPressureRange=100:90 + +[Dell Latitude E6220 Touchpad] MatchName=*AlpsPS/2 ALPS GlidePoint MatchDMIModalias=dmi:*svnDellInc.:pnLatitudeE6220:* AttrPressureRange=100:90 @@ -28,6 +40,11 @@ AttrPressureRange=15:10 AttrPalmPressureThreshold=150 +[Dell XPS 15 9500 Touchpad] +MatchName=* Touchpad +MatchDMIModalias=dmi:*svnDellInc.:pnXPS159500:* +ModelTouchpadVisibleMarker=0 + [Dell Latitude D620 Trackpoint] MatchName=*DualPoint Stick MatchDMIModalias=dmi:*svnDellInc.:pnLatitudeD620* @@ -65,6 +82,18 @@ MatchDMIModalias=dmi:*svnDellInc.:pnLatitudeE7470* AttrTrackpointMultiplier=0.125 +[Latitude 7490 Trackpoint] +MatchName=*Mouse +MatchUdevType=pointingstick +MatchDMIModalias=dmi:**bvnDellInc.:*:pnLatitude7490* +AttrTrackpointMultiplier=0.3 + +[Precision 7x50 Touchpad] +MatchBus=i2c +MatchUdevType=touchpad +MatchDMIModalias=dmi:*svnDellInc.:pnPrecision7?50* +AttrInputPropDisable=INPUT_PROP_BUTTONPAD + # The touch device has the same vid/pid as the totem, the MatchName # directive is required here [Canvas Totem] diff -Nru libinput-1.16.4/quirks/50-system-gigabyte.quirks libinput-1.17.2/quirks/50-system-gigabyte.quirks --- libinput-1.16.4/quirks/50-system-gigabyte.quirks 1970-01-01 00:00:00.000000000 +0000 +++ libinput-1.17.2/quirks/50-system-gigabyte.quirks 2021-04-30 04:25:41.528076400 +0000 @@ -0,0 +1,5 @@ +[Gigabyte Aero 15 touchpad] +MatchUdevType=touchpad +MatchName=ETPS/2 Elantech Touchpad +MatchDMIModalias=dmi:*svnGIGABYTE:pnAERO15-XA* +AttrPalmSizeThreshold=800 diff -Nru libinput-1.16.4/quirks/50-system-google.quirks libinput-1.17.2/quirks/50-system-google.quirks --- libinput-1.16.4/quirks/50-system-google.quirks 2020-11-27 01:38:59.364086200 +0000 +++ libinput-1.17.2/quirks/50-system-google.quirks 2021-04-30 04:25:41.528076400 +0000 @@ -89,7 +89,7 @@ [Google Chromebook Eve] MatchUdevType=touchpad -MatchName=ACPI0C50:00 18D1:5028 +MatchName=ACPI0C50:00 18D1:5028* MatchDMIModalias=dmi:*svnGoogle:pnEve* ModelChromebook=1 AttrPressureRange=6:4 diff -Nru libinput-1.16.4/quirks/50-system-hp.quirks libinput-1.17.2/quirks/50-system-hp.quirks --- libinput-1.16.4/quirks/50-system-hp.quirks 2020-11-27 01:38:59.364086200 +0000 +++ libinput-1.17.2/quirks/50-system-hp.quirks 2021-04-30 04:25:41.528076400 +0000 @@ -14,15 +14,17 @@ MatchDMIModalias=dmi:*svnHewlett-Packard:*pnHPCompaq8510w* AttrEventCodeDisable=BTN_TOOL_DOUBLETAP;BTN_TOOL_TRIPLETAP; -[HP Pavillion dmi4] +[HP Pavilion dmi4] MatchName=*SynPS/2 Synaptics TouchPad MatchDMIModalias=dmi:*svnHewlett-Packard:*pnHPPaviliondm4NotebookPC* ModelHPPavilionDM4Touchpad=1 +# Touchpad is a clickpad but INPUT_PROP_BUTTONPAD is not set, see +# https://bugs.freedesktop.org/show_bug.cgi?id=97147 [HP Stream 11] -MatchName=SYN1EDE:00 06CB:7442 +MatchName=SYN1EDE:00 06CB:7442* MatchDMIModalias=dmi:*svnHewlett-Packard:pnHPStreamNotebookPC11* -ModelHPStream11Touchpad=1 +AttrInputPropEnable=INPUT_PROP_BUTTONPAD # The HP stream x360's embedded-controller filters out events form its builtin # keyboard when in tablet-mode itself; and it has a capacitive home-button @@ -44,7 +46,7 @@ MatchDMIModalias=dmi:*svnHewlett-Packard*:pnFalco* AttrPressureRange=12:8 -[HP Spectre x360 Convertable 15-bl1xx] +[HP Spectre x360 Convertible 15-bl1xx] MatchUdevType=touchpad MatchName=*SynPS/2 Synaptics TouchPad MatchDMIModalias=dmi:*svnHP:pnHPSpectrex360Convertible15-bl1XX:* @@ -52,7 +54,7 @@ AttrThumbPressureThreshold=90 AttrPalmPressureThreshold=100 -[HP Spectre x360 Convertable 15-ch0xx] +[HP Spectre x360 Convertible 15-ch0xx] MatchUdevType=touchpad MatchName=*SynPS/2 Synaptics TouchPad MatchDMIModalias=dmi:*svnHP:pnHPSpectrex360Convertible15-ch0xx:* @@ -76,4 +78,4 @@ MatchUdevType=keyboard MatchBus=ps2 MatchDMIModalias=dmi:*svnHP:pnHPElitex21013G3:* -AttrKeyboardIntegration=external \ No newline at end of file +AttrKeyboardIntegration=external diff -Nru libinput-1.16.4/quirks/50-system-lenovo.quirks libinput-1.17.2/quirks/50-system-lenovo.quirks --- libinput-1.16.4/quirks/50-system-lenovo.quirks 2020-11-27 01:38:59.364086200 +0000 +++ libinput-1.17.2/quirks/50-system-lenovo.quirks 2021-04-30 04:25:41.528076400 +0000 @@ -31,25 +31,31 @@ MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadT480:* AttrTrackpointMultiplier=0.4 +# Touchpad is a clickpad but INPUT_PROP_BUTTONPAD is not set, see +# https://gitlab.freedesktop.org/libinput/libinput/issues/177 [Lenovo T480s Touchpad] MatchName=Elan Touchpad MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadT480s* -ModelLenovoT480sTouchpad=1 +AttrInputPropEnable=INPUT_PROP_BUTTONPAD +# Touchpad is a clickpad but INPUT_PROP_BUTTONPAD is not set, see +# https://gitlab.freedesktop.org/libinput/libinput/issues/177 [Lenovo T490s Touchpad] MatchName=Elan Touchpad MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadT490s* -ModelLenovoT490sTouchpad=1 +AttrInputPropEnable=INPUT_PROP_BUTTONPAD [Lenovo T490s Trackpoint] MatchName=*TPPS/2 IBM TrackPoint MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadT490s:* AttrTrackpointMultiplier=0.4 +# Touchpad is a clickpad but INPUT_PROP_BUTTONPAD is not set, see +# https://gitlab.freedesktop.org/libinput/libinput/issues/234 [Lenovo L380 Touchpad] MatchName=Elan Touchpad MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadL380* -ModelLenovoL380Touchpad=1 +AttrInputPropEnable=INPUT_PROP_BUTTONPAD [Lenovo X200 Trackpoint] MatchName=*TPPS/2 IBM TrackPoint @@ -130,6 +136,14 @@ MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadX1Yoga1st:* AttrTrackpointMultiplier=1.25 +# A true pressurepad so let's not use pressure for contact size +# https://gitlab.freedesktop.org/libinput/libinput/-/issues/562 +[Lenovo Yoga 9i Pressurepad] +MatchBus=i2c +MatchVendor=0x06CB +MatchProduct=0xCE37 +AttrEventCodeDisable=ABS_MT_PRESSURE;ABS_PRESSURE; + # Lenovo Carbon X1 6th gen (RMI4 only, PS/2 is broken on this device, # sends bogus ABS_MT_TOOL_TYPE events for MT_TOOL_PALM [Lenovo Carbon X1 6th gen] @@ -191,3 +205,28 @@ MatchName=AT Raw Set 2 keyboard MatchDMIModalias=dmi:*svnLENOVO:*pvrThinkPadX1Tablet:* ModelTabletModeNoSuspend=1 + +# Misidentified as an external keyboard by libinput +# Tested on Legion 5 15AR05H +[Lenovo Legion 5 Keyboard] +MatchUdevType=keyboard +MatchBus=usb +MatchVendor=0x048D +MatchProduct=0xC100 +AttrKeyboardIntegration=internal + +[Lenovo Legion 5 Keyboard] +MatchUdevType=keyboard +MatchBus=usb +MatchVendor=0x048D +MatchProduct=0xC955 +AttrKeyboardIntegration=internal + +# https://gitlab.freedesktop.org/libinput/libinput/-/issues/604 +[Lenovo Yoga Slim 9 14ITL5 Pressurepad] +MatchBus=i2c +MatchVendor=0x27C6 +MatchProduct=0x01E8 +AttrEventCodeDisable=ABS_MT_PRESSURE;ABS_PRESSURE; + + diff -Nru libinput-1.16.4/quirks/README.md libinput-1.17.2/quirks/README.md --- libinput-1.16.4/quirks/README.md 2020-11-27 01:38:59.364086200 +0000 +++ libinput-1.17.2/quirks/README.md 2021-04-30 04:25:41.528076400 +0000 @@ -1,4 +1,5 @@ -= libinput data file format = +libinput quirks file format +=========================== This directory contains hardware quirks used by libinput to work around bugs in the hardware, device behavior and to supply information not obtained @@ -6,28 +7,36 @@ **THIS IS NOT STABLE API** -The data format may change at any time. If your data file is not part of the -libinput git tree, do not expect it to work after an update. Absolutely no -guarantees are made for backwards-compatibility. +The data format may change at any time. If your quirks file is not part of +the libinput git tree, do not expect it to work after an update. Absolutely +no guarantees are made for backwards-compatibility. **THIS IS NOT A CONFIGURATION API** Use the `libinput_device_config_foo()` functions for device configuration. -The quirks are hardware quirks only. +Quirks here are hardware quirks only. -== Data file naming == +Data file naming +---------------- Data files are read in versionsort order, read order determines how values -override each other. A values read later override previously values. The -current structure is 10-generic-foo.quirks for generic settings, -30-vendor-foo.quirks for vendor-specific settings and 50-system-foo.quirks -for system vendors. This is not a fixed naming scheme and may change at any -time. It's an approximation only because some vendors are also system -vendors, e.g. Microsoft makes devices and laptops. +override each other. Values read later override previously read values. The +current structure is: +- `10-generic-foo.quirks` for generic settings, +- `30-vendor-foo.quirks` for vendor-specific settings, and +- `50-system-foo.quirks` for system vendors. + +This is not a fixed naming scheme and may change at any time. It's an +approximation only because some vendors are also system vendors, e.g. +Microsoft makes devices and laptops. + +Laptop-specific quirks should always go into the laptop vendor's file even +where they apply to a component of a different vendor. For example, a quirk +for a Synaptics touchpad specific to a Dell laptop should go into the Dell +quirks file. -Laptop-specific quirks should always go into the laptop vendor's file. - -== Sections, matches and values == +Sections, matches and values +---------------------------- A data file must contain at least one section, each section must have at least one `Match` tag and at least one of either `Attr` or `Model`. Section @@ -54,24 +63,29 @@ All `Attr` tag values are specific to that attribute. -== Parser errors == +Parser errors +------------- + +The following requirements must be met: -The following will cause parser errors and are considered invalid data -files: +* No whitespace is allowed at the beginning of the line +* A Section must have at least one `Match*` entry +* A Section must not repeat `Match*` entry +* A Section must have at least one of `Model*` or `Attr*` entries +* A `Model` tag may only have the value `1` or `0` +* String properties must not be enclosed in quotes +* Hex numbers must use uppercase letters (e.g. `0x12AB`) -* Whitespace at the beginning of the line -* Sections without at least one `Match*` entry -* Sections with the same `Match*` entry repeated -* Sections without at least one of `Model*` or `Attr` entries -* A `Model` tag with a value other than `1` or `0` -* A string property with enclosing quotes +Failure to meet these requirements will cause a parser error and the quirks +files will not be used. -== Debugging == +Debugging +--------- When modifying a data file, use the `libinput list-quirks` tool to verify the changes. The tool can be pointed at the data directory to analyse, use `--verbose` to get more info. For example: ``` -libinput list-quirks --data-dir /path/to/git/repo/data/ --verbose /dev/input/event0 +libinput list-quirks --data-dir /path/to/git/repo/quirks/ --verbose /dev/input/event0 ``` diff -Nru libinput-1.16.4/src/evdev.c libinput-1.17.2/src/evdev.c --- libinput-1.16.4/src/evdev.c 2020-11-27 01:38:59.371086100 +0000 +++ libinput-1.17.2/src/evdev.c 2021-04-30 04:25:41.531076400 +0000 @@ -763,8 +763,8 @@ if (evdev->scroll.lock_state == BUTTONSCROLL_LOCK_DISABLED) return LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED; - else - return LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED; + + return LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED; } static enum libinput_config_scroll_button_lock_state @@ -1024,6 +1024,7 @@ { struct libinput *libinput = evdev_libinput_context(device); uint32_t tdelta; + uint64_t eventtime = input_event_time(ev); /* if we have a current libinput_dispatch() snapshot, compare our * event time with the one from the snapshot. If we have more than @@ -1031,10 +1032,11 @@ * where there is no steady event flow and thus SYN_DROPPED may not * get hit by the kernel despite us being too slow. */ - if (libinput->dispatch_time == 0) + if (libinput->dispatch_time == 0 || + eventtime > libinput->dispatch_time) return; - tdelta = us2ms(libinput->dispatch_time - input_event_time(ev)); + tdelta = us2ms(libinput->dispatch_time - eventtime); if (tdelta > 10) { evdev_log_bug_client_ratelimit(device, &device->delay_warning_limit, @@ -1806,7 +1808,9 @@ evdev_log_info(device, "device is an accelerometer, ignoring\n"); return NULL; - } else if (udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER) { + } + + if (udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER) { evdev_disable_accelerometer_axes(device); } @@ -1853,7 +1857,9 @@ evdev_log_info(device, "device is a tablet pad\n"); return dispatch; - } else if ((udev_tags & tablet_tags) == EVDEV_UDEV_TAG_TABLET) { + } + + if ((udev_tags & tablet_tags) == EVDEV_UDEV_TAG_TABLET) { dispatch = evdev_tablet_create(device); device->seat_caps |= EVDEV_DEVICE_TABLET; evdev_log_info(device, "device is a tablet\n"); @@ -2050,23 +2056,10 @@ struct quirks_context *quirks; struct quirks *q; const struct quirk_tuples *t; + const uint32_t *props = NULL; + size_t nprops = 0; char *prop; - /* Touchpad is a clickpad but INPUT_PROP_BUTTONPAD is not set, see - * fdo bug 97147. Remove when RMI4 is commonplace */ - if (evdev_device_has_model_quirk(device, QUIRK_MODEL_HP_STREAM11_TOUCHPAD)) - libevdev_enable_property(device->evdev, - INPUT_PROP_BUTTONPAD); - - /* Touchpad is a clickpad but INPUT_PROP_BUTTONPAD is not set, see - * https://gitlab.freedesktop.org/libinput/libinput/issues/177 and - * https://gitlab.freedesktop.org/libinput/libinput/issues/234 */ - if (evdev_device_has_model_quirk(device, QUIRK_MODEL_LENOVO_T480S_TOUCHPAD) || - evdev_device_has_model_quirk(device, QUIRK_MODEL_LENOVO_T490S_TOUCHPAD) || - evdev_device_has_model_quirk(device, QUIRK_MODEL_LENOVO_L380_TOUCHPAD)) - libevdev_enable_property(device->evdev, - INPUT_PROP_BUTTONPAD); - /* Touchpad claims to have 4 slots but only ever sends 2 * https://bugs.freedesktop.org/show_bug.cgi?id=98100 */ if (evdev_device_has_model_quirk(device, QUIRK_MODEL_HP_ZBOOK_STUDIO_G3)) @@ -2083,12 +2076,36 @@ libevdev_disable_event_code(device->evdev, EV_MSC, MSC_TIMESTAMP); } - if (q && quirks_get_tuples(q, QUIRK_ATTR_EVENT_CODE_DISABLE, &t)) { - int type, code; + if (quirks_get_tuples(q, QUIRK_ATTR_EVENT_CODE_ENABLE, &t)) { + for (size_t i = 0; i < t->ntuples; i++) { + const struct input_absinfo absinfo = { + .minimum = 0, + .maximum = 1, + }; + + int type = t->tuples[i].first; + int code = t->tuples[i].second; + if (code == EVENT_CODE_UNDEFINED) + libevdev_enable_event_type(device->evdev, type); + else + libevdev_enable_event_code(device->evdev, + type, + code, + type == EV_ABS ? &absinfo : NULL); + evdev_log_debug(device, + "quirks: enabling %s %s (%#x %#x)\n", + libevdev_event_type_get_name(type), + libevdev_event_code_get_name(type, code), + type, + code); + } + } + + if (quirks_get_tuples(q, QUIRK_ATTR_EVENT_CODE_DISABLE, &t)) { for (size_t i = 0; i < t->ntuples; i++) { - type = t->tuples[i].first; - code = t->tuples[i].second; + int type = t->tuples[i].first; + int code = t->tuples[i].second; if (code == EVENT_CODE_UNDEFINED) libevdev_disable_event_type(device->evdev, @@ -2106,8 +2123,40 @@ } } - quirks_unref(q); + if (quirks_get_uint32_array(q, + QUIRK_ATTR_INPUT_PROP_ENABLE, + &props, + &nprops)) { + for (size_t idx = 0; idx < nprops; idx++) { + unsigned int p = props[idx]; + libevdev_enable_property(device->evdev, p); + evdev_log_debug(device, + "quirks: enabling %s (%#x)\n", + libevdev_property_get_name(p), + p); + } + } + if (quirks_get_uint32_array(q, + QUIRK_ATTR_INPUT_PROP_DISABLE, + &props, + &nprops)) { +#if HAVE_LIBEVDEV_DISABLE_PROPERTY + for (size_t idx = 0; idx < nprops; idx++) { + unsigned int p = props[idx]; + libevdev_disable_property(device->evdev, p); + evdev_log_debug(device, + "quirks: disabling %s (%#x)\n", + libevdev_property_get_name(p), + p); + } +#else + evdev_log_error(device, + "quirks: a quirk for this device requires newer libevdev than installed\n"); +#endif + } + + quirks_unref(q); } static void diff -Nru libinput-1.16.4/src/evdev-debounce.c libinput-1.17.2/src/evdev-debounce.c --- libinput-1.16.4/src/evdev-debounce.c 2020-11-27 01:38:59.365086000 +0000 +++ libinput-1.17.2/src/evdev-debounce.c 2021-04-30 04:25:41.528076400 +0000 @@ -162,7 +162,7 @@ fallback->debounce.spurious_enabled = true; evdev_log_info(fallback->device, "Enabling spurious button debouncing, " - "see %sbutton-debouncing.html for details\n", + "see %s/button-debouncing.html for details\n", HTTP_DOC_LINK); } diff -Nru libinput-1.16.4/src/evdev.h libinput-1.17.2/src/evdev.h --- libinput-1.16.4/src/evdev.h 2020-11-27 01:38:59.371086100 +0000 +++ libinput-1.17.2/src/evdev.h 2021-04-30 04:25:41.531076400 +0000 @@ -1003,7 +1003,7 @@ log_info_ratelimit(evdev_libinput_context(device), &device->abs.warning_range.range_warn_limit, "Axis %#x value %d is outside expected range [%d, %d]\n" - "See %sabsolute_coordinate_ranges.html for details\n", + "See %s/absolute_coordinate_ranges.html for details\n", code, value, min, max, HTTP_DOC_LINK); } diff -Nru libinput-1.16.4/src/evdev-mt-touchpad-buttons.c libinput-1.17.2/src/evdev-mt-touchpad-buttons.c --- libinput-1.16.4/src/evdev-mt-touchpad-buttons.c 2020-11-27 01:38:59.366086000 +0000 +++ libinput-1.17.2/src/evdev-mt-touchpad-buttons.c 2021-04-30 04:25:41.529076300 +0000 @@ -794,7 +794,8 @@ if (!tp->buttons.is_clickpad) return LIBINPUT_CONFIG_CLICK_METHOD_NONE; - else if (evdev_device_has_model_quirk(device, QUIRK_MODEL_APPLE_TOUCHPAD)) + + if (evdev_device_has_model_quirk(device, QUIRK_MODEL_APPLE_TOUCHPAD)) return LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; return LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; @@ -1286,8 +1287,7 @@ if (tp->buttons.is_clickpad || tp->device->model_flags & EVDEV_MODEL_APPLE_TOUCHPAD_ONEBUTTON) return tp_post_clickpadbutton_buttons(tp, time); - else - return tp_post_physical_buttons(tp, time); + return tp_post_physical_buttons(tp, time); } bool diff -Nru libinput-1.16.4/src/evdev-mt-touchpad.c libinput-1.17.2/src/evdev-mt-touchpad.c --- libinput-1.16.4/src/evdev-mt-touchpad.c 2020-11-27 01:38:59.369086000 +0000 +++ libinput-1.17.2/src/evdev-mt-touchpad.c 2021-04-30 04:25:41.530076300 +0000 @@ -153,7 +153,7 @@ * human can move like that within thresholds. * * We encode left moves as zeroes, and right as ones. We also drop - * the array to all zeroes when contraints are not satisfied. Then we + * the array to all zeroes when constraints are not satisfied. Then we * search for the pattern {1,0,1}. It can't match {Left, Right, Left}, * but it does match {Left, Right, Left, Right}, so it's okay. * @@ -201,7 +201,7 @@ tp->hysteresis.enabled = true; evdev_log_debug(tp->device, "hysteresis enabled. " - "See %stouchpad-jitter.html for details\n", + "See %s/touchpad-jitter.html for details\n", HTTP_DOC_LINK); } } @@ -256,8 +256,9 @@ if (tp->fake_touches & FAKE_FINGER_OVERFLOW) return FAKE_FINGER_OVERFLOW; - else /* don't count BTN_TOUCH */ - return ffs(tp->fake_touches >> 1); + + /* don't count BTN_TOUCH */ + return ffs(tp->fake_touches >> 1); } static inline bool @@ -610,7 +611,7 @@ (tp->nfingers_down == tp->num_slots && nfake_touches == tp->num_slots)) return; - /* Synaptics devices may end touch 2 on transition to/fro + /* Synaptics devices may end touch 2 on transition to/from * BTN_TOOL_TRIPLETAP and start it again on the next frame with * different coordinates (bz#91352, gitlab#434). We search the * touches we have, if there is one that has just ended despite us @@ -898,7 +899,9 @@ t->palm.state = PALM_TYPING; t->palm.first = t->point; return true; - } else if (!tp->dwt.keyboard_active && + } + + if (!tp->dwt.keyboard_active && t->state == TOUCH_UPDATE && t->palm.state == PALM_TYPING) { /* If a touch has started before the first or after the last @@ -932,7 +935,9 @@ tp->palm.trackpoint_active) { t->palm.state = PALM_TRACKPOINT; return true; - } else if (t->palm.state == PALM_TRACKPOINT && + } + + if (t->palm.state == PALM_TRACKPOINT && t->state == TOUCH_UPDATE && !tp->palm.trackpoint_active) { @@ -1074,7 +1079,9 @@ t->index); } return false; - } else if (tp_palm_detect_multifinger(tp, t, time)) { + } + + if (tp_palm_detect_multifinger(tp, t, time)) { return false; } @@ -1527,10 +1534,10 @@ if (tp->device->model_flags & EVDEV_MODEL_TEST_DEVICE) reference_interval = tdelta; - /* If the last frame is more than 25ms ago, we have irregular + /* If the last frame is more than 30ms ago, we have irregular * frames, who knows what's a pointer jump here and what's * legitimate movement.... */ - if (tdelta > 2 * reference_interval || tdelta == 0) + if (tdelta > 2.5 * reference_interval || tdelta == 0) return false; /* We historically expected ~12ms frame intervals, so the numbers @@ -1632,7 +1639,7 @@ SYN_REPORT +8ms Our approach is to detect the 0 timestamp, check the interval on - the next event and then calculate the movement for one fictious + the next event and then calculate the movement for one fictitious event instead, swallowing all other movements. So if the time delta is equivalent to 10 events and the movement is x, we instead pretend there was movement of x/10. @@ -1747,7 +1754,7 @@ evdev_log_bug_kernel_ratelimit(tp->device, &tp->jump.warning, "Touch jump detected and discarded.\n" - "See %stouchpad-jumping-cursors.html for details\n", + "See %s/touchpad-jumping-cursors.html for details\n", HTTP_DOC_LINK); tp_motion_history_reset(t); } @@ -2340,7 +2347,8 @@ considered a happy couple */ if (touchpad->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD) return vendor_tp == vendor_kbd && product_tp == product_kbd; - else if (keyboard->tags & EVDEV_TAG_INTERNAL_KEYBOARD) + + if (keyboard->tags & EVDEV_TAG_INTERNAL_KEYBOARD) return true; /* keyboard is not tagged as internal keyboard and it's not part of @@ -2697,14 +2705,16 @@ if (streq(prop, "internal")) { evdev_tag_touchpad_internal(device); return; - } else if (streq(prop, "external")) { + } + + if (streq(prop, "external")) { evdev_tag_touchpad_external(device); return; - } else { - evdev_log_info(device, - "tagged with unknown value %s\n", - prop); } + + evdev_log_info(device, + "tagged with unknown value %s\n", + prop); } /* The hwdb is the authority on integration, these heuristics are @@ -2963,7 +2973,7 @@ * Normalize motion events to the default mouse DPI as base * (unaccelerated) speed. This also evens out any differences in x * and y resolution, so that a circle on the - * touchpad does not turn into an elipse on the screen. + * touchpad does not turn into an ellipse on the screen. */ tp->accel.x_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_x; tp->accel.y_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_y; @@ -3231,8 +3241,6 @@ tp->dwt.config.get_default_enabled = tp_dwt_config_get_default; tp->dwt.dwt_enabled = tp_dwt_default_enabled(tp); device->base.config.dwt = &tp->dwt.config; - - return; } static inline void @@ -3486,7 +3494,7 @@ if (tp->hysteresis.enabled) evdev_log_debug(tp->device, "hysteresis enabled. " - "See %stouchpad-jitter.html for details\n", + "See %s/touchpad-jitter.html for details\n", HTTP_DOC_LINK); } @@ -3602,6 +3610,26 @@ return rc; } +static void +tp_init_pressurepad(struct tp_dispatch *tp, + struct evdev_device *device) +{ + /* On traditional touchpads, the pressure value equals contact + * size. On PressurePads, pressure is a real physical axis for the + * force down. So we disable it here because we don't do anything + * with it anyway and using it for touch size messes things up. + * + * The kernel/udev set the resolution to non-zero on those devices + * to indicate that the value is in a known axis space. + * + * See also #562 + */ + if (libevdev_get_abs_resolution(device->evdev, ABS_MT_PRESSURE) != 0) { + libevdev_disable_event_code(device->evdev, EV_ABS, ABS_MT_PRESSURE); + libevdev_disable_event_code(device->evdev, EV_ABS, ABS_PRESSURE); + } +} + static int tp_init(struct tp_dispatch *tp, struct evdev_device *device) @@ -3617,10 +3645,12 @@ return false; tp_init_default_resolution(tp, device); + tp_init_pressurepad(tp, device); if (!tp_init_slots(tp, device)) return false; + evdev_device_init_abs_range_warnings(device); use_touch_size = tp_init_touch_size(tp, device); diff -Nru libinput-1.16.4/src/evdev-mt-touchpad-gestures.c libinput-1.17.2/src/evdev-mt-touchpad-gestures.c --- libinput-1.16.4/src/evdev-mt-touchpad-gestures.c 2020-11-27 01:38:59.367086200 +0000 +++ libinput-1.17.2/src/evdev-mt-touchpad-gestures.c 2021-04-30 04:25:41.529076300 +0000 @@ -383,8 +383,7 @@ if (!tp->gesture.enabled) { if (ntouches == 2) return GESTURE_STATE_SCROLL; - else - return GESTURE_STATE_NONE; + return GESTURE_STATE_NONE; } first = touches[0]; @@ -525,9 +524,8 @@ if (tp->gesture.finger_count == 2) { tp_gesture_set_scroll_buildup(tp); return GESTURE_STATE_SCROLL; - } else { - return GESTURE_STATE_SWIPE; } + return GESTURE_STATE_SWIPE; } /* If one touch exceeds the max_move threshold while the other has not @@ -589,7 +587,9 @@ if (tp->gesture.finger_count == 2) { tp_gesture_set_scroll_buildup(tp); return GESTURE_STATE_SCROLL; - } else if (tp->gesture.enabled) { + } + + if (tp->gesture.enabled) { return GESTURE_STATE_SWIPE; } } diff -Nru libinput-1.16.4/src/evdev-mt-touchpad.h libinput-1.17.2/src/evdev-mt-touchpad.h --- libinput-1.16.4/src/evdev-mt-touchpad.h 2020-11-27 01:38:59.369086000 +0000 +++ libinput-1.17.2/src/evdev-mt-touchpad.h 2021-04-30 04:25:41.530076300 +0000 @@ -106,17 +106,31 @@ TAP_STATE_IDLE = 4, TAP_STATE_TOUCH, TAP_STATE_HOLD, - TAP_STATE_TAPPED, + TAP_STATE_1FGTAP_TAPPED, + TAP_STATE_2FGTAP_TAPPED, + TAP_STATE_3FGTAP_TAPPED, TAP_STATE_TOUCH_2, TAP_STATE_TOUCH_2_HOLD, TAP_STATE_TOUCH_2_RELEASE, TAP_STATE_TOUCH_3, TAP_STATE_TOUCH_3_HOLD, - TAP_STATE_DRAGGING_OR_DOUBLETAP, - TAP_STATE_DRAGGING_OR_TAP, - TAP_STATE_DRAGGING, - TAP_STATE_DRAGGING_WAIT, - TAP_STATE_DRAGGING_2, + TAP_STATE_TOUCH_3_RELEASE, + TAP_STATE_TOUCH_3_RELEASE_2, + TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP, + TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP, + TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP, + TAP_STATE_1FGTAP_DRAGGING_OR_TAP, + TAP_STATE_2FGTAP_DRAGGING_OR_TAP, + TAP_STATE_3FGTAP_DRAGGING_OR_TAP, + TAP_STATE_1FGTAP_DRAGGING, + TAP_STATE_2FGTAP_DRAGGING, + TAP_STATE_3FGTAP_DRAGGING, + TAP_STATE_1FGTAP_DRAGGING_WAIT, + TAP_STATE_2FGTAP_DRAGGING_WAIT, + TAP_STATE_3FGTAP_DRAGGING_WAIT, + TAP_STATE_1FGTAP_DRAGGING_2, + TAP_STATE_2FGTAP_DRAGGING_2, + TAP_STATE_3FGTAP_DRAGGING_2, TAP_STATE_DEAD, /**< finger count exceeded */ }; @@ -640,7 +654,7 @@ void tp_release_all_taps(struct tp_dispatch *tp, - uint64_t time); + uint64_t now); void tp_tap_suspend(struct tp_dispatch *tp, uint64_t time); diff -Nru libinput-1.16.4/src/evdev-mt-touchpad-tap.c libinput-1.17.2/src/evdev-mt-touchpad-tap.c --- libinput-1.16.4/src/evdev-mt-touchpad-tap.c 2020-11-27 01:38:59.368086000 +0000 +++ libinput-1.17.2/src/evdev-mt-touchpad-tap.c 2021-04-30 04:25:41.529076300 +0000 @@ -30,7 +30,9 @@ #include "evdev-mt-touchpad.h" #define DEFAULT_TAP_TIMEOUT_PERIOD ms2us(180) -#define DEFAULT_DRAG_TIMEOUT_PERIOD ms2us(300) +#define DEFAULT_DRAG_TIMEOUT_PERIOD_BASE ms2us(160) +#define DEFAULT_DRAG_TIMEOUT_PERIOD_PERFINGER ms2us(20) +#define DEFAULT_DRAGLOCK_TIMEOUT_PERIOD ms2us(300) #define DEFAULT_TAP_MOVE_THRESHOLD 1.3 /* mm */ enum tap_event { @@ -60,17 +62,31 @@ CASE_RETURN_STRING(TAP_STATE_IDLE); CASE_RETURN_STRING(TAP_STATE_HOLD); CASE_RETURN_STRING(TAP_STATE_TOUCH); - CASE_RETURN_STRING(TAP_STATE_TAPPED); + CASE_RETURN_STRING(TAP_STATE_1FGTAP_TAPPED); + CASE_RETURN_STRING(TAP_STATE_2FGTAP_TAPPED); + CASE_RETURN_STRING(TAP_STATE_3FGTAP_TAPPED); CASE_RETURN_STRING(TAP_STATE_TOUCH_2); CASE_RETURN_STRING(TAP_STATE_TOUCH_2_HOLD); CASE_RETURN_STRING(TAP_STATE_TOUCH_2_RELEASE); CASE_RETURN_STRING(TAP_STATE_TOUCH_3); CASE_RETURN_STRING(TAP_STATE_TOUCH_3_HOLD); - CASE_RETURN_STRING(TAP_STATE_DRAGGING); - CASE_RETURN_STRING(TAP_STATE_DRAGGING_WAIT); - CASE_RETURN_STRING(TAP_STATE_DRAGGING_OR_DOUBLETAP); - CASE_RETURN_STRING(TAP_STATE_DRAGGING_OR_TAP); - CASE_RETURN_STRING(TAP_STATE_DRAGGING_2); + CASE_RETURN_STRING(TAP_STATE_TOUCH_3_RELEASE); + CASE_RETURN_STRING(TAP_STATE_TOUCH_3_RELEASE_2); + CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING); + CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING); + CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING); + CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_WAIT); + CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_WAIT); + CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_WAIT); + CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP); + CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP); + CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP); + CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_OR_TAP); + CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_OR_TAP); + CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_OR_TAP); + CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_2); + CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_2); + CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_2); CASE_RETURN_STRING(TAP_STATE_DEAD); } return NULL; @@ -117,7 +133,7 @@ assert(tp->tap.map < ARRAY_LENGTH(button_map)); - if (nfingers > 3) + if (nfingers < 1 || nfingers > 3) return; button = button_map[tp->tap.map][nfingers - 1]; @@ -140,9 +156,20 @@ } static void -tp_tap_set_drag_timer(struct tp_dispatch *tp, uint64_t time) +tp_tap_set_drag_timer(struct tp_dispatch *tp, uint64_t time, + int nfingers_tapped) { - libinput_timer_set(&tp->tap.timer, time + DEFAULT_DRAG_TIMEOUT_PERIOD); + libinput_timer_set(&tp->tap.timer, + time + DEFAULT_DRAG_TIMEOUT_PERIOD_BASE + + (nfingers_tapped * + DEFAULT_DRAG_TIMEOUT_PERIOD_PERFINGER)); +} + +static void +tp_tap_set_draglock_timer(struct tp_dispatch *tp, uint64_t time) +{ + libinput_timer_set(&tp->tap.timer, + time + DEFAULT_DRAGLOCK_TIMEOUT_PERIOD); } static void @@ -209,9 +236,9 @@ 1, LIBINPUT_BUTTON_STATE_PRESSED); if (tp->tap.drag_enabled) { - tp->tap.state = TAP_STATE_TAPPED; + tp->tap.state = TAP_STATE_1FGTAP_TAPPED; tp->tap.saved_release_time = time; - tp_tap_set_timer(tp, time); + tp_tap_set_drag_timer(tp, time, 1); } else { tp_tap_notify(tp, time, @@ -286,36 +313,46 @@ static void tp_tap_tapped_handle_event(struct tp_dispatch *tp, struct tp_touch *t, - enum tap_event event, uint64_t time) + enum tap_event event, uint64_t time, + int nfingers_tapped) { switch (event) { case TAP_EVENT_MOTION: case TAP_EVENT_RELEASE: log_tap_bug(tp, t, event); break; - case TAP_EVENT_TOUCH: - tp->tap.state = TAP_STATE_DRAGGING_OR_DOUBLETAP; + case TAP_EVENT_TOUCH: { + enum tp_tap_state dest[3] = { + TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP, + TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP, + TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.state = dest[nfingers_tapped - 1]; tp->tap.saved_press_time = time; tp_tap_set_timer(tp, time); break; + } case TAP_EVENT_TIMEOUT: tp->tap.state = TAP_STATE_IDLE; tp_tap_notify(tp, tp->tap.saved_release_time, - 1, + nfingers_tapped, LIBINPUT_BUTTON_STATE_RELEASED); break; case TAP_EVENT_BUTTON: tp->tap.state = TAP_STATE_DEAD; tp_tap_notify(tp, tp->tap.saved_release_time, - 1, + nfingers_tapped, LIBINPUT_BUTTON_STATE_RELEASED); break; case TAP_EVENT_THUMB: log_tap_bug(tp, t, event); break; case TAP_EVENT_PALM: + log_tap_bug(tp, t, event); + break; case TAP_EVENT_PALM_UP: break; } @@ -351,7 +388,6 @@ break; case TAP_EVENT_PALM: tp->tap.state = TAP_STATE_TOUCH; - tp_tap_set_timer(tp, time); /* overwrite timer */ break; case TAP_EVENT_PALM_UP: break; @@ -409,11 +445,16 @@ tp->tap.saved_press_time, 2, LIBINPUT_BUTTON_STATE_PRESSED); - tp_tap_notify(tp, - tp->tap.saved_release_time, - 2, - LIBINPUT_BUTTON_STATE_RELEASED); - tp->tap.state = TAP_STATE_IDLE; + if (tp->tap.drag_enabled) { + tp->tap.state = TAP_STATE_2FGTAP_TAPPED; + tp_tap_set_drag_timer(tp, time, 2); + } else { + tp_tap_notify(tp, + tp->tap.saved_release_time, + 2, + LIBINPUT_BUTTON_STATE_RELEASED); + tp->tap.state = TAP_STATE_IDLE; + } break; case TAP_EVENT_MOTION: tp_tap_move_to_dead(tp, t); @@ -438,12 +479,13 @@ 1, LIBINPUT_BUTTON_STATE_PRESSED); if (tp->tap.drag_enabled) { - tp->tap.state = TAP_STATE_TAPPED; - tp->tap.saved_release_time = time; - tp_tap_set_timer(tp, time); + /* For a single-finger tap the timer delay is the same + * as for the release of the finger that became a palm, + * no reset necessary */ + tp->tap.state = TAP_STATE_1FGTAP_TAPPED; } else { tp_tap_notify(tp, - time, + tp->tap.saved_release_time, 1, LIBINPUT_BUTTON_STATE_RELEASED); tp->tap.state = TAP_STATE_IDLE; @@ -473,14 +515,9 @@ tp_tap_clear_timer(tp); break; case TAP_EVENT_RELEASE: - tp->tap.state = TAP_STATE_TOUCH_2_HOLD; - if (t->tap.state == TAP_TOUCH_STATE_TOUCH) { - tp_tap_notify(tp, - tp->tap.saved_press_time, - 3, - LIBINPUT_BUTTON_STATE_PRESSED); - tp_tap_notify(tp, time, 3, LIBINPUT_BUTTON_STATE_RELEASED); - } + tp->tap.state = TAP_STATE_TOUCH_3_RELEASE; + tp->tap.saved_release_time = time; + tp_tap_set_timer(tp, time); break; case TAP_EVENT_BUTTON: tp->tap.state = TAP_STATE_DEAD; @@ -528,19 +565,191 @@ } static void +tp_tap_touch3_release_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, uint64_t time) +{ + + switch (event) { + case TAP_EVENT_TOUCH: + tp_tap_notify(tp, + tp->tap.saved_press_time, + 3, + LIBINPUT_BUTTON_STATE_PRESSED); + tp_tap_notify(tp, + tp->tap.saved_release_time, + 3, + LIBINPUT_BUTTON_STATE_RELEASED); + tp->tap.state = TAP_STATE_TOUCH_3; + tp->tap.saved_press_time = time; + tp_tap_set_timer(tp, time); + break; + case TAP_EVENT_RELEASE: + tp->tap.state = TAP_STATE_TOUCH_3_RELEASE_2; + tp_tap_set_timer(tp, time); + break; + case TAP_EVENT_MOTION: + tp_tap_notify(tp, + tp->tap.saved_press_time, + 3, + LIBINPUT_BUTTON_STATE_PRESSED); + tp_tap_notify(tp, + tp->tap.saved_release_time, + 3, + LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_move_to_dead(tp, t); + break; + case TAP_EVENT_TIMEOUT: + tp_tap_notify(tp, + tp->tap.saved_press_time, + 3, + LIBINPUT_BUTTON_STATE_PRESSED); + tp_tap_notify(tp, + tp->tap.saved_release_time, + 3, + LIBINPUT_BUTTON_STATE_RELEASED); + tp->tap.state = TAP_STATE_TOUCH_2_HOLD; + break; + case TAP_EVENT_BUTTON: + tp_tap_notify(tp, + tp->tap.saved_press_time, + 3, + LIBINPUT_BUTTON_STATE_PRESSED); + tp_tap_notify(tp, + tp->tap.saved_release_time, + 3, + LIBINPUT_BUTTON_STATE_RELEASED); + tp->tap.state = TAP_STATE_DEAD; + break; + case TAP_EVENT_THUMB: + break; + case TAP_EVENT_PALM: + tp->tap.state = TAP_STATE_TOUCH_2_RELEASE; + break; + case TAP_EVENT_PALM_UP: + break; + } +} + +static void +tp_tap_touch3_release2_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, uint64_t time) +{ + + switch (event) { + case TAP_EVENT_TOUCH: + tp_tap_notify(tp, + tp->tap.saved_press_time, + 3, + LIBINPUT_BUTTON_STATE_PRESSED); + tp_tap_notify(tp, + tp->tap.saved_release_time, + 3, + LIBINPUT_BUTTON_STATE_RELEASED); + tp->tap.state = TAP_STATE_TOUCH_2; + tp->tap.saved_press_time = time; + tp_tap_set_timer(tp, time); + break; + case TAP_EVENT_RELEASE: + tp_tap_notify(tp, + tp->tap.saved_press_time, + 3, + LIBINPUT_BUTTON_STATE_PRESSED); + if (tp->tap.drag_enabled) { + tp->tap.state = TAP_STATE_3FGTAP_TAPPED; + tp_tap_set_drag_timer(tp, time, 3); + } else { + tp_tap_notify(tp, + tp->tap.saved_release_time, + 3, + LIBINPUT_BUTTON_STATE_RELEASED); + tp->tap.state = TAP_STATE_IDLE; + } + break; + case TAP_EVENT_MOTION: + tp_tap_notify(tp, + tp->tap.saved_press_time, + 3, + LIBINPUT_BUTTON_STATE_PRESSED); + tp_tap_notify(tp, + tp->tap.saved_release_time, + 3, + LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_move_to_dead(tp, t); + break; + case TAP_EVENT_TIMEOUT: + tp_tap_notify(tp, + tp->tap.saved_press_time, + 3, + LIBINPUT_BUTTON_STATE_PRESSED); + tp_tap_notify(tp, + tp->tap.saved_release_time, + 3, + LIBINPUT_BUTTON_STATE_RELEASED); + tp->tap.state = TAP_STATE_HOLD; + break; + case TAP_EVENT_BUTTON: + tp_tap_notify(tp, + tp->tap.saved_press_time, + 3, + LIBINPUT_BUTTON_STATE_PRESSED); + tp_tap_notify(tp, + tp->tap.saved_release_time, + 3, + LIBINPUT_BUTTON_STATE_RELEASED); + tp->tap.state = TAP_STATE_DEAD; + break; + case TAP_EVENT_THUMB: + break; + case TAP_EVENT_PALM: + tp_tap_notify(tp, + tp->tap.saved_press_time, + 2, + LIBINPUT_BUTTON_STATE_PRESSED); + if (tp->tap.drag_enabled) { + /* Resetting the timer to the appropriate delay + * for a two-finger tap would be ideal, but the + * timestamp of the last real finger release is lost, + * so the in-progress similar delay for release + * of the finger which became a palm instead + * will have to do */ + tp->tap.state = TAP_STATE_2FGTAP_TAPPED; + } else { + tp_tap_notify(tp, + tp->tap.saved_release_time, + 2, + LIBINPUT_BUTTON_STATE_RELEASED); + tp->tap.state = TAP_STATE_IDLE; + } + break; + case TAP_EVENT_PALM_UP: + break; + } +} + +static void tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp, struct tp_touch *t, - enum tap_event event, uint64_t time) + enum tap_event event, uint64_t time, + int nfingers_tapped) { switch (event) { - case TAP_EVENT_TOUCH: - tp->tap.state = TAP_STATE_DRAGGING_2; + case TAP_EVENT_TOUCH: { + tp_tap_notify(tp, + tp->tap.saved_release_time, + nfingers_tapped, + LIBINPUT_BUTTON_STATE_RELEASED); + tp->tap.state = TAP_STATE_TOUCH_2; + tp->tap.saved_press_time = time; + tp_tap_set_timer(tp, time); break; + } case TAP_EVENT_RELEASE: - tp->tap.state = TAP_STATE_TAPPED; + tp->tap.state = TAP_STATE_1FGTAP_TAPPED; tp_tap_notify(tp, tp->tap.saved_release_time, - 1, + nfingers_tapped, LIBINPUT_BUTTON_STATE_RELEASED); tp_tap_notify(tp, tp->tap.saved_press_time, @@ -550,21 +759,35 @@ tp_tap_set_timer(tp, time); break; case TAP_EVENT_MOTION: - case TAP_EVENT_TIMEOUT: - tp->tap.state = TAP_STATE_DRAGGING; + case TAP_EVENT_TIMEOUT: { + enum tp_tap_state dest[3] = { + TAP_STATE_1FGTAP_DRAGGING, + TAP_STATE_2FGTAP_DRAGGING, + TAP_STATE_3FGTAP_DRAGGING, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.state = dest[nfingers_tapped - 1]; break; + } case TAP_EVENT_BUTTON: tp->tap.state = TAP_STATE_DEAD; tp_tap_notify(tp, tp->tap.saved_release_time, - 1, + nfingers_tapped, LIBINPUT_BUTTON_STATE_RELEASED); break; case TAP_EVENT_THUMB: break; - case TAP_EVENT_PALM: - tp->tap.state = TAP_STATE_TAPPED; + case TAP_EVENT_PALM: { + enum tp_tap_state dest[3] = { + TAP_STATE_1FGTAP_TAPPED, + TAP_STATE_2FGTAP_TAPPED, + TAP_STATE_3FGTAP_TAPPED, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.state = dest[nfingers_tapped - 1]; break; + } case TAP_EVENT_PALM_UP: break; } @@ -573,21 +796,35 @@ static void tp_tap_dragging_handle_event(struct tp_dispatch *tp, struct tp_touch *t, - enum tap_event event, uint64_t time) + enum tap_event event, uint64_t time, + int nfingers_tapped) { switch (event) { - case TAP_EVENT_TOUCH: - tp->tap.state = TAP_STATE_DRAGGING_2; + case TAP_EVENT_TOUCH: { + enum tp_tap_state dest[3] = { + TAP_STATE_1FGTAP_DRAGGING_2, + TAP_STATE_2FGTAP_DRAGGING_2, + TAP_STATE_3FGTAP_DRAGGING_2, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.state = dest[nfingers_tapped - 1]; break; + } case TAP_EVENT_RELEASE: if (tp->tap.drag_lock_enabled) { - tp->tap.state = TAP_STATE_DRAGGING_WAIT; - tp_tap_set_drag_timer(tp, time); + enum tp_tap_state dest[3] = { + TAP_STATE_1FGTAP_DRAGGING_WAIT, + TAP_STATE_2FGTAP_DRAGGING_WAIT, + TAP_STATE_3FGTAP_DRAGGING_WAIT, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.state = dest[nfingers_tapped - 1]; + tp_tap_set_draglock_timer(tp, time); } else { tp_tap_notify(tp, time, - 1, + nfingers_tapped, LIBINPUT_BUTTON_STATE_RELEASED); tp->tap.state = TAP_STATE_IDLE; } @@ -598,14 +835,17 @@ break; case TAP_EVENT_BUTTON: tp->tap.state = TAP_STATE_DEAD; - tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_notify(tp, + time, + nfingers_tapped, + LIBINPUT_BUTTON_STATE_RELEASED); break; case TAP_EVENT_THUMB: break; case TAP_EVENT_PALM: tp_tap_notify(tp, tp->tap.saved_release_time, - 1, + nfingers_tapped, LIBINPUT_BUTTON_STATE_RELEASED); tp->tap.state = TAP_STATE_IDLE; break; @@ -617,27 +857,43 @@ static void tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp, struct tp_touch *t, - enum tap_event event, uint64_t time) + enum tap_event event, uint64_t time, + int nfingers_tapped) { switch (event) { - case TAP_EVENT_TOUCH: - tp->tap.state = TAP_STATE_DRAGGING_OR_TAP; + case TAP_EVENT_TOUCH: { + enum tp_tap_state dest[3] = { + TAP_STATE_1FGTAP_DRAGGING_OR_TAP, + TAP_STATE_2FGTAP_DRAGGING_OR_TAP, + TAP_STATE_3FGTAP_DRAGGING_OR_TAP, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.state = dest[nfingers_tapped - 1]; tp_tap_set_timer(tp, time); break; + } case TAP_EVENT_RELEASE: case TAP_EVENT_MOTION: + log_tap_bug(tp, t, event); break; case TAP_EVENT_TIMEOUT: tp->tap.state = TAP_STATE_IDLE; - tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_notify(tp, + time, + nfingers_tapped, + LIBINPUT_BUTTON_STATE_RELEASED); break; case TAP_EVENT_BUTTON: tp->tap.state = TAP_STATE_DEAD; - tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_notify(tp, + time, + nfingers_tapped, + LIBINPUT_BUTTON_STATE_RELEASED); break; case TAP_EVENT_THUMB: case TAP_EVENT_PALM: + log_tap_bug(tp, t, event); break; case TAP_EVENT_PALM_UP: break; @@ -646,36 +902,58 @@ static void tp_tap_dragging_tap_handle_event(struct tp_dispatch *tp, - struct tp_touch *t, - enum tap_event event, uint64_t time) + struct tp_touch *t, + enum tap_event event, uint64_t time, + int nfingers_tapped) { switch (event) { - case TAP_EVENT_TOUCH: - tp->tap.state = TAP_STATE_DRAGGING_2; + case TAP_EVENT_TOUCH: { + tp_tap_notify(tp, + time, + nfingers_tapped, + LIBINPUT_BUTTON_STATE_RELEASED); tp_tap_clear_timer(tp); + tp_tap_move_to_dead(tp, t); break; + } case TAP_EVENT_RELEASE: tp->tap.state = TAP_STATE_IDLE; - tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_notify(tp, + time, + nfingers_tapped, + LIBINPUT_BUTTON_STATE_RELEASED); break; case TAP_EVENT_MOTION: - case TAP_EVENT_TIMEOUT: - tp->tap.state = TAP_STATE_DRAGGING; + case TAP_EVENT_TIMEOUT: { + enum tp_tap_state dest[3] = { + TAP_STATE_1FGTAP_DRAGGING, + TAP_STATE_2FGTAP_DRAGGING, + TAP_STATE_3FGTAP_DRAGGING, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.state = dest[nfingers_tapped - 1]; break; + } case TAP_EVENT_BUTTON: tp->tap.state = TAP_STATE_DEAD; - tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_notify(tp, + time, + nfingers_tapped, + LIBINPUT_BUTTON_STATE_RELEASED); break; case TAP_EVENT_THUMB: break; - case TAP_EVENT_PALM: - tp_tap_notify(tp, - tp->tap.saved_release_time, - 1, - LIBINPUT_BUTTON_STATE_RELEASED); - tp->tap.state = TAP_STATE_IDLE; + case TAP_EVENT_PALM: { + enum tp_tap_state dest[3] = { + TAP_STATE_1FGTAP_DRAGGING_WAIT, + TAP_STATE_2FGTAP_DRAGGING_WAIT, + TAP_STATE_3FGTAP_DRAGGING_WAIT, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.state = dest[nfingers_tapped - 1]; break; + } case TAP_EVENT_PALM_UP: break; } @@ -684,16 +962,27 @@ static void tp_tap_dragging2_handle_event(struct tp_dispatch *tp, struct tp_touch *t, - enum tap_event event, uint64_t time) + enum tap_event event, uint64_t time, + int nfingers_tapped) { switch (event) { - case TAP_EVENT_RELEASE: - tp->tap.state = TAP_STATE_DRAGGING; + case TAP_EVENT_RELEASE: { + enum tp_tap_state dest[3] = { + TAP_STATE_1FGTAP_DRAGGING, + TAP_STATE_2FGTAP_DRAGGING, + TAP_STATE_3FGTAP_DRAGGING, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.state = dest[nfingers_tapped - 1]; break; + } case TAP_EVENT_TOUCH: tp->tap.state = TAP_STATE_DEAD; - tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_notify(tp, + time, + nfingers_tapped, + LIBINPUT_BUTTON_STATE_RELEASED); break; case TAP_EVENT_MOTION: case TAP_EVENT_TIMEOUT: @@ -701,13 +990,23 @@ break; case TAP_EVENT_BUTTON: tp->tap.state = TAP_STATE_DEAD; - tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_notify(tp, + time, + nfingers_tapped, + LIBINPUT_BUTTON_STATE_RELEASED); break; case TAP_EVENT_THUMB: break; - case TAP_EVENT_PALM: - tp->tap.state = TAP_STATE_DRAGGING_OR_DOUBLETAP; + case TAP_EVENT_PALM: { + enum tp_tap_state dest[3] = { + TAP_STATE_1FGTAP_DRAGGING, + TAP_STATE_2FGTAP_DRAGGING, + TAP_STATE_3FGTAP_DRAGGING, + }; + assert(nfingers_tapped >= 1 && nfingers_tapped <= 3); + tp->tap.state = dest[nfingers_tapped - 1]; break; + } case TAP_EVENT_PALM_UP: break; } @@ -760,8 +1059,14 @@ case TAP_STATE_HOLD: tp_tap_hold_handle_event(tp, t, event, time); break; - case TAP_STATE_TAPPED: - tp_tap_tapped_handle_event(tp, t, event, time); + case TAP_STATE_1FGTAP_TAPPED: + tp_tap_tapped_handle_event(tp, t, event, time, 1); + break; + case TAP_STATE_2FGTAP_TAPPED: + tp_tap_tapped_handle_event(tp, t, event, time, 2); + break; + case TAP_STATE_3FGTAP_TAPPED: + tp_tap_tapped_handle_event(tp, t, event, time, 3); break; case TAP_STATE_TOUCH_2: tp_tap_touch2_handle_event(tp, t, event, time); @@ -778,20 +1083,59 @@ case TAP_STATE_TOUCH_3_HOLD: tp_tap_touch3_hold_handle_event(tp, t, event, time); break; - case TAP_STATE_DRAGGING_OR_DOUBLETAP: - tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time); + case TAP_STATE_TOUCH_3_RELEASE: + tp_tap_touch3_release_handle_event(tp, t, event, time); + break; + case TAP_STATE_TOUCH_3_RELEASE_2: + tp_tap_touch3_release2_handle_event(tp, t, event, time); + break; + case TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP: + tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time, + 1); + break; + case TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP: + tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time, + 2); + break; + case TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP: + tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time, + 3); + break; + case TAP_STATE_1FGTAP_DRAGGING: + tp_tap_dragging_handle_event(tp, t, event, time, 1); + break; + case TAP_STATE_2FGTAP_DRAGGING: + tp_tap_dragging_handle_event(tp, t, event, time, 2); + break; + case TAP_STATE_3FGTAP_DRAGGING: + tp_tap_dragging_handle_event(tp, t, event, time, 3); + break; + case TAP_STATE_1FGTAP_DRAGGING_WAIT: + tp_tap_dragging_wait_handle_event(tp, t, event, time, 1); + break; + case TAP_STATE_2FGTAP_DRAGGING_WAIT: + tp_tap_dragging_wait_handle_event(tp, t, event, time, 2); + break; + case TAP_STATE_3FGTAP_DRAGGING_WAIT: + tp_tap_dragging_wait_handle_event(tp, t, event, time, 3); + break; + case TAP_STATE_1FGTAP_DRAGGING_OR_TAP: + tp_tap_dragging_tap_handle_event(tp, t, event, time, 1); + break; + case TAP_STATE_2FGTAP_DRAGGING_OR_TAP: + tp_tap_dragging_tap_handle_event(tp, t, event, time, 2); break; - case TAP_STATE_DRAGGING: - tp_tap_dragging_handle_event(tp, t, event, time); + case TAP_STATE_3FGTAP_DRAGGING_OR_TAP: + tp_tap_dragging_tap_handle_event(tp, t, event, time, 3); break; - case TAP_STATE_DRAGGING_WAIT: - tp_tap_dragging_wait_handle_event(tp, t, event, time); + case TAP_STATE_1FGTAP_DRAGGING_2: + tp_tap_dragging2_handle_event(tp, t, event, time, 1); break; - case TAP_STATE_DRAGGING_OR_TAP: - tp_tap_dragging_tap_handle_event(tp, t, event, time); + case TAP_STATE_2FGTAP_DRAGGING_2: + tp_tap_dragging2_handle_event(tp, t, event, time, 2); break; - case TAP_STATE_DRAGGING_2: - tp_tap_dragging2_handle_event(tp, t, event, time); + case TAP_STATE_3FGTAP_DRAGGING_2: + tp_tap_dragging2_handle_event(tp, t, event, time, 3); break; case TAP_STATE_DEAD: tp_tap_dead_handle_event(tp, t, event, time); @@ -876,7 +1220,7 @@ if (t->tap.is_thumb) continue; - /* A palm tap needs to be properly relased because we might + /* A palm tap needs to be properly released because we might * be who-knows-where in the state machine. Otherwise, we * ignore any event from it. */ @@ -955,9 +1299,15 @@ */ switch (tp->tap.state) { case TAP_STATE_TOUCH: - case TAP_STATE_TAPPED: - case TAP_STATE_DRAGGING_OR_DOUBLETAP: - case TAP_STATE_DRAGGING_OR_TAP: + case TAP_STATE_1FGTAP_TAPPED: + case TAP_STATE_2FGTAP_TAPPED: + case TAP_STATE_3FGTAP_TAPPED: + case TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP: + case TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP: + case TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP: + case TAP_STATE_1FGTAP_DRAGGING_OR_TAP: + case TAP_STATE_2FGTAP_DRAGGING_OR_TAP: + case TAP_STATE_3FGTAP_DRAGGING_OR_TAP: case TAP_STATE_TOUCH_2: case TAP_STATE_TOUCH_3: filter_motion = 1; @@ -1286,10 +1636,18 @@ tp_tap_dragging(const struct tp_dispatch *tp) { switch (tp->tap.state) { - case TAP_STATE_DRAGGING: - case TAP_STATE_DRAGGING_2: - case TAP_STATE_DRAGGING_WAIT: - case TAP_STATE_DRAGGING_OR_TAP: + case TAP_STATE_1FGTAP_DRAGGING: + case TAP_STATE_2FGTAP_DRAGGING: + case TAP_STATE_3FGTAP_DRAGGING: + case TAP_STATE_1FGTAP_DRAGGING_2: + case TAP_STATE_2FGTAP_DRAGGING_2: + case TAP_STATE_3FGTAP_DRAGGING_2: + case TAP_STATE_1FGTAP_DRAGGING_WAIT: + case TAP_STATE_2FGTAP_DRAGGING_WAIT: + case TAP_STATE_3FGTAP_DRAGGING_WAIT: + case TAP_STATE_1FGTAP_DRAGGING_OR_TAP: + case TAP_STATE_2FGTAP_DRAGGING_OR_TAP: + case TAP_STATE_3FGTAP_DRAGGING_OR_TAP: return true; default: return false; diff -Nru libinput-1.16.4/src/evdev-tablet.c libinput-1.17.2/src/evdev-tablet.c --- libinput-1.16.4/src/evdev-tablet.c 2020-11-27 01:38:59.370086000 +0000 +++ libinput-1.17.2/src/evdev-tablet.c 2021-04-30 04:25:41.530076300 +0000 @@ -89,7 +89,7 @@ static inline size_t tablet_history_size(const struct tablet_dispatch *tablet) { - return ARRAY_LENGTH(tablet->history.samples); + return tablet->history.size; } static inline void @@ -365,16 +365,16 @@ * * This means that there is a small range (lower-upper) where * different physical pressure (default: 1-5%) result in the same - * logical pressure. This is, hopefully, not noticable. + * logical pressure. This is, hopefully, not noticeable. * * Note that that lower-upper range gives us a negative pressure, so * we have to clip to 0 for those. */ - if (tool->has_pressure_offset) - offset = tool->pressure_offset; + if (tool->pressure.has_offset) + offset = tool->pressure.offset; else - offset = tool->pressure_threshold.upper; + offset = tool->pressure.threshold.upper; range = absinfo->maximum - offset; value = (absinfo->value - offset) / range; @@ -1081,8 +1081,8 @@ struct quirk_range r; int lo = 0, hi = 1; - tool->pressure_offset = 0; - tool->has_pressure_offset = false; + tool->pressure.offset = 0; + tool->pressure.has_offset = false; pressure = libevdev_get_abs_info(device->evdev, ABS_PRESSURE); if (!pressure) @@ -1091,7 +1091,7 @@ quirks = evdev_libinput_context(device)->quirks; q = quirks_fetch_for_device(quirks, device->udev_device); - tool->pressure_offset = pressure->minimum; + tool->pressure.offset = pressure->minimum; /* 5 and 1% of the pressure range */ hi = axis_range_percentage(pressure, 5); @@ -1107,8 +1107,8 @@ } } out: - tool->pressure_threshold.upper = hi; - tool->pressure_threshold.lower = lo; + tool->pressure.threshold.upper = hi; + tool->pressure.threshold.lower = lo; quirks_unref(q); } @@ -1194,8 +1194,10 @@ size_t nbits = 8 * sizeof(buttons->bits); enum libinput_tablet_tool_tip_state tip_state; - tip_state = tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT) ? - LIBINPUT_TABLET_TOOL_TIP_DOWN : LIBINPUT_TABLET_TOOL_TIP_UP; + if (tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT)) + tip_state = LIBINPUT_TABLET_TOOL_TIP_DOWN; + else + tip_state = LIBINPUT_TABLET_TOOL_TIP_UP; for (i = 0; i < nbits; i++) { if (!bit_is_set(buttons->bits, i)) @@ -1251,7 +1253,7 @@ !bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_PRESSURE)) return; - tool_in_contact = (pressure->value > tool->pressure_offset); + tool_in_contact = (pressure->value > tool->pressure.offset); /* Keep distance and pressure mutually exclusive */ if (distance && @@ -1324,9 +1326,9 @@ * higher-than-needed pressure offset and then we'd be tied into a * high pressure offset for the rest of the session. */ - if (tool->has_pressure_offset) { - if (offset < tool->pressure_offset) - tool->pressure_offset = offset; + if (tool->pressure.has_offset) { + if (offset < tool->pressure.offset) + tool->pressure.offset = offset; return; } @@ -1345,7 +1347,7 @@ if (offset > axis_range_percentage(pressure, 20)) { evdev_log_error(device, "Ignoring pressure offset greater than 20%% detected on tool %s (serial %#x). " - "See %stablet-support.html\n", + "See %s/tablet-support.html\n", tablet_tool_type_to_string(tool->type), tool->serial, HTTP_DOC_LINK); @@ -1354,13 +1356,13 @@ evdev_log_info(device, "Pressure offset detected on tool %s (serial %#x). " - "See %stablet-support.html\n", + "See %s/tablet-support.html\n", tablet_tool_type_to_string(tool->type), tool->serial, HTTP_DOC_LINK); - tool->pressure_offset = offset; - tool->has_pressure_offset = true; - tool->pressure_threshold.lower = pressure->minimum; + tool->pressure.offset = offset; + tool->pressure.has_offset = true; + tool->pressure.threshold.lower = pressure->minimum; } static void @@ -1391,13 +1393,13 @@ } pressure = p->value; - if (tool->has_pressure_offset) - pressure -= (tool->pressure_offset - p->minimum); + if (tool->pressure.has_offset) + pressure -= (tool->pressure.offset - p->minimum); - if (pressure <= tool->pressure_threshold.lower && + if (pressure <= tool->pressure.threshold.lower && tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT)) { tablet_set_status(tablet, TABLET_TOOL_LEAVING_CONTACT); - } else if (pressure >= tool->pressure_threshold.upper && + } else if (pressure >= tool->pressure.threshold.upper && !tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT)) { tablet_set_status(tablet, TABLET_TOOL_ENTERING_CONTACT); } @@ -1705,7 +1707,7 @@ */ axes = tablet->axes; - /* Dont' send an axis event, but we may have a tip event + /* Don't send an axis event, but we may have a tip event * update */ tablet_unset_status(tablet, TABLET_AXES_UPDATED); } else { @@ -2342,6 +2344,55 @@ tablet_change_to_left_handed); } +static void +tablet_init_smoothing(struct evdev_device *device, + struct tablet_dispatch *tablet) +{ + size_t history_size = ARRAY_LENGTH(tablet->history.samples); +#if HAVE_LIBWACOM + const char *devnode; + WacomDeviceDatabase *db; + WacomDevice *libwacom_device = NULL; + const int *stylus_ids; + int nstyli; + bool is_aes = false; + int vid = evdev_device_get_id_vendor(device); + + /* Wacom-specific check for whether smoothing is required: + * libwacom keeps all the AES pens in a single group, so any device + * that supports AES pens will list all AES pens. 0x11 is one of the + * lenovo pens so we use that as the flag of whether the tablet + * is an AES tablet + */ + if (vid != VENDOR_ID_WACOM) + goto out; + + db = tablet_libinput_context(tablet)->libwacom.db; + if (!db) + goto out; + + devnode = udev_device_get_devnode(device->udev_device); + libwacom_device = libwacom_new_from_path(db, devnode, WFALLBACK_NONE, NULL); + if (!libwacom_device) + goto out; + + stylus_ids = libwacom_get_supported_styli(libwacom_device, &nstyli); + for (int i = 0; i < nstyli; i++) { + if (stylus_ids[i] == 0x11) { + is_aes = true; + break; + } + } + + if (is_aes) + history_size = 1; + + libwacom_destroy(libwacom_device); +out: +#endif + tablet->history.size = history_size; +} + static bool tablet_reject_device(struct evdev_device *device) { @@ -2406,6 +2457,7 @@ evdev_init_sendevents(device, &tablet->base); tablet_init_left_handed(device); + tablet_init_smoothing(device, tablet); for (axis = LIBINPUT_TABLET_TOOL_AXIS_X; axis <= LIBINPUT_TABLET_TOOL_AXIS_MAX; diff -Nru libinput-1.16.4/src/evdev-tablet.h libinput-1.17.2/src/evdev-tablet.h --- libinput-1.16.4/src/evdev-tablet.h 2020-11-27 01:38:59.370086000 +0000 +++ libinput-1.17.2/src/evdev-tablet.h 2021-04-30 04:25:41.530076300 +0000 @@ -64,6 +64,7 @@ unsigned int index; unsigned int count; struct tablet_axes samples[TABLET_HISTORY_LENGTH]; + size_t size; } history; unsigned char axis_caps[NCHARS(LIBINPUT_TABLET_TOOL_AXIS_MAX + 1)]; diff -Nru libinput-1.16.4/src/evdev-tablet-pad.c libinput-1.17.2/src/evdev-tablet-pad.c --- libinput-1.16.4/src/evdev-tablet-pad.c 2020-11-27 01:38:59.369086000 +0000 +++ libinput-1.17.2/src/evdev-tablet-pad.c 2021-04-30 04:25:41.530076300 +0000 @@ -550,7 +550,7 @@ struct evdev_device *device) { bool rc = false; -#if HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE +#if HAVE_LIBWACOM struct libinput *li = pad_libinput_context(pad); WacomDeviceDatabase *db = NULL; WacomDevice *tablet = NULL; diff -Nru libinput-1.16.4/src/evdev-tablet-pad.h libinput-1.17.2/src/evdev-tablet-pad.h --- libinput-1.16.4/src/evdev-tablet-pad.h 2020-11-27 01:38:59.370086000 +0000 +++ libinput-1.17.2/src/evdev-tablet-pad.h 2021-04-30 04:25:41.530076300 +0000 @@ -103,6 +103,6 @@ pad_destroy_leds(struct pad_dispatch *pad); void pad_button_update_mode(struct libinput_tablet_pad_mode_group *g, - unsigned int pressed_button, + unsigned int button_index, enum libinput_button_state state); #endif diff -Nru libinput-1.16.4/src/evdev-tablet-pad-leds.c libinput-1.17.2/src/evdev-tablet-pad-leds.c --- libinput-1.16.4/src/evdev-tablet-pad-leds.c 2020-11-27 01:38:59.369086000 +0000 +++ libinput-1.17.2/src/evdev-tablet-pad-leds.c 2021-04-30 04:25:41.530076300 +0000 @@ -132,7 +132,7 @@ if (rc == -1) goto error; - fd = open_restricted(libinput, path, O_RDONLY); + fd = open_restricted(libinput, path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); if (fd < 0) { errno = -fd; goto error; diff -Nru libinput-1.16.4/src/evdev-totem.c libinput-1.17.2/src/evdev-totem.c --- libinput-1.16.4/src/evdev-totem.c 2020-11-27 01:38:59.370086000 +0000 +++ libinput-1.17.2/src/evdev-totem.c 2021-04-30 04:25:41.530076300 +0000 @@ -88,10 +88,10 @@ .refcount = 1, }; - tool->pressure_offset = 0; - tool->has_pressure_offset = false; - tool->pressure_threshold.lower = 0; - tool->pressure_threshold.upper = 1; + tool->pressure.offset = 0; + tool->pressure.has_offset = false; + tool->pressure.threshold.lower = 0; + tool->pressure.threshold.upper = 1; set_bit(tool->axis_caps, LIBINPUT_TABLET_TOOL_AXIS_X); set_bit(tool->axis_caps, LIBINPUT_TABLET_TOOL_AXIS_Y); @@ -705,8 +705,8 @@ .destroy = totem_interface_destroy, .device_added = totem_interface_device_added, .device_removed = totem_interface_device_removed, - .device_suspended = totem_interface_device_added, /* treat as remove */ - .device_resumed = totem_interface_device_removed, /* treat as add */ + .device_suspended = totem_interface_device_removed, /* treat as remove */ + .device_resumed = totem_interface_device_added, /* treat as add */ .post_added = totem_interface_initial_proximity, .touch_arbitration_toggle = NULL, .touch_arbitration_update_rect = NULL, @@ -717,7 +717,7 @@ totem_reject_device(struct evdev_device *device) { struct libevdev *evdev = device->evdev; - bool has_xy, has_slot, has_tool_dial, has_size; + bool has_xy, has_slot, has_tool_dial, has_size, has_touch_size; double w, h; has_xy = libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) && @@ -726,19 +726,21 @@ has_tool_dial = libevdev_has_event_code(evdev, EV_ABS, ABS_MT_TOOL_TYPE) && libevdev_get_abs_maximum(evdev, ABS_MT_TOOL_TYPE) >= MT_TOOL_DIAL; has_size = evdev_device_get_size(device, &w, &h) == 0; - has_size |= libevdev_get_abs_resolution(device->evdev, ABS_MT_TOUCH_MAJOR) > 0; - has_size |= libevdev_get_abs_resolution(device->evdev, ABS_MT_TOUCH_MINOR) > 0; + has_touch_size = + libevdev_get_abs_resolution(device->evdev, ABS_MT_TOUCH_MAJOR) > 0 || + libevdev_get_abs_resolution(device->evdev, ABS_MT_TOUCH_MINOR) > 0; - if (has_xy && has_slot && has_tool_dial && has_size) + if (has_xy && has_slot && has_tool_dial && has_size && has_touch_size) return false; evdev_log_bug_libinput(device, - "missing totem capabilities:%s%s%s%s. " + "missing totem capabilities:%s%s%s%s%s. " "Ignoring this device.\n", has_xy ? "" : " xy", has_slot ? "" : " slot", has_tool_dial ? "" : " dial", - has_size ? "" : " resolutions"); + has_size ? "" : " resolutions", + has_touch_size ? "" : " touch-size"); return true; } diff -Nru libinput-1.16.4/src/filter.c libinput-1.17.2/src/filter.c --- libinput-1.16.4/src/filter.c 2020-11-27 01:38:59.372086000 +0000 +++ libinput-1.17.2/src/filter.c 2021-04-30 04:25:41.532076400 +0000 @@ -285,7 +285,7 @@ { double factor; - /* Use Simpson's rule to calculate the avarage acceleration between + /* Use Simpson's rule to calculate the average acceleration between * the previous motion and the most recent. */ factor = profile(filter, data, velocity, time); factor += profile(filter, data, last_velocity, time); diff -Nru libinput-1.16.4/src/filter.h libinput-1.17.2/src/filter.h --- libinput-1.16.4/src/filter.h 2020-11-27 01:38:59.372086000 +0000 +++ libinput-1.17.2/src/filter.h 2021-04-30 04:25:41.532076400 +0000 @@ -50,7 +50,7 @@ * @param time The time of the delta * * @return A set of normalized coordinates that can be used for pixel - * movement. The normalized coordiantes are scaled to the default dpi range, + * movement. The normalized coordinates are scaled to the default dpi range, * i.e. regardless of the resolution of the underlying device, the returned * values always reflect a 1000dpi mouse. * @@ -158,6 +158,6 @@ double trackpoint_accel_profile(struct motion_filter *filter, void *data, - double delta, + double velocity, uint64_t time); #endif /* FILTER_H */ diff -Nru libinput-1.16.4/src/filter-touchpad-x230.c libinput-1.17.2/src/filter-touchpad-x230.c --- libinput-1.16.4/src/filter-touchpad-x230.c 2020-11-27 01:38:59.372086000 +0000 +++ libinput-1.17.2/src/filter-touchpad-x230.c 2021-04-30 04:25:41.531076400 +0000 @@ -112,7 +112,7 @@ { double factor; - /* Use Simpson's rule to calculate the avarage acceleration between + /* Use Simpson's rule to calculate the average acceleration between * the previous motion and the most recent. */ factor = acceleration_profile(accel, data, velocity, time); factor += acceleration_profile(accel, data, last_velocity, time); diff -Nru libinput-1.16.4/src/libinput.c libinput-1.17.2/src/libinput.c --- libinput-1.16.4/src/libinput.c 2020-11-27 01:38:59.375086000 +0000 +++ libinput-1.17.2/src/libinput.c 2021-04-30 04:25:41.532076400 +0000 @@ -76,37 +76,6 @@ ASSERT_INT_SIZE(enum libinput_config_scroll_method); ASSERT_INT_SIZE(enum libinput_config_dwt_state); -static inline bool -check_event_type(struct libinput *libinput, - const char *function_name, - unsigned int type_in, - ...) -{ - bool rc = false; - va_list args; - unsigned int type_permitted; - - va_start(args, type_in); - type_permitted = va_arg(args, unsigned int); - - while (type_permitted != (unsigned int)-1) { - if (type_permitted == type_in) { - rc = true; - break; - } - type_permitted = va_arg(args, unsigned int); - } - - va_end(args); - - if (!rc) - log_bug_client(libinput, - "Invalid event type %d passed to %s()\n", - type_in, function_name); - - return rc; -} - static inline const char * event_type_to_str(enum libinput_event_type type) { @@ -145,6 +114,39 @@ return NULL; } +static inline bool +check_event_type(struct libinput *libinput, + const char *function_name, + unsigned int type_in, + ...) +{ + bool rc = false; + va_list args; + unsigned int type_permitted; + + va_start(args, type_in); + type_permitted = va_arg(args, unsigned int); + + while (type_permitted != (unsigned int)-1) { + if (type_permitted == type_in) { + rc = true; + break; + } + type_permitted = va_arg(args, unsigned int); + } + + va_end(args); + + if (!rc) { + const char *name = event_type_to_str(type_in); + log_bug_client(libinput, + "Invalid event type %s (%d) passed to %s()\n", + name, type_in, function_name); + } + + return rc; +} + struct libinput_source { libinput_source_dispatch_t dispatch; void *user_data; @@ -1821,7 +1823,7 @@ log_error(libinput, "Failed to load the device quirks from %s%s%s. " "This will negatively affect device behavior. " - "See %sdevice-quirks.html for details.\n", + "See %s/device-quirks.html for details.\n", data_path, override_file ? " and " : "", override_file ? override_file : "", @@ -2020,9 +2022,9 @@ if (seat->refcount == 0) { libinput_seat_destroy(seat); return NULL; - } else { - return seat; } + + return seat; } LIBINPUT_EXPORT void @@ -2086,9 +2088,9 @@ if (device->refcount == 0) { libinput_device_destroy(device); return NULL; - } else { - return device; } + + return device; } LIBINPUT_EXPORT int @@ -3617,9 +3619,9 @@ if (group->refcount == 0) { libinput_device_group_destroy(group); return NULL; - } else { - return group; } + + return group; } LIBINPUT_EXPORT void @@ -3854,8 +3856,9 @@ if (device->config.sendevents) return device->config.sendevents->set_mode(device, mode); - else /* mode must be _ENABLED to get here */ - return LIBINPUT_CONFIG_STATUS_SUCCESS; + + /* mode must be _ENABLED to get here */ + return LIBINPUT_CONFIG_STATUS_SUCCESS; } LIBINPUT_EXPORT uint32_t @@ -3863,8 +3866,8 @@ { if (device->config.sendevents) return device->config.sendevents->get_mode(device); - else - return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; + + return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; } LIBINPUT_EXPORT uint32_t @@ -4036,8 +4039,8 @@ { if (device->config.click_method) return device->config.click_method->get_methods(device); - else - return 0; + + return 0; } LIBINPUT_EXPORT enum libinput_config_status @@ -4059,8 +4062,9 @@ if (device->config.click_method) return device->config.click_method->set_method(device, method); - else /* method must be _NONE to get here */ - return LIBINPUT_CONFIG_STATUS_SUCCESS; + + /* method must be _NONE to get here */ + return LIBINPUT_CONFIG_STATUS_SUCCESS; } LIBINPUT_EXPORT enum libinput_config_click_method @@ -4068,8 +4072,8 @@ { if (device->config.click_method) return device->config.click_method->get_method(device); - else - return LIBINPUT_CONFIG_CLICK_METHOD_NONE; + + return LIBINPUT_CONFIG_CLICK_METHOD_NONE; } LIBINPUT_EXPORT enum libinput_config_click_method @@ -4077,8 +4081,8 @@ { if (device->config.click_method) return device->config.click_method->get_default_method(device); - else - return LIBINPUT_CONFIG_CLICK_METHOD_NONE; + + return LIBINPUT_CONFIG_CLICK_METHOD_NONE; } LIBINPUT_EXPORT int @@ -4087,8 +4091,8 @@ { if (device->config.middle_emulation) return device->config.middle_emulation->available(device); - else - return LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED; + + return LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED; } LIBINPUT_EXPORT enum libinput_config_status @@ -4140,8 +4144,8 @@ { if (device->config.scroll_method) return device->config.scroll_method->get_methods(device); - else - return 0; + + return 0; } LIBINPUT_EXPORT enum libinput_config_status @@ -4164,8 +4168,9 @@ if (device->config.scroll_method) return device->config.scroll_method->set_method(device, method); - else /* method must be _NO_SCROLL to get here */ - return LIBINPUT_CONFIG_STATUS_SUCCESS; + + /* method must be _NO_SCROLL to get here */ + return LIBINPUT_CONFIG_STATUS_SUCCESS; } LIBINPUT_EXPORT enum libinput_config_scroll_method @@ -4173,8 +4178,8 @@ { if (device->config.scroll_method) return device->config.scroll_method->get_method(device); - else - return LIBINPUT_CONFIG_SCROLL_NO_SCROLL; + + return LIBINPUT_CONFIG_SCROLL_NO_SCROLL; } LIBINPUT_EXPORT enum libinput_config_scroll_method @@ -4182,8 +4187,8 @@ { if (device->config.scroll_method) return device->config.scroll_method->get_default_method(device); - else - return LIBINPUT_CONFIG_SCROLL_NO_SCROLL; + + return LIBINPUT_CONFIG_SCROLL_NO_SCROLL; } LIBINPUT_EXPORT enum libinput_config_status diff -Nru libinput-1.16.4/src/libinput.h libinput-1.17.2/src/libinput.h --- libinput-1.16.4/src/libinput.h 2020-11-27 01:38:59.376086000 +0000 +++ libinput-1.17.2/src/libinput.h 2021-04-30 04:25:41.533076300 +0000 @@ -4560,10 +4560,9 @@ * @ingroup config * * Enable or disable tap-and-drag on this device. When enabled, a - * single-finger tap immediately followed by a finger down results in a - * button down event, subsequent finger motion thus triggers a drag. The - * button is released on finger up. See the libinput documentation for more - * details. + * tap immediately followed by a finger down results in a button down event, + * subsequent finger motion thus triggers a drag. The button is released + * on finger up. See the libinput documentation for more details. * * @param device The device to configure * @param enable @ref LIBINPUT_CONFIG_DRAG_ENABLED to enable, @ref @@ -5053,7 +5052,7 @@ * mode. * * @param device The device to configure - * @param mode The mode to set the device to. + * @param profile The profile to set the device to. * * @return A config status code * @@ -5061,7 +5060,7 @@ */ enum libinput_config_status libinput_device_config_accel_set_profile(struct libinput_device *device, - enum libinput_config_accel_profile mode); + enum libinput_config_accel_profile profile); /** * @ingroup config diff -Nru libinput-1.16.4/src/libinput-private.h libinput-1.17.2/src/libinput-private.h --- libinput-1.16.4/src/libinput-private.h 2020-11-27 01:38:59.373086000 +0000 +++ libinput-1.17.2/src/libinput-private.h 2021-04-30 04:25:41.532076400 +0000 @@ -378,11 +378,13 @@ int refcount; void *user_data; - /* The pressure threshold assumes a pressure_offset of 0 */ - struct threshold pressure_threshold; - /* pressure_offset includes axis->minimum */ - int pressure_offset; - bool has_pressure_offset; + struct { + /* The pressure threshold assumes a pressure_offset of 0 */ + struct threshold threshold; + /* pressure_offset includes axis->minimum */ + int offset; + bool has_offset; + } pressure; }; struct libinput_tablet_pad_mode_group { diff -Nru libinput-1.16.4/src/path-seat.c libinput-1.17.2/src/path-seat.c --- libinput-1.16.4/src/path-seat.c 2020-11-27 01:38:59.376086000 +0000 +++ libinput-1.17.2/src/path-seat.c 2021-04-30 04:25:41.533076300 +0000 @@ -49,8 +49,7 @@ static const char default_seat_name[] = "default"; static void -path_disable_device(struct libinput *libinput, - struct evdev_device *device) +path_disable_device(struct evdev_device *device) { struct libinput_seat *seat = device->base.seat; struct evdev_device *dev, *next; @@ -76,7 +75,7 @@ libinput_seat_ref(&seat->base); list_for_each_safe(device, next, &seat->base.devices_list, base.link) - path_disable_device(libinput, device); + path_disable_device(device); libinput_seat_unref(&seat->base); } } @@ -424,6 +423,6 @@ seat = device->seat; libinput_seat_ref(seat); - path_disable_device(libinput, evdev); + path_disable_device(evdev); libinput_seat_unref(seat); } diff -Nru libinput-1.16.4/src/quirks.c libinput-1.17.2/src/quirks.c --- libinput-1.16.4/src/quirks.c 2020-11-27 01:38:59.376086000 +0000 +++ libinput-1.17.2/src/quirks.c 2021-04-30 04:25:41.534076200 +0000 @@ -35,6 +35,9 @@ #include #include #include +#ifdef __FreeBSD__ +#include +#endif #include "libinput-versionsort.h" #include "libinput-util.h" @@ -57,6 +60,14 @@ PT_RANGE, PT_DOUBLE, PT_TUPLES, + PT_UINT_ARRAY, +}; + +struct quirk_array { + union { + uint32_t u[32]; + } data; + size_t nelements; }; /** @@ -79,6 +90,7 @@ struct quirk_dimensions dim; struct quirk_range range; struct quirk_tuples tuples; + struct quirk_array array; } value; }; @@ -102,6 +114,7 @@ BT_PS2, BT_RMI, BT_I2C, + BT_SPI, }; enum udev_type { @@ -239,11 +252,8 @@ case QUIRK_MODEL_HP_STREAM11_TOUCHPAD: return "ModelHPStream11Touchpad"; case QUIRK_MODEL_HP_ZBOOK_STUDIO_G3: return "ModelHPZBookStudioG3"; case QUIRK_MODEL_INVERT_HORIZONTAL_SCROLLING: return "ModelInvertHorizontalScrolling"; - case QUIRK_MODEL_LENOVO_L380_TOUCHPAD: return "ModelLenovoL380Touchpad"; case QUIRK_MODEL_LENOVO_SCROLLPOINT: return "ModelLenovoScrollPoint"; case QUIRK_MODEL_LENOVO_T450_TOUCHPAD: return "ModelLenovoT450Touchpad"; - case QUIRK_MODEL_LENOVO_T480S_TOUCHPAD: return "ModelLenovoT480sTouchpad"; - case QUIRK_MODEL_LENOVO_T490S_TOUCHPAD: return "ModelLenovoT490sTouchpad"; case QUIRK_MODEL_LENOVO_X1GEN6_TOUCHPAD: return "ModelLenovoX1Gen6Touchpad"; case QUIRK_MODEL_LENOVO_X230: return "ModelLenovoX230"; case QUIRK_MODEL_SYNAPTICS_SERIAL_TOUCHPAD: return "ModelSynapticsSerialTouchpad"; @@ -273,6 +283,9 @@ case QUIRK_ATTR_THUMB_SIZE_THRESHOLD: return "AttrThumbSizeThreshold"; case QUIRK_ATTR_MSC_TIMESTAMP: return "AttrMscTimestamp"; case QUIRK_ATTR_EVENT_CODE_DISABLE: return "AttrEventCodeDisable"; + case QUIRK_ATTR_EVENT_CODE_ENABLE: return "AttrEventCodeEnable"; + case QUIRK_ATTR_INPUT_PROP_DISABLE: return "AttrInputPropDisable"; + case QUIRK_ATTR_INPUT_PROP_ENABLE: return "AttrInputPropEnable"; default: abort(); } @@ -343,10 +356,11 @@ } /** - * Return the dmi modalias from the udev device. + * Return the system DMI info in modalias format. */ +#ifdef __linux__ static inline char * -init_dmi(void) +init_dmi_linux(void) { struct udev *udev; struct udev_device *udev_device; @@ -354,9 +368,6 @@ char *copy = NULL; const char *syspath = "/sys/devices/virtual/dmi/id"; - if (getenv("LIBINPUT_RUNNING_TEST_SUITE")) - return safe_strdup("dmi:"); - udev = udev_new(); if (!udev) return NULL; @@ -379,6 +390,73 @@ return copy; } +#endif + +#ifdef __FreeBSD__ +static inline char * +init_dmi_freebsd(void) +{ +#define LEN (KENV_MVALLEN + 1) + char *modalias; + char bios_vendor[LEN], bios_version[LEN], bios_date[LEN]; + char sys_vendor[LEN], product_name[LEN], product_version[LEN]; + char board_vendor[LEN], board_name[LEN], board_version[LEN]; + char chassis_vendor[LEN], chassis_type[LEN], chassis_version[LEN]; + int chassis_type_num = 0x2; + + kenv(KENV_GET, "smbios.bios.vendor", bios_vendor, LEN); + kenv(KENV_GET, "smbios.bios.version", bios_version, LEN); + kenv(KENV_GET, "smbios.bios.reldate", bios_date, LEN); + kenv(KENV_GET, "smbios.system.maker", sys_vendor, LEN); + kenv(KENV_GET, "smbios.system.product", product_name, LEN); + kenv(KENV_GET, "smbios.system.version", product_version, LEN); + kenv(KENV_GET, "smbios.planar.maker", board_vendor, LEN); + kenv(KENV_GET, "smbios.planar.product", board_name, LEN); + kenv(KENV_GET, "smbios.planar.version", board_version, LEN); + kenv(KENV_GET, "smbios.chassis.vendor", chassis_vendor, LEN); + kenv(KENV_GET, "smbios.chassis.type", chassis_type, LEN); + kenv(KENV_GET, "smbios.chassis.version", chassis_version, LEN); +#undef LEN + + if (strcmp(chassis_type, "Desktop") == 0) + chassis_type_num = 0x3; + else if (strcmp(chassis_type, "Portable") == 0) + chassis_type_num = 0x8; + else if (strcmp(chassis_type, "Laptop") == 0) + chassis_type_num = 0x9; + else if (strcmp(chassis_type, "Notebook") == 0) + chassis_type_num = 0xA; + else if (strcmp(chassis_type, "Tablet") == 0) + chassis_type_num = 0x1E; + else if (strcmp(chassis_type, "Convertible") == 0) + chassis_type_num = 0x1F; + else if (strcmp(chassis_type, "Detachable") == 0) + chassis_type_num = 0x20; + + xasprintf(&modalias, + "dmi:bvn%s:bvr%s:bd%s:svn%s:pn%s:pvr%s:rvn%s:rn%s:rvr%s:cvn%s:ct%d:cvr%s:", + bios_vendor, bios_version, bios_date, sys_vendor, product_name, + product_version, board_vendor, board_name, board_version, chassis_vendor, + chassis_type_num, chassis_version); + + return modalias; +} +#endif + +static inline char * +init_dmi(void) +{ + if (getenv("LIBINPUT_RUNNING_TEST_SUITE")) + return safe_strdup("dmi:"); + +#if defined(__linux__) + return init_dmi_linux(); +#elif defined(__FreeBSD__) + return init_dmi_freebsd(); +#else + return NULL; +#endif +} /** * Return the dt compatible string @@ -490,6 +568,8 @@ s->match.bus = BT_RMI; else if (streq(value, "i2c")) s->match.bus = BT_I2C; + else if (streq(value, "spi")) + s->match.bus = BT_SPI; else goto out; } else if (streq(key, "MatchVendor")) { @@ -737,10 +817,15 @@ p->type = PT_STRING; p->value.s = safe_strdup(value); rc = true; - } else if (streq(key, quirk_get_name(QUIRK_ATTR_EVENT_CODE_DISABLE))) { + } else if (streq(key, quirk_get_name(QUIRK_ATTR_EVENT_CODE_DISABLE)) || + streq(key, quirk_get_name(QUIRK_ATTR_EVENT_CODE_ENABLE))) { struct input_event events[32]; size_t nevents = ARRAY_LENGTH(events); - p->id = QUIRK_ATTR_EVENT_CODE_DISABLE; + if (streq(key, quirk_get_name(QUIRK_ATTR_EVENT_CODE_DISABLE))) + p->id = QUIRK_ATTR_EVENT_CODE_DISABLE; + else + p->id = QUIRK_ATTR_EVENT_CODE_ENABLE; + if (!parse_evcode_property(value, events, &nevents) || nevents == 0) goto out; @@ -753,6 +838,24 @@ p->type = PT_TUPLES; rc = true; + } else if (streq(key, quirk_get_name(QUIRK_ATTR_INPUT_PROP_DISABLE)) || + streq(key, quirk_get_name(QUIRK_ATTR_INPUT_PROP_ENABLE))) { + unsigned int props[INPUT_PROP_CNT]; + size_t nprops = ARRAY_LENGTH(props); + if (streq(key, quirk_get_name(QUIRK_ATTR_INPUT_PROP_DISABLE))) + p->id = QUIRK_ATTR_INPUT_PROP_DISABLE; + else + p->id = QUIRK_ATTR_INPUT_PROP_ENABLE; + + if (!parse_input_prop_property(value, props, &nprops) || + nprops == 0) + goto out; + + memcpy(p->value.array.data.u, props, nprops * sizeof(unsigned int)); + p->value.array.nelements = nprops; + p->type = PT_UINT_ARRAY; + + rc = true; } else { qlog_error(ctx, "Unknown key %s in %s\n", key, s->name); } @@ -916,7 +1019,7 @@ break; default: /* entries must start with A-Z */ - if (line[0] < 'A' && line[0] > 'Z') { + if (line[0] < 'A' || line[0] > 'Z') { qlog_parser(ctx, "%s:%d: Unexpected line %s\n", path, lineno, line); goto out; @@ -1209,6 +1312,10 @@ m->bus = BT_I2C; m->bits |= M_BUS; break; + case BUS_SPI: + m->bus = BT_SPI; + m->bits |= M_BUS; + break; default: break; } @@ -1583,3 +1690,25 @@ return true; } + +bool +quirks_get_uint32_array(struct quirks *q, + enum quirk which, + const uint32_t **array, + size_t *nelements) +{ + struct property *p; + + if (!q) + return false; + + p = quirk_find_prop(q, which); + if (!p) + return false; + + assert(p->type == PT_UINT_ARRAY); + *array = p->value.array.data.u; + *nelements = p->value.array.nelements; + + return true; +} diff -Nru libinput-1.16.4/src/quirks.h libinput-1.17.2/src/quirks.h --- libinput-1.16.4/src/quirks.h 2020-11-27 01:38:59.377086200 +0000 +++ libinput-1.17.2/src/quirks.h 2021-04-30 04:25:41.534076200 +0000 @@ -72,11 +72,8 @@ QUIRK_MODEL_HP_STREAM11_TOUCHPAD, QUIRK_MODEL_HP_ZBOOK_STUDIO_G3, QUIRK_MODEL_INVERT_HORIZONTAL_SCROLLING, - QUIRK_MODEL_LENOVO_L380_TOUCHPAD, QUIRK_MODEL_LENOVO_SCROLLPOINT, QUIRK_MODEL_LENOVO_T450_TOUCHPAD, - QUIRK_MODEL_LENOVO_T480S_TOUCHPAD, - QUIRK_MODEL_LENOVO_T490S_TOUCHPAD, QUIRK_MODEL_LENOVO_X1GEN6_TOUCHPAD, QUIRK_MODEL_LENOVO_X230, QUIRK_MODEL_SYNAPTICS_SERIAL_TOUCHPAD, @@ -109,6 +106,9 @@ QUIRK_ATTR_THUMB_SIZE_THRESHOLD, QUIRK_ATTR_MSC_TIMESTAMP, QUIRK_ATTR_EVENT_CODE_DISABLE, + QUIRK_ATTR_EVENT_CODE_ENABLE, + QUIRK_ATTR_INPUT_PROP_DISABLE, + QUIRK_ATTR_INPUT_PROP_ENABLE, _QUIRK_LAST_ATTR_QUIRK_, /* Guard: do not modify */ }; @@ -118,7 +118,7 @@ * tools, not user consumption. Do not display this in a GUI. */ const char* -quirk_get_name(enum quirk which); +quirk_get_name(enum quirk q); /** * Log priorities used if custom logging is enabled. @@ -312,3 +312,17 @@ quirks_get_tuples(struct quirks *q, enum quirk which, const struct quirk_tuples **tuples); + +/** + * Get the uint32 array of the given quirk. + * This function will assert if the quirk type does not match the + * requested type. If the quirk is not set for this device, tuples is + * unchanged. + * + * @return true if the quirk value is valid, false otherwise. + */ +bool +quirks_get_uint32_array(struct quirks *q, + enum quirk which, + const uint32_t **array, + size_t *nelements); diff -Nru libinput-1.16.4/src/timer.c libinput-1.17.2/src/timer.c --- libinput-1.16.4/src/timer.c 2020-11-27 01:38:59.377086200 +0000 +++ libinput-1.17.2/src/timer.c 2021-04-30 04:25:41.534076200 +0000 @@ -48,7 +48,7 @@ void libinput_timer_destroy(struct libinput_timer *timer) { - if (timer->link.prev != NULL && timer->link.prev != NULL && + if (timer->link.prev != NULL && timer->link.next != NULL && !list_empty(&timer->link)) { log_bug_libinput(timer->libinput, "timer: %s has not been cancelled\n", diff -Nru libinput-1.16.4/src/udev-seat.c libinput-1.17.2/src/udev-seat.c --- libinput-1.16.4/src/udev-seat.c 2020-11-27 01:38:59.377086200 +0000 +++ libinput-1.17.2/src/udev-seat.c 2021-04-30 04:25:41.534076200 +0000 @@ -128,7 +128,9 @@ sysname, devnode); return 0; - } else if (device == NULL) { + } + + if (device == NULL) { log_info(&input->base, "%-7s - failed to create input device '%s'\n", sysname, @@ -287,8 +289,11 @@ return -1; } - udev_monitor_filter_add_match_subsystem_devtype(input->udev_monitor, - "input", NULL); + if (udev_monitor_filter_add_match_subsystem_devtype( + input->udev_monitor, "input", NULL)) { + log_info(libinput, "udev: failed to set up filter\n"); + return -1; + } if (udev_monitor_enable_receiving(input->udev_monitor)) { log_info(libinput, "udev: failed to bind the udev monitor\n"); diff -Nru libinput-1.16.4/src/util-prop-parsers.c libinput-1.17.2/src/util-prop-parsers.c --- libinput-1.16.4/src/util-prop-parsers.c 2020-11-27 01:38:59.378086000 +0000 +++ libinput-1.17.2/src/util-prop-parsers.c 2021-04-30 04:25:41.534076200 +0000 @@ -249,7 +249,7 @@ /** * Parses a string of the format "a:b" where both a and b must be integer - * numbers and a > b. Also allowed is the special string vaule "none" which + * numbers and a > b. Also allowed is the special string value "none" which * amounts to unsetting the property. * * @param prop The value of the property @@ -398,6 +398,63 @@ rc = true; out: + strv_free(strv); + return rc; +} + +/** + * Parses a string of the format "INPUT_PROP_BUTTONPAD;INPUT_PROP_POINTER;0x123;" + * where each element must be a named input prop OR a hexcode in the form + * 0x1234 + * + * props must point to an existing array of size nprops. + * nprops specifies the size of the array in props and returns the number + * of elements, elements exceeding nprops are simply ignored, just make sure + * props is large enough for your use-case. + * + * On success, props contains nprops elements. + */ +bool +parse_input_prop_property(const char *prop, unsigned int *props_out, size_t *nprops) +{ + char **strv = NULL; + bool rc = false; + size_t count = 0; + size_t idx; + unsigned int props[INPUT_PROP_CNT]; /* doubling up on quirks is a bug */ + + strv = strv_from_string(prop, ";"); + if (!strv) + goto out; + + for (idx = 0; strv[idx]; idx++) + count++; + + if (count == 0 || count > ARRAY_LENGTH(props)) + goto out; + + count = min(*nprops, count); + for (idx = 0; strv[idx]; idx++) { + char *s = strv[idx]; + unsigned int prop; + + if (safe_atou_base(s, &prop, 16)) { + if (prop > INPUT_PROP_MAX) + goto out; + } else { + int val = libevdev_property_from_name(s); + if (val == -1) + goto out; + prop = (unsigned int)val; + } + props[idx] = prop; + } + + memcpy(props_out, props, count * sizeof *props); + *nprops = count; + rc = true; + +out: strv_free(strv); return rc; } diff -Nru libinput-1.16.4/src/util-prop-parsers.h libinput-1.17.2/src/util-prop-parsers.h --- libinput-1.16.4/src/util-prop-parsers.h 2020-11-27 01:38:59.379086000 +0000 +++ libinput-1.17.2/src/util-prop-parsers.h 2021-04-30 04:25:41.534076200 +0000 @@ -38,6 +38,7 @@ bool parse_range_property(const char *prop, int *hi, int *lo); #define EVENT_CODE_UNDEFINED 0xffff bool parse_evcode_property(const char *prop, struct input_event *events, size_t *nevents); +bool parse_input_prop_property(const char *prop, unsigned int *props_out, size_t *nprops); enum tpkbcombo_layout { TPKBCOMBO_LAYOUT_UNKNOWN, diff -Nru libinput-1.16.4/src/util-ratelimit.c libinput-1.17.2/src/util-ratelimit.c --- libinput-1.16.4/src/util-ratelimit.c 2020-11-27 01:38:59.379086000 +0000 +++ libinput-1.17.2/src/util-ratelimit.c 2021-04-30 04:25:41.534076200 +0000 @@ -69,7 +69,9 @@ r->begin = utime; r->num = 1; return RATELIMIT_PASS; - } else if (r->num < r->burst) { + } + + if (r->num < r->burst) { /* continue burst */ return (++r->num == r->burst) ? RATELIMIT_THRESHOLD : RATELIMIT_PASS; diff -Nru libinput-1.16.4/src/util-ratelimit.h libinput-1.17.2/src/util-ratelimit.h --- libinput-1.16.4/src/util-ratelimit.h 2020-11-27 01:38:59.379086000 +0000 +++ libinput-1.17.2/src/util-ratelimit.h 2021-04-30 04:25:41.534076200 +0000 @@ -41,5 +41,5 @@ unsigned int num; }; -void ratelimit_init(struct ratelimit *r, uint64_t ival_ms, unsigned int burst); +void ratelimit_init(struct ratelimit *r, uint64_t ival_us, unsigned int burst); enum ratelimit_state ratelimit_test(struct ratelimit *r); diff -Nru libinput-1.16.4/src/util-strings.c libinput-1.17.2/src/util-strings.c --- libinput-1.16.4/src/util-strings.c 2020-11-27 01:38:59.379086000 +0000 +++ libinput-1.17.2/src/util-strings.c 2021-04-30 04:25:41.534076200 +0000 @@ -115,7 +115,7 @@ * An empty strv ([NULL]) returns NULL, same for passing NULL as either * argument. * - * @param strv Input string arrray + * @param strv Input string array * @param joiner Joiner between the elements in the final string * * @return A null-terminated string joining all elements @@ -155,3 +155,54 @@ return str; } + +/** + * Return a pointer to the basename within filename. + * If the filename the empty string or a directory (i.e. the last char of + * filename is '/') NULL is returned. + */ +const char * +safe_basename(const char *filename) +{ + const char *basename; + + if (*filename == '\0') + return NULL; + + basename = strrchr(filename, '/'); + if (basename == NULL) + return filename; + + if (*(basename + 1) == '\0') + return NULL; + + return basename + 1; +} + + +/** + * Similar to basename() but returns the trunk only without the (last) + * trailing suffix, so that: + * + * - foo.c returns foo + * - foo.a.b returns foo.a + * - foo returns foo + * - foo/ returns "" + * + * @return an allocated string representing the trunk name of the file + */ +char * +trunkname(const char *filename) +{ + const char *base = safe_basename(filename); + char *suffix; + + if (base == NULL) + return strdup(""); + + suffix = rindex(base, '.'); + if (suffix == NULL) + return strdup(base); + else + return strndup(base, suffix-base); +} diff -Nru libinput-1.16.4/src/util-strings.h libinput-1.17.2/src/util-strings.h --- libinput-1.16.4/src/util-strings.h 2020-11-27 01:38:59.379086000 +0000 +++ libinput-1.17.2/src/util-strings.h 2021-04-30 04:25:41.534076200 +0000 @@ -43,8 +43,23 @@ #include #endif -#define streq(s1, s2) (strcmp((s1), (s2)) == 0) -#define strneq(s1, s2, n) (strncmp((s1), (s2), (n)) == 0) +static inline bool +streq(const char *str1, const char *str2) +{ + /* one NULL, one not NULL is always false */ + if (str1 && str2) + return strcmp(str1, str2) == 0; + return str1 == str2; +} + +static inline bool +strneq(const char *str1, const char *str2, int n) +{ + /* one NULL, one not NULL is always false */ + if (str1 && str2) + return strncmp(str1, str2, n) == 0; + return str1 == str2; +} static inline void * zalloc(size_t size) @@ -111,6 +126,18 @@ return rc; } +__attribute__ ((format (printf, 2, 0))) +static inline int +xvasprintf(char **strp, const char *fmt, va_list args) +{ + int rc = 0; + rc = vasprintf(strp, fmt, args); + if ((rc == -1) && strp) + *strp = NULL; + + return rc; +} + static inline bool safe_atoi_base(const char *str, int *val, int base) { @@ -225,8 +252,8 @@ return true; } -char **strv_from_string(const char *string, const char *separator); -char *strv_join(char **strv, const char *separator); +char **strv_from_string(const char *in, const char *separator); +char *strv_join(char **strv, const char *joiner); static inline void strv_free(char **strv) { @@ -364,3 +391,9 @@ return prefixlen > 0 ? strneq(str, prefix, strlen(prefix)) : false; } + +const char * +safe_basename(const char *filename); + +char * +trunkname(const char *filename); diff -Nru libinput-1.16.4/test/build-cxx.cc libinput-1.17.2/test/build-cxx.cc --- libinput-1.16.4/test/build-cxx.cc 2020-11-27 01:38:59.380086200 +0000 +++ libinput-1.17.2/test/build-cxx.cc 2021-04-30 04:25:41.534076200 +0000 @@ -5,7 +5,7 @@ using namespace std; int -main(int argc, char **argv) +main(void) { return 0; } diff -Nru libinput-1.16.4/test/litest.c libinput-1.17.2/test/litest.c --- libinput-1.16.4/test/litest.c 2020-11-27 01:38:59.387086200 +0000 +++ libinput-1.17.2/test/litest.c 2021-04-30 04:25:41.539076300 +0000 @@ -65,6 +65,8 @@ #include +#define evbit(t, c) ((t) << 16U | (c & 0xffff)) + #define UDEV_RULES_D "/run/udev/rules.d" #define UDEV_FUZZ_OVERRIDE_RULE_FILE UDEV_RULES_D \ "/91-litest-fuzz-override-REMOVEME-XXXXXX.rules" @@ -427,25 +429,6 @@ get_suite(const char *name) { struct suite *s; - /* this is the list meson calls, ensure we don't miss out on tests */ - const char * allowed_suites[] = { - "config:", "context:", "device:", "events:", "gestures:", - "keyboard:", "lid:", "log:", "misc:", "pad:", "path:", - "pointer:", "quirks:", "switch:", "tablet:", "tablet-mode:", - "tap:", "timer:", "totem:", "touch:", "touchpad:", - "trackball:", "trackpoint:", "udev:", - }; - const char **allowed; - bool found = false; - - ARRAY_FOR_EACH(allowed_suites, allowed) { - if (strstartswith(name, *allowed)) { - found = true; - break; - } - } - if (!found) - litest_abort_msg("Suite name '%s' is not allowed\n", name); list_for_each(s, &all_tests, node) { if (streq(s->name, name)) @@ -462,13 +445,28 @@ } static void -litest_add_tcase(const char *suite_name, +create_suite_name(const char *filename, char suitename[64]) +{ + char *trunk = trunkname(filename); + char *p = trunk; + + /* strip the test- prefix */ + if (strstartswith(trunk, "test-")) + p += 5; + + snprintf(suitename, 64, "%s", p); + free(trunk); +} + +static void +litest_add_tcase(const char *filename, const char *funcname, const void *func, int64_t required, int64_t excluded, const struct range *range) { + char suite_name[65]; struct suite *suite; bool added = false; @@ -480,9 +478,9 @@ fnmatch(filter_test, funcname, 0) != 0) return; - if (filter_group && - strstr(suite_name, filter_group) == NULL && - fnmatch(filter_group, suite_name, 0) != 0) + create_suite_name(filename, suite_name); + + if (filter_group && fnmatch(filter_group, suite_name, 0) != 0) return; suite = get_suite(suite_name); @@ -616,7 +614,7 @@ } void -_litest_add_ranged_for_device(const char *name, +_litest_add_ranged_for_device(const char *filename, const char *funcname, const void *func, enum litest_device_type type, @@ -625,6 +623,7 @@ struct suite *s; struct litest_test_device *dev; bool device_filtered = false; + char suite_name[64]; litest_assert(type < LITEST_NO_DEVICE); @@ -633,12 +632,11 @@ fnmatch(filter_test, funcname, 0) != 0) return; - if (filter_group && - strstr(name, filter_group) == NULL && - fnmatch(filter_group, name, 0) != 0) + create_suite_name(filename, suite_name); + if (filter_group && fnmatch(filter_group, suite_name, 0) != 0) return; - s = get_suite(name); + s = get_suite(suite_name); list_for_each(dev, &devices, node) { if (filter_device && strstr(dev->shortname, filter_device) == NULL && @@ -1424,7 +1422,7 @@ false); list_insert(created_files_list, &file->link); - /* Ony install the litest device rule when we're running as system + /* Only install the litest device rule when we're running as system * test suite, we expect the others to be in place already */ if (use_system_rules_quirks) return; @@ -1812,6 +1810,7 @@ d->interface->min[ABS_Y] = libevdev_get_abs_minimum(d->evdev, code); d->interface->max[ABS_Y] = libevdev_get_abs_maximum(d->evdev, code); } + d->interface->tool_type = BTN_TOOL_PEN; } return d; } @@ -1892,7 +1891,7 @@ udev_device = udev_monitor_receive_device(udev_monitor); litest_assert_notnull(udev_device); udev_action = udev_device_get_action(udev_device); - if (!streq(udev_action, udev_event)) { + if (!udev_action || !streq(udev_action, udev_event)) { udev_device_unref(udev_device); continue; } @@ -2444,15 +2443,56 @@ } void +litest_tablet_set_tool_type(struct litest_device *d, unsigned int code) +{ + switch (code) { + case BTN_TOOL_PEN: + case BTN_TOOL_RUBBER: + case BTN_TOOL_BRUSH: + case BTN_TOOL_PENCIL: + case BTN_TOOL_AIRBRUSH: + case BTN_TOOL_MOUSE: + case BTN_TOOL_LENS: + break; + default: + abort(); + } + + d->interface->tool_type = code; +} + +static void +litest_tool_event(struct litest_device *d, int value) +{ + unsigned int tool = d->interface->tool_type; + + litest_event(d, EV_KEY, tool, value); +} + +void litest_tablet_proximity_in(struct litest_device *d, int x, int y, struct axis_replacement *axes) { struct input_event *ev; + /* If the test device overrides proximity_in and says it didn't + * handle the event, let's continue normally */ + if (d->interface->tablet_proximity_in && + d->interface->tablet_proximity_in(d, d->interface->tool_type, x, y, axes)) + return; + ev = d->interface->tablet_proximity_in_events; while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) { - int value = auto_assign_tablet_value(d, ev, x, y, axes); - if (!tablet_ignore_event(ev, value)) - litest_event(d, ev->type, ev->code, value); + int value; + + switch (evbit(ev->type, ev->code)) { + case evbit(EV_KEY, LITEST_BTN_TOOL_AUTO): + litest_tool_event(d, ev->value); + break; + default: + value = auto_assign_tablet_value(d, ev, x, y, axes); + if (!tablet_ignore_event(ev, value)) + litest_event(d, ev->type, ev->code, value); + } ev++; } } @@ -2462,11 +2502,26 @@ { struct input_event *ev; + /* If the test device overrides proximity_out and says it didn't + * handle the event, let's continue normally */ + if (d->interface->tablet_proximity_out && + d->interface->tablet_proximity_out(d, d->interface->tool_type)) + return; + ev = d->interface->tablet_proximity_out_events; while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) { - int value = auto_assign_tablet_value(d, ev, -1, -1, NULL); - if (!tablet_ignore_event(ev, value)) - litest_event(d, ev->type, ev->code, value); + int value; + + switch (evbit(ev->type, ev->code)) { + case evbit(EV_KEY, LITEST_BTN_TOOL_AUTO): + litest_tool_event(d, ev->value); + break; + default: + value = auto_assign_tablet_value(d, ev, -1, -1, NULL); + if (!tablet_ignore_event(ev, value)) + litest_event(d, ev->type, ev->code, value); + break; + } ev++; } } @@ -3591,6 +3646,20 @@ return gevent; } +void +litest_assert_gesture_event(struct libinput *li, + enum libinput_event_type type, + int nfingers) +{ + struct libinput_event *event; + + litest_wait_for_event(li); + event = libinput_get_event(li); + + litest_is_gesture_event(event, type, nfingers); + libinput_event_destroy(event); +} + struct libinput_event_tablet_tool * litest_is_tablet_event(struct libinput_event *event, enum libinput_event_type type) @@ -3780,13 +3849,12 @@ enum libinput_button_state state) { struct libinput_event *event; - struct libinput_event_tablet_pad *pev; litest_wait_for_event(li); event = libinput_get_event(li); - pev = litest_is_pad_button_event(event, button, state); - libinput_event_destroy(libinput_event_tablet_pad_get_base_event(pev)); + litest_is_pad_button_event(event, button, state); + libinput_event_destroy(event); } void @@ -3795,13 +3863,12 @@ enum libinput_key_state state) { struct libinput_event *event; - struct libinput_event_tablet_pad *pev; litest_wait_for_event(li); event = libinput_get_event(li); - pev = litest_is_pad_key_event(event, key, state); - libinput_event_destroy(libinput_event_tablet_pad_get_base_event(pev)); + litest_is_pad_key_event(event, key, state); + libinput_event_destroy(event); } void @@ -3865,8 +3932,7 @@ litest_assert_notnull(event); while (event) { - litest_assert_int_eq(libinput_event_get_type(event), - type); + litest_assert_event_type(event, type); libinput_event_destroy(event); libinput_dispatch(li); event = libinput_get_event(li); @@ -4003,7 +4069,7 @@ void litest_timeout_tap(void) { - msleep(200); + msleep(300); } void @@ -4557,23 +4623,20 @@ if (mode == LITEST_MODE_ERROR) return EXIT_FAILURE; - if (!run_deviceless && (rc = check_device_access()) != 0) - return rc; - litest_init_test_devices(); - list_init(&all_tests); - - setenv("CK_DEFAULT_TIMEOUT", "30", 0); - setenv("LIBINPUT_RUNNING_TEST_SUITE", "1", 1); - setup_tests(); - if (mode == LITEST_MODE_LIST) { litest_list_tests(&all_tests); return EXIT_SUCCESS; } + if (!run_deviceless && (rc = check_device_access()) != 0) + return rc; + + setenv("CK_DEFAULT_TIMEOUT", "30", 0); + setenv("LIBINPUT_RUNNING_TEST_SUITE", "1", 1); + if (setrlimit(RLIMIT_CORE, &corelimit) != 0) perror("WARNING: Core dumps not disabled"); diff -Nru libinput-1.16.4/test/litest-device-elan-tablet.c libinput-1.17.2/test/litest-device-elan-tablet.c --- libinput-1.16.4/test/litest-device-elan-tablet.c 2020-11-27 01:38:59.383086000 +0000 +++ libinput-1.17.2/test/litest-device-elan-tablet.c 2021-04-30 04:25:41.535076400 +0000 @@ -26,22 +26,22 @@ #include "litest.h" #include "litest-int.h" -static struct input_event proximity_in[] = { +static struct input_event proximity_in_events[] = { { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 1 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 1 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; -static struct input_event proximity_out[] = { - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 0 }, +static struct input_event proximity_out_events[] = { + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 0 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; -static struct input_event motion[] = { +static struct input_event motion_events[] = { { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, @@ -49,6 +49,42 @@ { .type = -1, .code = -1 }, }; +static bool +proximity_in(struct litest_device *d, + unsigned int tool_type, + double x, double y, + struct axis_replacement *axes) +{ + /* nothing special needed for the pen tool, so let litest handle + * this */ + if (tool_type == BTN_TOOL_PEN) + return false; + + /* a non-pen tool requires the pen to be in proximity as well. */ + x = litest_scale(d, ABS_X, x); + y = litest_scale(d, ABS_Y, y); + litest_event(d, EV_ABS, ABS_X, x); + litest_event(d, EV_ABS, ABS_X, y); + litest_event(d, EV_KEY, BTN_TOOL_PEN, 1); + litest_event(d, EV_SYN, SYN_REPORT, 0); + + /* litest will append the proximity_in_events if we return false, + * including the right tool event */ + return false; +} + +static bool +proximity_out(struct litest_device *d, unsigned int tool_type) +{ + /* a non-pen tool requires the pen to go out of proximity as well. + * litest will append the proximity_out_events if we return false + */ + if (tool_type != BTN_TOOL_PEN) + litest_event(d, EV_KEY, BTN_TOOL_PEN, 0); + + return false; +} + static int get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value) { @@ -61,9 +97,11 @@ } static struct litest_device_interface interface = { - .tablet_proximity_in_events = proximity_in, - .tablet_proximity_out_events = proximity_out, - .tablet_motion_events = motion, + .tablet_proximity_in_events = proximity_in_events, + .tablet_proximity_out_events = proximity_out_events, + .tablet_motion_events = motion_events, + .tablet_proximity_in = proximity_in, + .tablet_proximity_out = proximity_out, .get_axis_default = get_axis_default, }; @@ -82,6 +120,11 @@ .version = 0x100, }; +/* Note: this tablet is one that sets both BTN_TOOL_PEN and BTN_TOOL_RUBBER, + * see https://gitlab.freedesktop.org/libinput/libinput/-/issues/259 + * The one in the issue isn't the exact same model, but only the pid and x/y + * axis max differs differs. + */ static int events[] = { EV_KEY, BTN_TOOL_PEN, EV_KEY, BTN_TOOL_RUBBER, diff -Nru libinput-1.16.4/test/litest-device-generic-pressurepad.c libinput-1.17.2/test/litest-device-generic-pressurepad.c --- libinput-1.16.4/test/litest-device-generic-pressurepad.c 1970-01-01 00:00:00.000000000 +0000 +++ libinput-1.17.2/test/litest-device-generic-pressurepad.c 2021-04-30 04:25:41.536076300 +0000 @@ -0,0 +1,125 @@ +/* + * Copyright © 2021 Red Hat, Inc. + * + * 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 "litest.h" +#include "litest-int.h" + +/* This is the same device as the one from + https://gitlab.freedesktop.org/libinput/libinput/-/issues/562 + + Except this one has a different input_id and sets the pressure + resolution to test the generic pressure handling. + */ + +static struct input_event down[] = { + { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, + { .type = -1, .code = -1 }, +}; + +static struct input_event move[] = { + { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, + { .type = -1, .code = -1 }, +}; + + +static int +get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value) +{ + switch (evcode) { + /* Always set pressure to zero. The real device sends pressure + * values > 30 when the device is clicked but until this is a) + * handled by libinput and b) integrated into this test suite + * a zero value does the job. + */ + case ABS_PRESSURE: + case ABS_MT_PRESSURE: + *value = 0; + return 0; + } + return 1; +} + +static struct litest_device_interface interface = { + .touch_down_events = down, + .touch_move_events = move, + + .get_axis_default = get_axis_default, +}; + +static struct input_id input_id = { + .bustype = 0x18, + .vendor = 0x123, + .product = 0x4567, +}; + +static int events[] = { + EV_KEY, BTN_LEFT, + EV_KEY, BTN_TOOL_FINGER, + EV_KEY, BTN_TOUCH, + EV_KEY, BTN_TOOL_DOUBLETAP, + EV_KEY, BTN_TOOL_TRIPLETAP, + EV_KEY, BTN_TOOL_QUADTAP, + EV_KEY, BTN_TOOL_QUINTTAP, + INPUT_PROP_MAX, INPUT_PROP_POINTER, + INPUT_PROP_MAX, INPUT_PROP_BUTTONPAD, + -1, -1, +}; + +static struct input_absinfo absinfo[] = { + { ABS_X, 0, 1224, 0, 0, 12 }, + { ABS_Y, 0, 756, 0, 0, 12 }, + { ABS_PRESSURE, 0, 255, 0, 0, 40 }, /* some random resolution */ + { ABS_MT_SLOT, 0, 4, 0, 0, 0 }, + { ABS_MT_POSITION_X, 0, 1224, 0, 0, 12 }, + { ABS_MT_POSITION_Y, 0, 756, 0, 0, 12 }, + { ABS_MT_TRACKING_ID, 0, 65535, 0, 0, 0 }, + { ABS_MT_PRESSURE, 0, 255, 0, 0, 40 }, /* some random resolution */ + { ABS_MT_TOOL_TYPE, 0, 2, 0, 0, 0 }, + { .value = -1 } +}; + +TEST_DEVICE("generic-pressurepad", + .type = LITEST_GENERIC_PRESSUREPAD, + .features = LITEST_TOUCHPAD | LITEST_CLICKPAD | LITEST_BUTTON, + .interface = &interface, + + .name = "Some Generic Pressurepad Touchpad", + .id = &input_id, + .events = events, + .absinfo = absinfo, +) diff -Nru libinput-1.16.4/test/litest-device-huion-pentablet.c libinput-1.17.2/test/litest-device-huion-pentablet.c --- libinput-1.16.4/test/litest-device-huion-pentablet.c 2020-11-27 01:38:59.383086000 +0000 +++ libinput-1.17.2/test/litest-device-huion-pentablet.c 2021-04-30 04:25:41.536076300 +0000 @@ -30,7 +30,7 @@ { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 1 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 1 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; diff -Nru libinput-1.16.4/test/litest-device-keyboard-quirked.c libinput-1.17.2/test/litest-device-keyboard-quirked.c --- libinput-1.16.4/test/litest-device-keyboard-quirked.c 1970-01-01 00:00:00.000000000 +0000 +++ libinput-1.17.2/test/litest-device-keyboard-quirked.c 2021-04-30 04:25:41.536076300 +0000 @@ -0,0 +1,231 @@ +/* + * Copyright © 2013 Red Hat, Inc. + * + * 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 "litest.h" +#include "litest-int.h" + +static struct input_id input_id = { + .bustype = 0x11, + .vendor = 0x1, + .product = 0x1, +}; + +static int events[] = { + EV_REL, REL_X, + EV_REL, REL_Y, + + EV_KEY, KEY_ESC, + EV_KEY, KEY_1, + EV_KEY, KEY_2, + EV_KEY, KEY_3, + EV_KEY, KEY_4, + EV_KEY, KEY_5, + EV_KEY, KEY_6, + EV_KEY, KEY_7, + EV_KEY, KEY_8, + EV_KEY, KEY_9, + EV_KEY, KEY_0, + EV_KEY, KEY_MINUS, + EV_KEY, KEY_EQUAL, + EV_KEY, KEY_BACKSPACE, + EV_KEY, KEY_TAB, + EV_KEY, KEY_Q, + EV_KEY, KEY_W, + EV_KEY, KEY_E, + EV_KEY, KEY_R, + EV_KEY, KEY_T, + EV_KEY, KEY_Y, + EV_KEY, KEY_U, + EV_KEY, KEY_I, + EV_KEY, KEY_O, + EV_KEY, KEY_P, + EV_KEY, KEY_LEFTBRACE, + EV_KEY, KEY_RIGHTBRACE, + EV_KEY, KEY_ENTER, + EV_KEY, KEY_LEFTCTRL, + EV_KEY, KEY_A, + EV_KEY, KEY_S, + EV_KEY, KEY_D, + EV_KEY, KEY_F, + EV_KEY, KEY_G, + EV_KEY, KEY_H, + EV_KEY, KEY_J, + EV_KEY, KEY_K, + EV_KEY, KEY_L, + EV_KEY, KEY_SEMICOLON, + EV_KEY, KEY_APOSTROPHE, + EV_KEY, KEY_GRAVE, + EV_KEY, KEY_LEFTSHIFT, + EV_KEY, KEY_BACKSLASH, + EV_KEY, KEY_Z, + EV_KEY, KEY_X, + EV_KEY, KEY_C, + EV_KEY, KEY_V, + EV_KEY, KEY_B, + EV_KEY, KEY_N, + EV_KEY, KEY_M, + EV_KEY, KEY_COMMA, + EV_KEY, KEY_DOT, + EV_KEY, KEY_SLASH, + EV_KEY, KEY_RIGHTSHIFT, + EV_KEY, KEY_KPASTERISK, + EV_KEY, KEY_LEFTALT, + EV_KEY, KEY_SPACE, + EV_KEY, KEY_CAPSLOCK, + EV_KEY, KEY_F1, + EV_KEY, KEY_F2, + EV_KEY, KEY_F3, + EV_KEY, KEY_F4, + EV_KEY, KEY_F5, + EV_KEY, KEY_F6, + EV_KEY, KEY_F7, + EV_KEY, KEY_F8, + EV_KEY, KEY_F9, + EV_KEY, KEY_F10, + EV_KEY, KEY_NUMLOCK, + EV_KEY, KEY_SCROLLLOCK, + EV_KEY, KEY_KP7, + EV_KEY, KEY_KP8, + EV_KEY, KEY_KP9, + EV_KEY, KEY_KPMINUS, + EV_KEY, KEY_KP4, + EV_KEY, KEY_KP5, + EV_KEY, KEY_KP6, + EV_KEY, KEY_KPPLUS, + EV_KEY, KEY_KP1, + EV_KEY, KEY_KP2, + EV_KEY, KEY_KP3, + EV_KEY, KEY_KP0, + EV_KEY, KEY_KPDOT, + EV_KEY, KEY_ZENKAKUHANKAKU, + EV_KEY, KEY_102ND, + EV_KEY, KEY_F11, + EV_KEY, KEY_F12, + EV_KEY, KEY_RO, + EV_KEY, KEY_KATAKANA, + EV_KEY, KEY_HIRAGANA, + EV_KEY, KEY_HENKAN, + EV_KEY, KEY_KATAKANAHIRAGANA, + EV_KEY, KEY_MUHENKAN, + EV_KEY, KEY_KPJPCOMMA, + EV_KEY, KEY_KPENTER, + EV_KEY, KEY_RIGHTCTRL, + EV_KEY, KEY_KPSLASH, + EV_KEY, KEY_SYSRQ, + EV_KEY, KEY_RIGHTALT, + EV_KEY, KEY_LINEFEED, + EV_KEY, KEY_HOME, + EV_KEY, KEY_UP, + EV_KEY, KEY_PAGEUP, + EV_KEY, KEY_LEFT, + EV_KEY, KEY_RIGHT, + EV_KEY, KEY_END, + EV_KEY, KEY_DOWN, + EV_KEY, KEY_PAGEDOWN, + EV_KEY, KEY_INSERT, + EV_KEY, KEY_DELETE, + EV_KEY, KEY_MACRO, + EV_KEY, KEY_MUTE, + EV_KEY, KEY_VOLUMEDOWN, + EV_KEY, KEY_VOLUMEUP, + EV_KEY, KEY_POWER, + EV_KEY, KEY_KPEQUAL, + EV_KEY, KEY_KPPLUSMINUS, + EV_KEY, KEY_PAUSE, + /* EV_KEY, KEY_SCALE, */ + EV_KEY, KEY_KPCOMMA, + EV_KEY, KEY_HANGEUL, + EV_KEY, KEY_HANJA, + EV_KEY, KEY_YEN, + EV_KEY, KEY_LEFTMETA, + EV_KEY, KEY_RIGHTMETA, + EV_KEY, KEY_COMPOSE, + EV_KEY, KEY_STOP, + + EV_KEY, KEY_MENU, + EV_KEY, KEY_CALC, + EV_KEY, KEY_SETUP, + EV_KEY, KEY_SLEEP, + EV_KEY, KEY_WAKEUP, + EV_KEY, KEY_SCREENLOCK, + EV_KEY, KEY_DIRECTION, + EV_KEY, KEY_CYCLEWINDOWS, + EV_KEY, KEY_MAIL, + EV_KEY, KEY_BOOKMARKS, + EV_KEY, KEY_COMPUTER, + EV_KEY, KEY_BACK, + EV_KEY, KEY_FORWARD, + EV_KEY, KEY_NEXTSONG, + EV_KEY, KEY_PLAYPAUSE, + EV_KEY, KEY_PREVIOUSSONG, + EV_KEY, KEY_STOPCD, + EV_KEY, KEY_HOMEPAGE, + EV_KEY, KEY_REFRESH, + EV_KEY, KEY_F14, + EV_KEY, KEY_F15, + EV_KEY, KEY_SEARCH, + EV_KEY, KEY_MEDIA, + EV_KEY, KEY_FN, + EV_LED, LED_NUML, + EV_LED, LED_CAPSL, + EV_LED, LED_SCROLLL, + + /* gets disabled */ + INPUT_PROP_MAX, INPUT_PROP_POINTING_STICK, + + -1, -1, +}; + +static const char quirk_file[] = +"[litest Quirked Keyboard enable rel]\n" +"MatchName=litest Quirked Keyboard\n" +"AttrEventCodeEnable=BTN_RIGHT;EV_KEY:0x110\n" /* BTN_LEFT */ +"\n" +"[litest Quirked keyboard disable F1-F3]\n" +"MatchName=litest Quirked Keyboard\n" +"AttrEventCodeDisable=KEY_F1;EV_KEY:0x3c;KEY_F3\n" +#if HAVE_LIBEVDEV_DISABLE_PROPERTY +"\n" +"[litest Quirked keyboard enable buttonpad]\n" +"MatchName=litest Quirked Keyboard\n" +"AttrInputPropEnable=INPUT_PROP_BUTTONPAD\n" +"\n" +"[litest Quirked keyboard disable pointingstick]\n" +"MatchName=litest Quirked Keyboard\n" +"AttrInputPropDisable=INPUT_PROP_POINTING_STICK\n" +#endif +; + +TEST_DEVICE("keyboard-quirked", + .type = LITEST_KEYBOARD_QUIRKED, + .features = LITEST_KEYS | LITEST_IGNORED, /* Only use this keyboard in specific tests */ + .interface = NULL, + + .name = "Quirked Keyboard", + .id = &input_id, + .events = events, + .absinfo = NULL, + .quirk_file = quirk_file, +) diff -Nru libinput-1.16.4/test/litest-device-synaptics-pressurepad.c libinput-1.17.2/test/litest-device-synaptics-pressurepad.c --- libinput-1.16.4/test/litest-device-synaptics-pressurepad.c 1970-01-01 00:00:00.000000000 +0000 +++ libinput-1.17.2/test/litest-device-synaptics-pressurepad.c 2021-04-30 04:25:41.537076200 +0000 @@ -0,0 +1,125 @@ +/* + * Copyright © 2021 Red Hat, Inc. + * + * 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 "litest.h" +#include "litest-int.h" + +/* + * Device from https://gitlab.freedesktop.org/libinput/libinput/-/issues/562 + * + * This device relies on a quirk to disable the pressure axis, resolution is + * not set on ABS_PRESSURE. + */ + +static struct input_event down[] = { + { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, + { .type = -1, .code = -1 }, +}; + +static struct input_event move[] = { + { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, + { .type = -1, .code = -1 }, +}; + + +static int +get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value) +{ + switch (evcode) { + /* Always set pressure to zero. The real device sends pressure + * values > 30 when the device is clicked but until this is a) + * handled by libinput and b) integrated into this test suite + * a zero value does the job. + */ + case ABS_PRESSURE: + case ABS_MT_PRESSURE: + *value = 0; + return 0; + } + return 1; +} + +static struct litest_device_interface interface = { + .touch_down_events = down, + .touch_move_events = move, + + .get_axis_default = get_axis_default, +}; + +static struct input_id input_id = { + .bustype = 0x18, + .vendor = 0x6cb, + .product = 0xce37, +}; + +static int events[] = { + EV_KEY, BTN_LEFT, + EV_KEY, BTN_TOOL_FINGER, + EV_KEY, BTN_TOUCH, + EV_KEY, BTN_TOOL_DOUBLETAP, + EV_KEY, BTN_TOOL_TRIPLETAP, + EV_KEY, BTN_TOOL_QUADTAP, + EV_KEY, BTN_TOOL_QUINTTAP, + INPUT_PROP_MAX, INPUT_PROP_POINTER, + INPUT_PROP_MAX, INPUT_PROP_BUTTONPAD, + -1, -1, +}; + +static struct input_absinfo absinfo[] = { + { ABS_X, 0, 1224, 0, 0, 12 }, + { ABS_Y, 0, 756, 0, 0, 12 }, + { ABS_PRESSURE, 0, 255, 0, 0, 0 }, /* note: resolution zero */ + { ABS_MT_SLOT, 0, 4, 0, 0, 0 }, + { ABS_MT_POSITION_X, 0, 1224, 0, 0, 12 }, + { ABS_MT_POSITION_Y, 0, 756, 0, 0, 12 }, + { ABS_MT_TRACKING_ID, 0, 65535, 0, 0, 0 }, + { ABS_MT_PRESSURE, 0, 255, 0, 0, 0 }, /* note: resolution zero */ + { ABS_MT_TOOL_TYPE, 0, 2, 0, 0, 0 }, + { .value = -1 } +}; + +TEST_DEVICE("synaptics-pressurepad", + .type = LITEST_SYNAPTICS_PRESSUREPAD, + .features = LITEST_TOUCHPAD | LITEST_CLICKPAD | LITEST_BUTTON, + .interface = &interface, + + .name = "SYNA2B31:00 06CB:CE37 Touchpad", + .id = &input_id, + .events = events, + .absinfo = absinfo, +) diff -Nru libinput-1.16.4/test/litest-device-wacom-bamboo-16fg-pen.c libinput-1.17.2/test/litest-device-wacom-bamboo-16fg-pen.c --- libinput-1.16.4/test/litest-device-wacom-bamboo-16fg-pen.c 2020-11-27 01:38:59.386086000 +0000 +++ libinput-1.17.2/test/litest-device-wacom-bamboo-16fg-pen.c 2021-04-30 04:25:41.538076400 +0000 @@ -31,7 +31,7 @@ { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_DISTANCE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 1 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 1 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; @@ -40,7 +40,7 @@ { .type = EV_ABS, .code = ABS_X, .value = 0 }, { .type = EV_ABS, .code = ABS_Y, .value = 0 }, { .type = EV_ABS, .code = ABS_DISTANCE, .value = 0 }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 0 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 0 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; diff -Nru libinput-1.16.4/test/litest-device-wacom-bamboo-2fg-pen.c libinput-1.17.2/test/litest-device-wacom-bamboo-2fg-pen.c --- libinput-1.16.4/test/litest-device-wacom-bamboo-2fg-pen.c 2020-11-27 01:38:59.386086000 +0000 +++ libinput-1.17.2/test/litest-device-wacom-bamboo-2fg-pen.c 2021-04-30 04:25:41.538076400 +0000 @@ -31,7 +31,7 @@ { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_DISTANCE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 1 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 1 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; @@ -40,7 +40,7 @@ { .type = EV_ABS, .code = ABS_X, .value = 0 }, { .type = EV_ABS, .code = ABS_Y, .value = 0 }, { .type = EV_ABS, .code = ABS_DISTANCE, .value = 0 }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 0 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 0 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; diff -Nru libinput-1.16.4/test/litest-device-wacom-cintiq-12wx-pen.c libinput-1.17.2/test/litest-device-wacom-cintiq-12wx-pen.c --- libinput-1.16.4/test/litest-device-wacom-cintiq-12wx-pen.c 2020-11-27 01:38:59.386086000 +0000 +++ libinput-1.17.2/test/litest-device-wacom-cintiq-12wx-pen.c 2021-04-30 04:25:41.538076400 +0000 @@ -35,7 +35,7 @@ { .type = EV_ABS, .code = ABS_TILT_Y, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MISC, .value = 2083 }, { .type = EV_MSC, .code = MSC_SERIAL, .value = 297797542 }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 1 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 1 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; @@ -48,7 +48,7 @@ { .type = EV_ABS, .code = ABS_TILT_Y, .value = 0 }, { .type = EV_ABS, .code = ABS_MISC, .value = 0 }, { .type = EV_MSC, .code = MSC_SERIAL, .value = 297797542 }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 0 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 0 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; diff -Nru libinput-1.16.4/test/litest-device-wacom-cintiq-13hdt-pen.c libinput-1.17.2/test/litest-device-wacom-cintiq-13hdt-pen.c --- libinput-1.16.4/test/litest-device-wacom-cintiq-13hdt-pen.c 2020-11-27 01:38:59.386086000 +0000 +++ libinput-1.17.2/test/litest-device-wacom-cintiq-13hdt-pen.c 2021-04-30 04:25:41.538076400 +0000 @@ -35,7 +35,7 @@ { .type = EV_ABS, .code = ABS_TILT_Y, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MISC, .value = 2083 }, { .type = EV_MSC, .code = MSC_SERIAL, .value = 297797542 }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 1 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 1 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; @@ -48,7 +48,7 @@ { .type = EV_ABS, .code = ABS_TILT_Y, .value = 0 }, { .type = EV_ABS, .code = ABS_MISC, .value = 0 }, { .type = EV_MSC, .code = MSC_SERIAL, .value = 297797542 }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 0 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 0 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; diff -Nru libinput-1.16.4/test/litest-device-wacom-cintiq-24hd-pen.c libinput-1.17.2/test/litest-device-wacom-cintiq-24hd-pen.c --- libinput-1.16.4/test/litest-device-wacom-cintiq-24hd-pen.c 2020-11-27 01:38:59.386086000 +0000 +++ libinput-1.17.2/test/litest-device-wacom-cintiq-24hd-pen.c 2021-04-30 04:25:41.538076400 +0000 @@ -35,7 +35,7 @@ { .type = EV_ABS, .code = ABS_TILT_Y, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MISC, .value = 2083 }, { .type = EV_MSC, .code = MSC_SERIAL, .value = 297797542 }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 1 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 1 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; @@ -48,7 +48,7 @@ { .type = EV_ABS, .code = ABS_TILT_Y, .value = 0 }, { .type = EV_ABS, .code = ABS_MISC, .value = 0 }, { .type = EV_MSC, .code = MSC_SERIAL, .value = 297797542 }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 0 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 0 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; diff -Nru libinput-1.16.4/test/litest-device-wacom-cintiq-pro-16-pen.c libinput-1.17.2/test/litest-device-wacom-cintiq-pro-16-pen.c --- libinput-1.16.4/test/litest-device-wacom-cintiq-pro-16-pen.c 2020-11-27 01:38:59.386086000 +0000 +++ libinput-1.17.2/test/litest-device-wacom-cintiq-pro-16-pen.c 2021-04-30 04:25:41.538076400 +0000 @@ -37,7 +37,7 @@ { .type = EV_ABS, .code = ABS_TILT_Y, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MISC, .value = 2083 }, { .type = EV_MSC, .code = MSC_SERIAL, .value = 297797542 }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 1 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 1 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; @@ -52,7 +52,7 @@ { .type = EV_ABS, .code = ABS_TILT_Y, .value = 0 }, { .type = EV_ABS, .code = ABS_MISC, .value = 0 }, { .type = EV_MSC, .code = MSC_SERIAL, .value = 297797542 }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 0 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 0 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; diff -Nru libinput-1.16.4/test/litest-device-wacom-hid4800-pen.c libinput-1.17.2/test/litest-device-wacom-hid4800-pen.c --- libinput-1.16.4/test/litest-device-wacom-hid4800-pen.c 2020-11-27 01:38:59.386086000 +0000 +++ libinput-1.17.2/test/litest-device-wacom-hid4800-pen.c 2021-04-30 04:25:41.538076400 +0000 @@ -30,7 +30,7 @@ { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 1 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 1 }, { .type = EV_MSC, .code = MSC_SERIAL, .value = 297797542 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, @@ -40,7 +40,7 @@ { .type = EV_ABS, .code = ABS_X, .value = 0 }, { .type = EV_ABS, .code = ABS_Y, .value = 0 }, { .type = EV_MSC, .code = MSC_SERIAL, .value = 297797542 }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 0 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 0 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; diff -Nru libinput-1.16.4/test/litest-device-wacom-intuos5-pen.c libinput-1.17.2/test/litest-device-wacom-intuos5-pen.c --- libinput-1.16.4/test/litest-device-wacom-intuos5-pen.c 2020-11-27 01:38:59.386086000 +0000 +++ libinput-1.17.2/test/litest-device-wacom-intuos5-pen.c 2021-04-30 04:25:41.538076400 +0000 @@ -35,7 +35,7 @@ { .type = EV_ABS, .code = ABS_TILT_Y, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MISC, .value = 1050626 }, { .type = EV_MSC, .code = MSC_SERIAL, .value = 578837976 }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 1 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 1 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; @@ -48,7 +48,7 @@ { .type = EV_ABS, .code = ABS_TILT_Y, .value = 0 }, { .type = EV_ABS, .code = ABS_MISC, .value = 0 }, { .type = EV_MSC, .code = MSC_SERIAL, .value = 578837976 }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 0 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 0 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; diff -Nru libinput-1.16.4/test/litest-device-wacom-isdv4-4200-pen.c libinput-1.17.2/test/litest-device-wacom-isdv4-4200-pen.c --- libinput-1.16.4/test/litest-device-wacom-isdv4-4200-pen.c 2020-11-27 01:38:59.386086000 +0000 +++ libinput-1.17.2/test/litest-device-wacom-isdv4-4200-pen.c 2021-04-30 04:25:41.538076400 +0000 @@ -30,13 +30,13 @@ { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 1 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 1 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; static struct input_event proximity_out[] = { - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 0 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 0 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; diff -Nru libinput-1.16.4/test/litest-device-wacom-isdv4-e6-pen.c libinput-1.17.2/test/litest-device-wacom-isdv4-e6-pen.c --- libinput-1.16.4/test/litest-device-wacom-isdv4-e6-pen.c 2020-11-27 01:38:59.386086000 +0000 +++ libinput-1.17.2/test/litest-device-wacom-isdv4-e6-pen.c 2021-04-30 04:25:41.538076400 +0000 @@ -30,13 +30,13 @@ { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 1 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 1 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; static struct input_event proximity_out[] = { - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 0 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 0 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; diff -Nru libinput-1.16.4/test/litest-device-waltop-tablet.c libinput-1.17.2/test/litest-device-waltop-tablet.c --- libinput-1.16.4/test/litest-device-waltop-tablet.c 2020-11-27 01:38:59.387086200 +0000 +++ libinput-1.17.2/test/litest-device-waltop-tablet.c 2021-04-30 04:25:41.538076400 +0000 @@ -32,7 +32,7 @@ { .type = EV_ABS, .code = ABS_TILT_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_TILT_Y, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 1 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 1 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; @@ -42,7 +42,7 @@ { .type = EV_ABS, .code = ABS_Y, .value = 0 }, { .type = EV_ABS, .code = ABS_TILT_X, .value = 0 }, { .type = EV_ABS, .code = ABS_TILT_Y, .value = 0 }, - { .type = EV_KEY, .code = BTN_TOOL_PEN, .value = 0 }, + { .type = EV_KEY, .code = LITEST_BTN_TOOL_AUTO, .value = 0 }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; diff -Nru libinput-1.16.4/test/litest.h libinput-1.17.2/test/litest.h --- libinput-1.16.4/test/litest.h 2020-11-27 01:38:59.388086000 +0000 +++ libinput-1.17.2/test/litest.h 2021-04-30 04:25:41.539076300 +0000 @@ -78,6 +78,16 @@ }; \ static void (name##_setup)(void) + +/** + * litest itself needs the user_data to store some test-suite-specific + * information. Tests must not override this pointer, any data they need + * they can hang off the private pointer in this struct. + */ +struct litest_user_data { + void *private; +}; + void litest_fail_condition(const char *file, int line, @@ -306,6 +316,9 @@ LITEST_TABLET_MODE_UNRELIABLE, LITEST_KEYBOARD_LOGITECH_MEDIA_KEYBOARD_ELITE, LITEST_SONY_VAIO_KEYS, + LITEST_KEYBOARD_QUIRKED, + LITEST_SYNAPTICS_PRESSUREPAD, + LITEST_GENERIC_PRESSUREPAD, }; #define LITEST_DEVICELESS -2 @@ -427,20 +440,20 @@ void litest_restore_log_handler(struct libinput *libinput); void litest_set_log_handler_bug(struct libinput *libinput); -#define litest_add(name_, func_, ...) \ - _litest_add(name_, #func_, func_, __VA_ARGS__) -#define litest_add_ranged(name_, func_, ...) \ - _litest_add_ranged(name_, #func_, func_, __VA_ARGS__) -#define litest_add_for_device(name_, func_, ...) \ - _litest_add_for_device(name_, #func_, func_, __VA_ARGS__) -#define litest_add_ranged_for_device(name_, func_, ...) \ - _litest_add_ranged_for_device(name_, #func_, func_, __VA_ARGS__) -#define litest_add_no_device(name_, func_) \ - _litest_add_no_device(name_, #func_, func_) -#define litest_add_ranged_no_device(name_, func_, ...) \ - _litest_add_ranged_no_device(name_, #func_, func_, __VA_ARGS__) -#define litest_add_deviceless(name_, func_) \ - _litest_add_deviceless(name_, #func_, func_) +#define litest_add(func_, ...) \ + _litest_add(__FILE__, #func_, func_, __VA_ARGS__) +#define litest_add_ranged(func_, ...) \ + _litest_add_ranged(__FILE__, #func_, func_, __VA_ARGS__) +#define litest_add_for_device(func_, ...) \ + _litest_add_for_device(__FILE__, #func_, func_, __VA_ARGS__) +#define litest_add_ranged_for_device(func_, ...) \ + _litest_add_ranged_for_device(__FILE__, #func_, func_, __VA_ARGS__) +#define litest_add_no_device(func_) \ + _litest_add_no_device(__FILE__, #func_, func_) +#define litest_add_ranged_no_device(func_, ...) \ + _litest_add_ranged_no_device(__FILE__, #func_, func_, __VA_ARGS__) +#define litest_add_deviceless(func_) \ + _litest_add_deviceless(__FILE__, #func_, func_) void _litest_add(const char *name, @@ -604,6 +617,10 @@ int steps); void +litest_tablet_set_tool_type(struct litest_device *d, + unsigned int code); + +void litest_tablet_proximity_in(struct litest_device *d, int x, int y, struct axis_replacement *axes); @@ -822,6 +839,12 @@ litest_assert_pad_key_event(struct libinput *li, unsigned int key, enum libinput_key_state state); + +void +litest_assert_gesture_event(struct libinput *li, + enum libinput_event_type type, + int nfingers); + struct libevdev_uinput * litest_create_uinput_device(const char *name, struct input_id *id, diff -Nru libinput-1.16.4/test/litest-int.h libinput-1.17.2/test/litest-int.h --- libinput-1.16.4/test/litest-int.h 2020-11-27 01:38:59.387086200 +0000 +++ libinput-1.17.2/test/litest-int.h 2021-04-30 04:25:41.538076400 +0000 @@ -31,6 +31,9 @@ /* Use as designater for litest to change the value */ #define LITEST_AUTO_ASSIGN INT_MIN +/* Special event code to auto-assign the BTN_TOOL_PEN and friends */ +#define LITEST_BTN_TOOL_AUTO (KEY_MAX << 1) + struct litest_test_device { struct list node; /* global test device list */ @@ -111,6 +114,12 @@ struct input_event *tablet_proximity_out_events; struct input_event *tablet_motion_events; + bool (*tablet_proximity_in)(struct litest_device *d, + unsigned int tool_type, + double x, double y, + struct axis_replacement *axes); + bool (*tablet_proximity_out)(struct litest_device *d, unsigned int tool_type); + /** * Pad events, LITEST_AUTO_ASSIGN is allowed on event values * for ABS_WHEEL @@ -129,6 +138,8 @@ int min[2]; /* x/y axis minimum */ int max[2]; /* x/y axis maximum */ + + unsigned int tool_type; }; struct path { @@ -138,6 +149,7 @@ }; struct litest_context { + struct litest_user_data *user_data; struct list paths; }; diff -Nru libinput-1.16.4/test/test-device.c libinput-1.17.2/test/test-device.c --- libinput-1.16.4/test/test-device.c 2020-11-27 01:38:59.389086000 +0000 +++ libinput-1.17.2/test/test-device.c 2021-04-30 04:25:41.540076300 +0000 @@ -164,7 +164,7 @@ ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); litest_assert_empty_queue(li); - /* event from renabled device */ + /* event from re-enabled device */ litest_event(dev, EV_REL, REL_X, 10); litest_event(dev, EV_SYN, SYN_REPORT, 0); @@ -1419,6 +1419,95 @@ } END_TEST +char *debug_messages[64] = { NULL }; + +static void +debug_log_handler(struct libinput *libinput, + enum libinput_log_priority priority, + const char *format, + va_list args) +{ + char *message; + int n; + + if (priority != LIBINPUT_LOG_PRIORITY_DEBUG) + return; + + n = xvasprintf(&message, format, args); + litest_assert_int_gt(n, 0); + + for (size_t idx = 0; idx < ARRAY_LENGTH(debug_messages); idx++) { + if (debug_messages[idx] == NULL) { + debug_messages[idx] = message; + return; + } + } + + litest_abort_msg("Out of space for debug messages"); +} + +START_TEST(device_quirks) +{ + struct libinput *li; + struct litest_device *dev; + struct libinput_device *device; + char **message; + bool disable_key_f1 = false, + enable_btn_left = false; +#if HAVE_LIBEVDEV_DISABLE_PROPERTY + bool disable_pointingstick = false, + enable_buttonpad = false; +#endif + + li = litest_create_context(); + libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG); + libinput_log_set_handler(li, debug_log_handler); + dev = litest_add_device(li, LITEST_KEYBOARD_QUIRKED); + device = dev->libinput_device; + + ck_assert(libinput_device_pointer_has_button(device, + BTN_LEFT)); + ck_assert(libinput_device_pointer_has_button(dev->libinput_device, + BTN_RIGHT)); + ck_assert(!libinput_device_keyboard_has_key(dev->libinput_device, + KEY_F1)); + ck_assert(!libinput_device_keyboard_has_key(dev->libinput_device, + KEY_F2)); + ck_assert(!libinput_device_keyboard_has_key(dev->libinput_device, + KEY_F3)); + + /* Scrape the debug messages for confirmation that our quirks are + * triggered, the above checks cannot work non-key codes */ + message = debug_messages; + while (*message) { + if (strstr(*message, "disabling EV_KEY KEY_F1")) + disable_key_f1 = true; + if (strstr(*message, "enabling EV_KEY BTN_LEFT")) + enable_btn_left = true; +#if HAVE_LIBEVDEV_DISABLE_PROPERTY + if (strstr(*message, "enabling INPUT_PROP_BUTTONPAD")) + enable_buttonpad = true; + if (strstr(*message, "disabling INPUT_PROP_POINTING_STICK")) + disable_pointingstick = true; +#endif + free(*message); + message++; + } + + ck_assert(disable_key_f1); + ck_assert(enable_btn_left); +#if HAVE_LIBEVDEV_DISABLE_PROPERTY + ck_assert(enable_buttonpad); + ck_assert(disable_pointingstick); +#endif + + litest_disable_log_handler(li); + + litest_delete_device(dev); + litest_destroy_context(li); +} +END_TEST + START_TEST(device_capability_at_least_one) { struct litest_device *dev = litest_current_device(); @@ -1613,78 +1702,79 @@ struct range abs_range = { 0, ABS_MISC }; struct range abs_mt_range = { ABS_MT_SLOT + 1, ABS_CNT }; - litest_add("device:sendevents", device_sendevents_config, LITEST_ANY, LITEST_TOUCHPAD|LITEST_TABLET); - litest_add("device:sendevents", device_sendevents_config_invalid, LITEST_ANY, LITEST_TABLET); - litest_add("device:sendevents", device_sendevents_config_touchpad, LITEST_TOUCHPAD, LITEST_TABLET); - litest_add("device:sendevents", device_sendevents_config_touchpad_superset, LITEST_TOUCHPAD, LITEST_TABLET); - litest_add("device:sendevents", device_sendevents_config_default, LITEST_ANY, LITEST_TABLET); - litest_add("device:sendevents", device_disable, LITEST_RELATIVE, LITEST_TABLET); - litest_add("device:sendevents", device_disable_tablet, LITEST_TABLET, LITEST_ANY); - litest_add("device:sendevents", device_disable_touchpad, LITEST_TOUCHPAD, LITEST_TABLET); - litest_add("device:sendevents", device_disable_touch, LITEST_TOUCH, LITEST_ANY); - litest_add("device:sendevents", device_disable_touch_during_touch, LITEST_TOUCH, LITEST_ANY); - litest_add("device:sendevents", device_disable_touch, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD); - litest_add("device:sendevents", device_disable_touch_during_touch, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD); - litest_add("device:sendevents", device_disable_events_pending, LITEST_RELATIVE, LITEST_TOUCHPAD|LITEST_TABLET); - litest_add("device:sendevents", device_double_disable, LITEST_ANY, LITEST_TABLET); - litest_add("device:sendevents", device_double_enable, LITEST_ANY, LITEST_TABLET); - litest_add_no_device("device:sendevents", device_reenable_syspath_changed); - litest_add_no_device("device:sendevents", device_reenable_device_removed); - litest_add_for_device("device:sendevents", device_disable_release_buttons, LITEST_MOUSE); - litest_add_for_device("device:sendevents", device_disable_release_keys, LITEST_KEYBOARD); - litest_add("device:sendevents", device_disable_release_tap, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("device:sendevents", device_disable_release_tap_n_drag, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("device:sendevents", device_disable_release_softbutton, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); - litest_add("device:sendevents", device_disable_topsoftbutton, LITEST_TOPBUTTONPAD, LITEST_ANY); - litest_add("device:id", device_ids, LITEST_ANY, LITEST_ANY); - litest_add_for_device("device:context", device_context, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_for_device("device:context", device_user_data, LITEST_SYNAPTICS_CLICKPAD_X220); - - litest_add("device:udev", device_get_udev_handle, LITEST_ANY, LITEST_ANY); - - litest_add("device:group", device_group_get, LITEST_ANY, LITEST_ANY); - litest_add_no_device("device:group", device_group_ref); - litest_add_no_device("device:group", device_group_leak); - - litest_add_no_device("device:invalid devices", abs_device_no_absx); - litest_add_no_device("device:invalid devices", abs_device_no_absy); - litest_add_no_device("device:invalid devices", abs_mt_device_no_absx); - litest_add_no_device("device:invalid devices", abs_mt_device_no_absy); - litest_add_ranged_no_device("device:invalid devices", abs_device_no_range, &abs_range); - litest_add_ranged_no_device("device:invalid devices", abs_mt_device_no_range, &abs_mt_range); - litest_add_no_device("device:invalid devices", abs_device_missing_res); - litest_add_no_device("device:invalid devices", abs_mt_device_missing_res); - litest_add_no_device("device:invalid devices", ignore_joystick); - - litest_add("device:wheel", device_wheel_only, LITEST_WHEEL, LITEST_RELATIVE|LITEST_ABSOLUTE|LITEST_TABLET); - litest_add_no_device("device:accelerometer", device_accelerometer); - - litest_add("device:udev tags", device_udev_tag_wacom_tablet, LITEST_TABLET, LITEST_TOTEM); - - litest_add_no_device("device:invalid rel events", device_nonpointer_rel); - litest_add_no_device("device:invalid rel events", device_touchpad_rel); - litest_add_no_device("device:invalid rel events", device_touch_rel); - litest_add_no_device("device:invalid rel events", device_abs_rel); - - litest_add_for_device("device:quirks", device_quirks_no_abs_mt_y, LITEST_ANKER_MOUSE_KBD); - litest_add_for_device("device:quirks", device_quirks_cyborg_rat_mode_button, LITEST_CYBORG_RAT); - litest_add_for_device("device:quirks", device_quirks_apple_magicmouse, LITEST_MAGICMOUSE); - litest_add_for_device("device:quirks", device_quirks_logitech_marble_mouse, LITEST_LOGITECH_TRACKBALL); - - litest_add("device:capability", device_capability_at_least_one, LITEST_ANY, LITEST_ANY); - litest_add("device:capability", device_capability_check_invalid, LITEST_ANY, LITEST_ANY); - litest_add_no_device("device:capability", device_capability_nocaps_ignored); - - litest_add("device:size", device_has_size, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("device:size", device_has_size, LITEST_TABLET, LITEST_ANY); - litest_add("device:size", device_has_no_size, LITEST_ANY, + litest_add(device_sendevents_config, LITEST_ANY, LITEST_TOUCHPAD|LITEST_TABLET); + litest_add(device_sendevents_config_invalid, LITEST_ANY, LITEST_TABLET); + litest_add(device_sendevents_config_touchpad, LITEST_TOUCHPAD, LITEST_TABLET); + litest_add(device_sendevents_config_touchpad_superset, LITEST_TOUCHPAD, LITEST_TABLET); + litest_add(device_sendevents_config_default, LITEST_ANY, LITEST_TABLET); + litest_add(device_disable, LITEST_RELATIVE, LITEST_TABLET); + litest_add(device_disable_tablet, LITEST_TABLET, LITEST_ANY); + litest_add(device_disable_touchpad, LITEST_TOUCHPAD, LITEST_TABLET); + litest_add(device_disable_touch, LITEST_TOUCH, LITEST_ANY); + litest_add(device_disable_touch_during_touch, LITEST_TOUCH, LITEST_ANY); + litest_add(device_disable_touch, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD); + litest_add(device_disable_touch_during_touch, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD); + litest_add(device_disable_events_pending, LITEST_RELATIVE, LITEST_TOUCHPAD|LITEST_TABLET); + litest_add(device_double_disable, LITEST_ANY, LITEST_TABLET); + litest_add(device_double_enable, LITEST_ANY, LITEST_TABLET); + litest_add_no_device(device_reenable_syspath_changed); + litest_add_no_device(device_reenable_device_removed); + litest_add_for_device(device_disable_release_buttons, LITEST_MOUSE); + litest_add_for_device(device_disable_release_keys, LITEST_KEYBOARD); + litest_add(device_disable_release_tap, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(device_disable_release_tap_n_drag, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(device_disable_release_softbutton, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); + litest_add(device_disable_topsoftbutton, LITEST_TOPBUTTONPAD, LITEST_ANY); + litest_add(device_ids, LITEST_ANY, LITEST_ANY); + litest_add_for_device(device_context, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_for_device(device_user_data, LITEST_SYNAPTICS_CLICKPAD_X220); + + litest_add(device_get_udev_handle, LITEST_ANY, LITEST_ANY); + + litest_add(device_group_get, LITEST_ANY, LITEST_ANY); + litest_add_no_device(device_group_ref); + litest_add_no_device(device_group_leak); + + litest_add_no_device(abs_device_no_absx); + litest_add_no_device(abs_device_no_absy); + litest_add_no_device(abs_mt_device_no_absx); + litest_add_no_device(abs_mt_device_no_absy); + litest_add_ranged_no_device(abs_device_no_range, &abs_range); + litest_add_ranged_no_device(abs_mt_device_no_range, &abs_mt_range); + litest_add_no_device(abs_device_missing_res); + litest_add_no_device(abs_mt_device_missing_res); + litest_add_no_device(ignore_joystick); + + litest_add(device_wheel_only, LITEST_WHEEL, LITEST_RELATIVE|LITEST_ABSOLUTE|LITEST_TABLET); + litest_add_no_device(device_accelerometer); + + litest_add(device_udev_tag_wacom_tablet, LITEST_TABLET, LITEST_TOTEM); + + litest_add_no_device(device_nonpointer_rel); + litest_add_no_device(device_touchpad_rel); + litest_add_no_device(device_touch_rel); + litest_add_no_device(device_abs_rel); + + litest_add_for_device(device_quirks_no_abs_mt_y, LITEST_ANKER_MOUSE_KBD); + litest_add_for_device(device_quirks_cyborg_rat_mode_button, LITEST_CYBORG_RAT); + litest_add_for_device(device_quirks_apple_magicmouse, LITEST_MAGICMOUSE); + litest_add_for_device(device_quirks_logitech_marble_mouse, LITEST_LOGITECH_TRACKBALL); + litest_add_no_device(device_quirks); + + litest_add(device_capability_at_least_one, LITEST_ANY, LITEST_ANY); + litest_add(device_capability_check_invalid, LITEST_ANY, LITEST_ANY); + litest_add_no_device(device_capability_nocaps_ignored); + + litest_add(device_has_size, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(device_has_size, LITEST_TABLET, LITEST_ANY); + litest_add(device_has_no_size, LITEST_ANY, LITEST_TOUCHPAD|LITEST_TABLET|LITEST_TOUCH|LITEST_ABSOLUTE|LITEST_SINGLE_TOUCH|LITEST_TOTEM); - litest_add_for_device("device:output", device_get_output, LITEST_CALIBRATED_TOUCHSCREEN); - litest_add("device:output", device_no_output, LITEST_RELATIVE, LITEST_ANY); - litest_add("device:output", device_no_output, LITEST_KEYS, LITEST_ANY); + litest_add_for_device(device_get_output, LITEST_CALIBRATED_TOUCHSCREEN); + litest_add(device_no_output, LITEST_RELATIVE, LITEST_ANY); + litest_add(device_no_output, LITEST_KEYS, LITEST_ANY); - litest_add("device:seat", device_seat_phys_name, LITEST_ANY, LITEST_ANY); + litest_add(device_seat_phys_name, LITEST_ANY, LITEST_ANY); - litest_add("device:button", device_button_down_remove, LITEST_BUTTON, LITEST_ANY); + litest_add(device_button_down_remove, LITEST_BUTTON, LITEST_ANY); } diff -Nru libinput-1.16.4/test/test-gestures.c libinput-1.17.2/test/test-gestures.c --- libinput-1.16.4/test/test-gestures.c 2020-11-27 01:38:59.389086000 +0000 +++ libinput-1.17.2/test/test-gestures.c 2021-04-30 04:25:41.540076300 +0000 @@ -1066,21 +1066,21 @@ { struct range cardinals = { N, N + NCARDINALS }; - litest_add("gestures:cap", gestures_cap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("gestures:cap", gestures_nocap, LITEST_ANY, LITEST_TOUCHPAD); + litest_add(gestures_cap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(gestures_nocap, LITEST_ANY, LITEST_TOUCHPAD); - litest_add_ranged("gestures:swipe", gestures_swipe_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); - litest_add_ranged("gestures:swipe", gestures_swipe_3fg_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); - litest_add("gestures:swipe", gestures_swipe_3fg_btntool_pinch_like, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add_ranged("gestures:swipe", gestures_swipe_4fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); - litest_add_ranged("gestures:swipe", gestures_swipe_4fg_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); - litest_add_ranged("gestures:pinch", gestures_pinch, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); - litest_add_ranged("gestures:pinch", gestures_pinch_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); - litest_add_ranged("gestures:pinch", gestures_pinch_4fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); - litest_add_ranged("gestures:pinch", gestures_spread, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); + litest_add_ranged(gestures_swipe_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); + litest_add_ranged(gestures_swipe_3fg_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); + litest_add(gestures_swipe_3fg_btntool_pinch_like, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add_ranged(gestures_swipe_4fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); + litest_add_ranged(gestures_swipe_4fg_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); + litest_add_ranged(gestures_pinch, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); + litest_add_ranged(gestures_pinch_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); + litest_add_ranged(gestures_pinch_4fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); + litest_add_ranged(gestures_spread, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); - litest_add("gestures:swipe", gestures_3fg_buttonarea_scroll, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH); - litest_add("gestures:swipe", gestures_3fg_buttonarea_scroll_btntool, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH); + litest_add(gestures_3fg_buttonarea_scroll, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH); + litest_add(gestures_3fg_buttonarea_scroll_btntool, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH); - litest_add("gestures:time", gestures_time_usec, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(gestures_time_usec, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); } diff -Nru libinput-1.16.4/test/test-keyboard.c libinput-1.17.2/test/test-keyboard.c --- libinput-1.16.4/test/test-keyboard.c 2020-11-27 01:38:59.389086000 +0000 +++ libinput-1.17.2/test/test-keyboard.c 2021-04-30 04:25:41.540076300 +0000 @@ -478,17 +478,17 @@ TEST_COLLECTION(keyboard) { - litest_add_no_device("keyboard:seat key count", keyboard_seat_key_count); - litest_add_no_device("keyboard:key counting", keyboard_ignore_no_pressed_release); - litest_add_no_device("keyboard:key counting", keyboard_key_auto_release); - litest_add("keyboard:keys", keyboard_has_key, LITEST_KEYS, LITEST_ANY); - litest_add("keyboard:keys", keyboard_keys_bad_device, LITEST_ANY, LITEST_ANY); - litest_add("keyboard:time", keyboard_time_usec, LITEST_KEYS, LITEST_ANY); + litest_add_no_device(keyboard_seat_key_count); + litest_add_no_device(keyboard_ignore_no_pressed_release); + litest_add_no_device(keyboard_key_auto_release); + litest_add(keyboard_has_key, LITEST_KEYS, LITEST_ANY); + litest_add(keyboard_keys_bad_device, LITEST_ANY, LITEST_ANY); + litest_add(keyboard_time_usec, LITEST_KEYS, LITEST_ANY); - litest_add("keyboard:events", keyboard_no_buttons, LITEST_KEYS, LITEST_ANY); - litest_add("keyboard:events", keyboard_frame_order, LITEST_KEYS, LITEST_ANY); + litest_add(keyboard_no_buttons, LITEST_KEYS, LITEST_ANY); + litest_add(keyboard_frame_order, LITEST_KEYS, LITEST_ANY); - litest_add("keyboard:leds", keyboard_leds, LITEST_ANY, LITEST_ANY); + litest_add(keyboard_leds, LITEST_ANY, LITEST_ANY); - litest_add("keyboard:scroll", keyboard_no_scroll, LITEST_KEYS, LITEST_WHEEL); + litest_add(keyboard_no_scroll, LITEST_KEYS, LITEST_WHEEL); } diff -Nru libinput-1.16.4/test/test-log.c libinput-1.17.2/test/test-log.c --- libinput-1.16.4/test/test-log.c 2020-11-27 01:38:59.389086000 +0000 +++ libinput-1.17.2/test/test-log.c 2021-04-30 04:25:41.540076300 +0000 @@ -188,12 +188,12 @@ { struct range axes = { ABS_X, ABS_Y + 1}; - litest_add_deviceless("log:defaults", log_default_priority); - litest_add_deviceless("log:logging", log_handler_invoked); - litest_add_deviceless("log:logging", log_handler_NULL); - litest_add_no_device("log:logging", log_priority); + litest_add_deviceless(log_default_priority); + litest_add_deviceless(log_handler_invoked); + litest_add_deviceless(log_handler_NULL); + litest_add_no_device(log_priority); /* mtdev clips to axis ranges */ - litest_add_ranged("log:warnings", log_axisrange_warning, LITEST_TOUCH, LITEST_PROTOCOL_A, &axes); - litest_add_ranged("log:warnings", log_axisrange_warning, LITEST_TOUCHPAD, LITEST_ANY, &axes); + litest_add_ranged(log_axisrange_warning, LITEST_TOUCH, LITEST_PROTOCOL_A, &axes); + litest_add_ranged(log_axisrange_warning, LITEST_TOUCHPAD, LITEST_ANY, &axes); } diff -Nru libinput-1.16.4/test/test-misc.c libinput-1.17.2/test/test-misc.c --- libinput-1.16.4/test/test-misc.c 2020-11-27 01:38:59.390086200 +0000 +++ libinput-1.17.2/test/test-misc.c 2021-04-30 04:25:41.540076300 +0000 @@ -657,7 +657,8 @@ const char *format, va_list args) { - int *warning_triggered = (int*)libinput_get_user_data(libinput); + struct litest_user_data *user_data = libinput_get_user_data(libinput); + int *warning_triggered = user_data->private; if (priority == LIBINPUT_LOG_PRIORITY_ERROR && strstr(format, "scheduled expiry is in the past")) @@ -669,7 +670,7 @@ struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; int warning_triggered = 0; - void *old_user_data; + struct litest_user_data *user_data = libinput_get_user_data(li); litest_enable_tap(dev->libinput_device); litest_drain_events(li); @@ -679,16 +680,13 @@ litest_timeout_tap(); - old_user_data = libinput_get_user_data(li); - libinput_set_user_data(li, &warning_triggered); + user_data->private = &warning_triggered; libinput_log_set_handler(li, timer_offset_warning); libinput_dispatch(li); /* triggered for touch down and touch up */ ck_assert_int_eq(warning_triggered, 2); litest_restore_log_handler(li); - - libinput_set_user_data(li, old_user_data); } END_TEST @@ -697,39 +695,35 @@ const char *format, va_list args) { - int *warning_triggered = (int*)libinput_get_user_data(libinput); + struct litest_user_data *user_data = libinput_get_user_data(libinput); + int *warning_triggered = user_data->private; if (priority == LIBINPUT_LOG_PRIORITY_ERROR && strstr(format, "event processing lagging behind by")) (*warning_triggered)++; } - START_TEST(timer_delay_bug_warning) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; int warning_triggered = 0; - void *old_user_data; + struct litest_user_data *user_data = libinput_get_user_data(li); - old_user_data = libinput_get_user_data(li); litest_drain_events(li); - for (int i = 0; i < 10; i++) { - litest_button_click(dev, BTN_LEFT, true); - libinput_dispatch(li); - litest_button_click(dev, BTN_LEFT, false); - msleep(11); + user_data->private = &warning_triggered; + libinput_log_set_handler(li, timer_delay_warning); - libinput_set_user_data(li, &warning_triggered); - libinput_log_set_handler(li, timer_delay_warning); + for (int i = 0; i < 20; i++) { + litest_event(dev, EV_REL, REL_X, -1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + msleep(11); libinput_dispatch(li); } - ck_assert_int_ge(warning_triggered, 1); litest_restore_log_handler(li); - libinput_set_user_data(li, old_user_data); } END_TEST @@ -771,7 +765,7 @@ libinput_dispatch(li); litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY); - /* Ingore 'timer offset negative' warnings */ + /* Ignore 'timer offset negative' warnings */ litest_disable_log_handler(li); /* now mess with the timing @@ -886,25 +880,24 @@ TEST_COLLECTION(misc) { - litest_add_no_device("events:conversion", event_conversion_device_notify); - litest_add_for_device("events:conversion", event_conversion_pointer, LITEST_MOUSE); - litest_add_for_device("events:conversion", event_conversion_pointer, LITEST_MOUSE); - litest_add_for_device("events:conversion", event_conversion_pointer_abs, LITEST_XEN_VIRTUAL_POINTER); - litest_add_for_device("events:conversion", event_conversion_key, LITEST_KEYBOARD); - litest_add_for_device("events:conversion", event_conversion_touch, LITEST_WACOM_TOUCH); - litest_add_for_device("events:conversion", event_conversion_gesture, LITEST_BCM5974); - litest_add_for_device("events:conversion", event_conversion_tablet, LITEST_WACOM_CINTIQ); - litest_add_for_device("events:conversion", event_conversion_tablet_pad, LITEST_WACOM_INTUOS5_PAD); - litest_add_for_device("events:conversion", event_conversion_switch, LITEST_LID_SWITCH); - - litest_add_deviceless("context:refcount", context_ref_counting); - litest_add_deviceless("config:status string", config_status_string); - - litest_add_for_device("timer:offset-warning", timer_offset_bug_warning, LITEST_SYNAPTICS_TOUCHPAD); - litest_add_for_device("timer:delay-warning", timer_delay_bug_warning, LITEST_MOUSE); - litest_add_no_device("timer:flush", timer_flush); + litest_add_no_device(event_conversion_device_notify); + litest_add_for_device(event_conversion_pointer, LITEST_MOUSE); + litest_add_for_device(event_conversion_pointer_abs, LITEST_XEN_VIRTUAL_POINTER); + litest_add_for_device(event_conversion_key, LITEST_KEYBOARD); + litest_add_for_device(event_conversion_touch, LITEST_WACOM_TOUCH); + litest_add_for_device(event_conversion_gesture, LITEST_BCM5974); + litest_add_for_device(event_conversion_tablet, LITEST_WACOM_CINTIQ); + litest_add_for_device(event_conversion_tablet_pad, LITEST_WACOM_INTUOS5_PAD); + litest_add_for_device(event_conversion_switch, LITEST_LID_SWITCH); + + litest_add_deviceless(context_ref_counting); + litest_add_deviceless(config_status_string); + + litest_add_for_device(timer_offset_bug_warning, LITEST_SYNAPTICS_TOUCHPAD); + litest_add_for_device(timer_delay_bug_warning, LITEST_MOUSE); + litest_add_no_device(timer_flush); - litest_add_no_device("misc:fd", fd_no_event_leak); + litest_add_no_device(fd_no_event_leak); - litest_add_for_device("misc:system", udev_absinfo_override, LITEST_ABSINFO_OVERRIDE); + litest_add_for_device(udev_absinfo_override, LITEST_ABSINFO_OVERRIDE); } diff -Nru libinput-1.16.4/test/test-pad.c libinput-1.17.2/test/test-pad.c --- libinput-1.16.4/test/test-pad.c 2020-11-27 01:38:59.390086200 +0000 +++ libinput-1.17.2/test/test-pad.c 2021-04-30 04:25:41.540076300 +0000 @@ -176,7 +176,7 @@ START_TEST(pad_button_intuos) { -#if !HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE +#if !HAVE_LIBWACOM struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; unsigned int code; @@ -236,7 +236,7 @@ START_TEST(pad_button_bamboo) { -#if !HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE +#if !HAVE_LIBWACOM struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; unsigned int code; @@ -286,7 +286,7 @@ START_TEST(pad_button_libwacom) { -#if HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE +#if HAVE_LIBWACOM struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; WacomDeviceDatabase *db = NULL; @@ -984,38 +984,38 @@ TEST_COLLECTION(tablet_pad) { - litest_add("pad:cap", pad_cap, LITEST_TABLET_PAD, LITEST_ANY); - litest_add("pad:cap", pad_no_cap, LITEST_ANY, LITEST_TABLET_PAD); + litest_add(pad_cap, LITEST_TABLET_PAD, LITEST_ANY); + litest_add(pad_no_cap, LITEST_ANY, LITEST_TABLET_PAD); - litest_add("pad:time", pad_time, LITEST_TABLET_PAD, LITEST_ANY); + litest_add(pad_time, LITEST_TABLET_PAD, LITEST_ANY); - litest_add("pad:button", pad_num_buttons, LITEST_TABLET_PAD, LITEST_ANY); - litest_add("pad:button", pad_num_buttons_libwacom, LITEST_TABLET_PAD, LITEST_ANY); - litest_add("pad:button", pad_button_intuos, LITEST_TABLET_PAD, LITEST_ANY); - litest_add("pad:button", pad_button_bamboo, LITEST_TABLET_PAD, LITEST_ANY); - litest_add("pad:button", pad_button_libwacom, LITEST_TABLET_PAD, LITEST_ANY); - litest_add("pad:button", pad_button_mode_groups, LITEST_TABLET_PAD, LITEST_ANY); - - litest_add("pad:ring", pad_has_ring, LITEST_RING, LITEST_ANY); - litest_add("pad:ring", pad_ring, LITEST_RING, LITEST_ANY); - litest_add("pad:ring", pad_ring_finger_up, LITEST_RING, LITEST_ANY); - - litest_add("pad:strip", pad_has_strip, LITEST_STRIP, LITEST_ANY); - litest_add("pad:strip", pad_strip, LITEST_STRIP, LITEST_ANY); - litest_add("pad:strip", pad_strip_finger_up, LITEST_STRIP, LITEST_ANY); - - litest_add_for_device("pad:left_handed", pad_left_handed_default, LITEST_WACOM_INTUOS5_PAD); - litest_add_for_device("pad:left_handed", pad_no_left_handed, LITEST_WACOM_INTUOS3_PAD); - litest_add_for_device("pad:left_handed", pad_left_handed_ring, LITEST_WACOM_INTUOS5_PAD); + litest_add(pad_num_buttons, LITEST_TABLET_PAD, LITEST_ANY); + litest_add(pad_num_buttons_libwacom, LITEST_TABLET_PAD, LITEST_ANY); + litest_add(pad_button_intuos, LITEST_TABLET_PAD, LITEST_ANY); + litest_add(pad_button_bamboo, LITEST_TABLET_PAD, LITEST_ANY); + litest_add(pad_button_libwacom, LITEST_TABLET_PAD, LITEST_ANY); + litest_add(pad_button_mode_groups, LITEST_TABLET_PAD, LITEST_ANY); + + litest_add(pad_has_ring, LITEST_RING, LITEST_ANY); + litest_add(pad_ring, LITEST_RING, LITEST_ANY); + litest_add(pad_ring_finger_up, LITEST_RING, LITEST_ANY); + + litest_add(pad_has_strip, LITEST_STRIP, LITEST_ANY); + litest_add(pad_strip, LITEST_STRIP, LITEST_ANY); + litest_add(pad_strip_finger_up, LITEST_STRIP, LITEST_ANY); + + litest_add_for_device(pad_left_handed_default, LITEST_WACOM_INTUOS5_PAD); + litest_add_for_device(pad_no_left_handed, LITEST_WACOM_INTUOS3_PAD); + litest_add_for_device(pad_left_handed_ring, LITEST_WACOM_INTUOS5_PAD); /* None of the current strip tablets are left-handed */ - litest_add("pad:modes", pad_mode_groups, LITEST_TABLET_PAD, LITEST_ANY); - litest_add("pad:modes", pad_mode_groups_userdata, LITEST_TABLET_PAD, LITEST_ANY); - litest_add("pad:modes", pad_mode_groups_ref, LITEST_TABLET_PAD, LITEST_ANY); - litest_add("pad:modes", pad_mode_group_mode, LITEST_TABLET_PAD, LITEST_ANY); - litest_add("pad:modes", pad_mode_group_has, LITEST_TABLET_PAD, LITEST_ANY); - litest_add("pad:modes", pad_mode_group_has_invalid, LITEST_TABLET_PAD, LITEST_ANY); - litest_add("pad:modes", pad_mode_group_has_no_toggle, LITEST_TABLET_PAD, LITEST_ANY); + litest_add(pad_mode_groups, LITEST_TABLET_PAD, LITEST_ANY); + litest_add(pad_mode_groups_userdata, LITEST_TABLET_PAD, LITEST_ANY); + litest_add(pad_mode_groups_ref, LITEST_TABLET_PAD, LITEST_ANY); + litest_add(pad_mode_group_mode, LITEST_TABLET_PAD, LITEST_ANY); + litest_add(pad_mode_group_has, LITEST_TABLET_PAD, LITEST_ANY); + litest_add(pad_mode_group_has_invalid, LITEST_TABLET_PAD, LITEST_ANY); + litest_add(pad_mode_group_has_no_toggle, LITEST_TABLET_PAD, LITEST_ANY); - litest_add("pad:keys", pad_keys, LITEST_TABLET_PAD, LITEST_ANY); + litest_add(pad_keys, LITEST_TABLET_PAD, LITEST_ANY); } diff -Nru libinput-1.16.4/test/test-path.c libinput-1.17.2/test/test-path.c --- libinput-1.16.4/test/test-path.c 2020-11-27 01:38:59.390086200 +0000 +++ libinput-1.17.2/test/test-path.c 2021-04-30 04:25:41.540076300 +0000 @@ -1014,30 +1014,30 @@ TEST_COLLECTION(path) { - litest_add_no_device("path:create", path_create_NULL); - litest_add_no_device("path:create", path_create_invalid); - litest_add_no_device("path:create", path_create_invalid_file); - litest_add_no_device("path:create", path_create_invalid_kerneldev); - litest_add_no_device("path:create", path_create_pathmax_file); - litest_add_no_device("path:create", path_create_destroy); - litest_add("path:create", path_force_destroy, LITEST_ANY, LITEST_ANY); - litest_add_no_device("path:create", path_set_user_data); - litest_add_no_device("path:suspend", path_suspend); - litest_add_no_device("path:suspend", path_double_suspend); - litest_add_no_device("path:suspend", path_double_resume); - litest_add_no_device("path:suspend", path_add_device_suspend_resume); - litest_add_no_device("path:suspend", path_add_device_suspend_resume_fail); - litest_add_no_device("path:suspend", path_add_device_suspend_resume_remove_device); - litest_add_for_device("path:seat", path_added_seat, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_for_device("path:seat", path_seat_change, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add("path:device events", path_added_device, LITEST_ANY, LITEST_ANY); - litest_add("path:device events", path_device_sysname, LITEST_ANY, LITEST_ANY); - litest_add_for_device("path:device events", path_add_device, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_no_device("path:device events", path_add_invalid_path); - litest_add_for_device("path:device events", path_remove_device, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_for_device("path:device events", path_double_remove_device, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_no_device("path:seat", path_seat_recycle); - litest_add_for_device("path:udev", path_udev_assign_seat, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_no_device(path_create_NULL); + litest_add_no_device(path_create_invalid); + litest_add_no_device(path_create_invalid_file); + litest_add_no_device(path_create_invalid_kerneldev); + litest_add_no_device(path_create_pathmax_file); + litest_add_no_device(path_create_destroy); + litest_add(path_force_destroy, LITEST_ANY, LITEST_ANY); + litest_add_no_device(path_set_user_data); + litest_add_no_device(path_suspend); + litest_add_no_device(path_double_suspend); + litest_add_no_device(path_double_resume); + litest_add_no_device(path_add_device_suspend_resume); + litest_add_no_device(path_add_device_suspend_resume_fail); + litest_add_no_device(path_add_device_suspend_resume_remove_device); + litest_add_for_device(path_added_seat, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_for_device(path_seat_change, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add(path_added_device, LITEST_ANY, LITEST_ANY); + litest_add(path_device_sysname, LITEST_ANY, LITEST_ANY); + litest_add_for_device(path_add_device, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_no_device(path_add_invalid_path); + litest_add_for_device(path_remove_device, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_for_device(path_double_remove_device, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_no_device(path_seat_recycle); + litest_add_for_device(path_udev_assign_seat, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_no_device("path:ignore", path_ignore_device); + litest_add_no_device(path_ignore_device); } diff -Nru libinput-1.16.4/test/test-pointer.c libinput-1.17.2/test/test-pointer.c --- libinput-1.16.4/test/test-pointer.c 2020-11-27 01:38:59.391086000 +0000 +++ libinput-1.17.2/test/test-pointer.c 2021-04-30 04:25:41.541076400 +0000 @@ -3130,88 +3130,88 @@ struct range buttons = {BTN_LEFT, BTN_TASK + 1}; struct range buttonorder = {0, _MB_BUTTONORDER_COUNT}; - litest_add("pointer:motion", pointer_motion_relative, LITEST_RELATIVE, LITEST_POINTINGSTICK); - litest_add_for_device("pointer:motion", pointer_motion_relative_zero, LITEST_MOUSE); - litest_add_ranged("pointer:motion", pointer_motion_relative_min_decel, LITEST_RELATIVE, LITEST_POINTINGSTICK, &compass); - litest_add("pointer:motion", pointer_motion_absolute, LITEST_ABSOLUTE, LITEST_ANY); - litest_add("pointer:motion", pointer_motion_unaccel, LITEST_RELATIVE, LITEST_ANY); - litest_add("pointer:button", pointer_button, LITEST_BUTTON, LITEST_CLICKPAD); - litest_add_no_device("pointer:button", pointer_button_auto_release); - litest_add_no_device("pointer:button", pointer_seat_button_count); - litest_add_for_device("pointer:button", pointer_button_has_no_button, LITEST_KEYBOARD); - litest_add("pointer:button", pointer_recover_from_lost_button_count, LITEST_BUTTON, LITEST_CLICKPAD); - litest_add("pointer:scroll", pointer_scroll_wheel, LITEST_WHEEL, LITEST_TABLET); - litest_add("pointer:scroll", pointer_scroll_button, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); - litest_add("pointer:scroll", pointer_scroll_button_noscroll, LITEST_ABSOLUTE|LITEST_BUTTON, LITEST_RELATIVE); - litest_add("pointer:scroll", pointer_scroll_button_noscroll, LITEST_ANY, LITEST_RELATIVE|LITEST_BUTTON); - litest_add("pointer:scroll", pointer_scroll_button_no_event_before_timeout, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); - litest_add("pointer:scroll", pointer_scroll_button_middle_emulation, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); - litest_add("pointer:scroll", pointer_scroll_button_device_remove_while_down, LITEST_ANY, LITEST_RELATIVE|LITEST_BUTTON); - - litest_add("pointer:scroll", pointer_scroll_button_lock, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); - litest_add("pointer:scroll", pointer_scroll_button_lock_defaults, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); - litest_add("pointer:scroll", pointer_scroll_button_lock_config, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); - litest_add("pointer:scroll", pointer_scroll_button_lock_enable_while_down, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); - litest_add("pointer:scroll", pointer_scroll_button_lock_enable_while_down_just_lock, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); - litest_add("pointer:scroll", pointer_scroll_button_lock_otherbutton, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); - litest_add("pointer:scroll", pointer_scroll_button_lock_enable_while_otherbutton_down, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); - litest_add_ranged("pointer:scroll", pointer_scroll_button_lock_middlebutton, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY, &buttonorder); - litest_add("pointer:scroll", pointer_scroll_button_lock_doubleclick_nomove, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); - - litest_add("pointer:scroll", pointer_scroll_nowheel_defaults, LITEST_RELATIVE|LITEST_BUTTON, LITEST_WHEEL); - litest_add_for_device("pointer:scroll", pointer_scroll_defaults_logitech_marble , LITEST_LOGITECH_TRACKBALL); - litest_add("pointer:scroll", pointer_scroll_natural_defaults, LITEST_WHEEL, LITEST_TABLET); - litest_add("pointer:scroll", pointer_scroll_natural_defaults_noscroll, LITEST_ANY, LITEST_WHEEL); - litest_add("pointer:scroll", pointer_scroll_natural_enable_config, LITEST_WHEEL, LITEST_TABLET); - litest_add("pointer:scroll", pointer_scroll_natural_wheel, LITEST_WHEEL, LITEST_TABLET); - litest_add("pointer:scroll", pointer_scroll_has_axis_invalid, LITEST_WHEEL, LITEST_TABLET); + litest_add(pointer_motion_relative, LITEST_RELATIVE, LITEST_POINTINGSTICK); + litest_add_for_device(pointer_motion_relative_zero, LITEST_MOUSE); + litest_add_ranged(pointer_motion_relative_min_decel, LITEST_RELATIVE, LITEST_POINTINGSTICK, &compass); + litest_add(pointer_motion_absolute, LITEST_ABSOLUTE, LITEST_ANY); + litest_add(pointer_motion_unaccel, LITEST_RELATIVE, LITEST_ANY); + litest_add(pointer_button, LITEST_BUTTON, LITEST_CLICKPAD); + litest_add_no_device(pointer_button_auto_release); + litest_add_no_device(pointer_seat_button_count); + litest_add_for_device(pointer_button_has_no_button, LITEST_KEYBOARD); + litest_add(pointer_recover_from_lost_button_count, LITEST_BUTTON, LITEST_CLICKPAD); + litest_add(pointer_scroll_wheel, LITEST_WHEEL, LITEST_TABLET); + litest_add(pointer_scroll_button, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); + litest_add(pointer_scroll_button_noscroll, LITEST_ABSOLUTE|LITEST_BUTTON, LITEST_RELATIVE); + litest_add(pointer_scroll_button_noscroll, LITEST_ANY, LITEST_RELATIVE|LITEST_BUTTON); + litest_add(pointer_scroll_button_no_event_before_timeout, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); + litest_add(pointer_scroll_button_middle_emulation, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); + litest_add(pointer_scroll_button_device_remove_while_down, LITEST_ANY, LITEST_RELATIVE|LITEST_BUTTON); + + litest_add(pointer_scroll_button_lock, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); + litest_add(pointer_scroll_button_lock_defaults, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); + litest_add(pointer_scroll_button_lock_config, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); + litest_add(pointer_scroll_button_lock_enable_while_down, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); + litest_add(pointer_scroll_button_lock_enable_while_down_just_lock, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); + litest_add(pointer_scroll_button_lock_otherbutton, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); + litest_add(pointer_scroll_button_lock_enable_while_otherbutton_down, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); + litest_add_ranged(pointer_scroll_button_lock_middlebutton, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY, &buttonorder); + litest_add(pointer_scroll_button_lock_doubleclick_nomove, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); + + litest_add(pointer_scroll_nowheel_defaults, LITEST_RELATIVE|LITEST_BUTTON, LITEST_WHEEL); + litest_add_for_device(pointer_scroll_defaults_logitech_marble , LITEST_LOGITECH_TRACKBALL); + litest_add(pointer_scroll_natural_defaults, LITEST_WHEEL, LITEST_TABLET); + litest_add(pointer_scroll_natural_defaults_noscroll, LITEST_ANY, LITEST_WHEEL); + litest_add(pointer_scroll_natural_enable_config, LITEST_WHEEL, LITEST_TABLET); + litest_add(pointer_scroll_natural_wheel, LITEST_WHEEL, LITEST_TABLET); + litest_add(pointer_scroll_has_axis_invalid, LITEST_WHEEL, LITEST_TABLET); - litest_add("pointer:calibration", pointer_no_calibration, LITEST_ANY, LITEST_TOUCH|LITEST_SINGLE_TOUCH|LITEST_ABSOLUTE|LITEST_PROTOCOL_A|LITEST_TABLET); + litest_add(pointer_no_calibration, LITEST_ANY, LITEST_TOUCH|LITEST_SINGLE_TOUCH|LITEST_ABSOLUTE|LITEST_PROTOCOL_A|LITEST_TABLET); /* tests touchpads too */ - litest_add("pointer:left-handed", pointer_left_handed_defaults, LITEST_BUTTON, LITEST_ANY); - litest_add("pointer:left-handed", pointer_left_handed, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); - litest_add("pointer:left-handed", pointer_left_handed_during_click, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); - litest_add("pointer:left-handed", pointer_left_handed_during_click_multiple_buttons, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); - - litest_add("pointer:accel", pointer_accel_defaults, LITEST_RELATIVE, LITEST_ANY); - litest_add("pointer:accel", pointer_accel_invalid, LITEST_RELATIVE, LITEST_ANY); - litest_add("pointer:accel", pointer_accel_defaults_absolute, LITEST_ABSOLUTE, LITEST_RELATIVE); - litest_add("pointer:accel", pointer_accel_defaults_absolute_relative, LITEST_ABSOLUTE|LITEST_RELATIVE, LITEST_ANY); - litest_add("pointer:accel", pointer_accel_direction_change, LITEST_RELATIVE, LITEST_POINTINGSTICK); - litest_add("pointer:accel", pointer_accel_profile_defaults, LITEST_RELATIVE, LITEST_TOUCHPAD); - litest_add("pointer:accel", pointer_accel_profile_defaults, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("pointer:accel", pointer_accel_profile_invalid, LITEST_RELATIVE, LITEST_ANY); - litest_add("pointer:accel", pointer_accel_profile_noaccel, LITEST_ANY, LITEST_TOUCHPAD|LITEST_RELATIVE|LITEST_TABLET); - litest_add("pointer:accel", pointer_accel_profile_flat_motion_relative, LITEST_RELATIVE, LITEST_TOUCHPAD); - - litest_add("pointer:middlebutton", middlebutton, LITEST_BUTTON, LITEST_CLICKPAD); - litest_add("pointer:middlebutton", middlebutton_nostart_while_down, LITEST_BUTTON, LITEST_CLICKPAD); - litest_add("pointer:middlebutton", middlebutton_timeout, LITEST_BUTTON, LITEST_CLICKPAD); - litest_add("pointer:middlebutton", middlebutton_doubleclick, LITEST_BUTTON, LITEST_CLICKPAD); - litest_add("pointer:middlebutton", middlebutton_middleclick, LITEST_BUTTON, LITEST_CLICKPAD); - litest_add("pointer:middlebutton", middlebutton_middleclick_during, LITEST_BUTTON, LITEST_CLICKPAD); - litest_add("pointer:middlebutton", middlebutton_default_enabled, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_POINTINGSTICK); - litest_add("pointer:middlebutton", middlebutton_default_clickpad, LITEST_CLICKPAD, LITEST_ANY); - litest_add("pointer:middlebutton", middlebutton_default_touchpad, LITEST_TOUCHPAD, LITEST_CLICKPAD); - litest_add("pointer:middlebutton", middlebutton_default_disabled, LITEST_ANY, LITEST_BUTTON); - litest_add_for_device("pointer:middlebutton", middlebutton_default_alps, LITEST_ALPS_SEMI_MT); - litest_add("pointer:middlebutton", middlebutton_button_scrolling, LITEST_RELATIVE|LITEST_BUTTON, LITEST_CLICKPAD); - litest_add("pointer:middlebutton", middlebutton_button_scrolling_middle, LITEST_RELATIVE|LITEST_BUTTON, LITEST_CLICKPAD); - litest_add("pointer:middlebutton", middlebutton_device_remove_while_down, LITEST_BUTTON, LITEST_CLICKPAD); - litest_add("pointer:middlebutton", middlebutton_device_remove_while_one_is_down, LITEST_BUTTON, LITEST_CLICKPAD); - - litest_add_ranged("pointer:state", pointer_absolute_initial_state, LITEST_ABSOLUTE, LITEST_ANY, &axis_range); - - litest_add("pointer:time", pointer_time_usec, LITEST_RELATIVE, LITEST_ANY); - - litest_add_ranged("pointer:debounce", debounce_bounce, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE, &buttons); - litest_add("pointer:debounce", debounce_bounce_check_immediate, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE); - litest_add_ranged("pointer:debounce", debounce_spurious, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE, &buttons); - litest_add("pointer:debounce", debounce_spurious_multibounce, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE); - litest_add("pointer:debounce_otherbutton", debounce_spurious_dont_enable_on_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE); - litest_add("pointer:debounce_otherbutton", debounce_spurious_cancel_debounce_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE); - litest_add("pointer:debounce_otherbutton", debounce_spurious_switch_to_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE); - litest_add_no_device("pointer:debounce", debounce_remove_device_button_down); - litest_add_no_device("pointer:debounce", debounce_remove_device_button_up); + litest_add(pointer_left_handed_defaults, LITEST_BUTTON, LITEST_ANY); + litest_add(pointer_left_handed, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); + litest_add(pointer_left_handed_during_click, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); + litest_add(pointer_left_handed_during_click_multiple_buttons, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY); + + litest_add(pointer_accel_defaults, LITEST_RELATIVE, LITEST_ANY); + litest_add(pointer_accel_invalid, LITEST_RELATIVE, LITEST_ANY); + litest_add(pointer_accel_defaults_absolute, LITEST_ABSOLUTE, LITEST_RELATIVE); + litest_add(pointer_accel_defaults_absolute_relative, LITEST_ABSOLUTE|LITEST_RELATIVE, LITEST_ANY); + litest_add(pointer_accel_direction_change, LITEST_RELATIVE, LITEST_POINTINGSTICK); + litest_add(pointer_accel_profile_defaults, LITEST_RELATIVE, LITEST_TOUCHPAD); + litest_add(pointer_accel_profile_defaults, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(pointer_accel_profile_invalid, LITEST_RELATIVE, LITEST_ANY); + litest_add(pointer_accel_profile_noaccel, LITEST_ANY, LITEST_TOUCHPAD|LITEST_RELATIVE|LITEST_TABLET); + litest_add(pointer_accel_profile_flat_motion_relative, LITEST_RELATIVE, LITEST_TOUCHPAD); + + litest_add(middlebutton, LITEST_BUTTON, LITEST_CLICKPAD); + litest_add(middlebutton_nostart_while_down, LITEST_BUTTON, LITEST_CLICKPAD); + litest_add(middlebutton_timeout, LITEST_BUTTON, LITEST_CLICKPAD); + litest_add(middlebutton_doubleclick, LITEST_BUTTON, LITEST_CLICKPAD); + litest_add(middlebutton_middleclick, LITEST_BUTTON, LITEST_CLICKPAD); + litest_add(middlebutton_middleclick_during, LITEST_BUTTON, LITEST_CLICKPAD); + litest_add(middlebutton_default_enabled, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_POINTINGSTICK); + litest_add(middlebutton_default_clickpad, LITEST_CLICKPAD, LITEST_ANY); + litest_add(middlebutton_default_touchpad, LITEST_TOUCHPAD, LITEST_CLICKPAD); + litest_add(middlebutton_default_disabled, LITEST_ANY, LITEST_BUTTON); + litest_add_for_device(middlebutton_default_alps, LITEST_ALPS_SEMI_MT); + litest_add(middlebutton_button_scrolling, LITEST_RELATIVE|LITEST_BUTTON, LITEST_CLICKPAD); + litest_add(middlebutton_button_scrolling_middle, LITEST_RELATIVE|LITEST_BUTTON, LITEST_CLICKPAD); + litest_add(middlebutton_device_remove_while_down, LITEST_BUTTON, LITEST_CLICKPAD); + litest_add(middlebutton_device_remove_while_one_is_down, LITEST_BUTTON, LITEST_CLICKPAD); + + litest_add_ranged(pointer_absolute_initial_state, LITEST_ABSOLUTE, LITEST_ANY, &axis_range); + + litest_add(pointer_time_usec, LITEST_RELATIVE, LITEST_ANY); + + litest_add_ranged(debounce_bounce, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE, &buttons); + litest_add(debounce_bounce_check_immediate, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE); + litest_add_ranged(debounce_spurious, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE, &buttons); + litest_add(debounce_spurious_multibounce, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE); + litest_add(debounce_spurious_dont_enable_on_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE); + litest_add(debounce_spurious_cancel_debounce_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE); + litest_add(debounce_spurious_switch_to_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE); + litest_add_no_device(debounce_remove_device_button_down); + litest_add_no_device(debounce_remove_device_button_up); } diff -Nru libinput-1.16.4/test/test-quirks.c libinput-1.17.2/test/test-quirks.c --- libinput-1.16.4/test/test-quirks.c 2020-11-27 01:38:59.391086000 +0000 +++ libinput-1.17.2/test/test-quirks.c 2021-04-30 04:25:41.541076400 +0000 @@ -1305,6 +1305,54 @@ } END_TEST +START_TEST(quirks_model_override) +{ + struct litest_device *dev = litest_current_device(); + struct udev_device *ud = libinput_device_get_udev_device(dev->libinput_device); + struct quirks_context *ctx; + char *quirks_file; + struct data_dir dd; + struct quirks *q; + bool isset; + bool set = _i; /* ranged test */ + + /* Test model quirks override by setting, then unsetting (or the + other way round) */ + int rc = xasprintf(&quirks_file, + "[first]\n" + "MatchUdevType=mouse\n" + "ModelAppleTouchpad=%d\n" + "\n" + "[second]\n" + "MatchUdevType=mouse\n" + "ModelAppleTouchpad=%d\n", + set ? 0 : 1, + set ? 1 : 0); + ck_assert_int_ne(rc, -1); + + dd = make_data_dir(quirks_file); + + ctx = quirks_init_subsystem(dd.dirname, + NULL, + log_handler, + NULL, + QLOG_CUSTOM_LOG_PRIORITIES); + ck_assert_notnull(ctx); + + q = quirks_fetch_for_device(ctx, ud); + ck_assert_notnull(q); + + ck_assert(quirks_get_bool(q, QUIRK_MODEL_APPLE_TOUCHPAD, &isset)); + ck_assert(isset == set); + + quirks_unref(q); + quirks_context_unref(ctx); + cleanup_data_dir(dd); + udev_device_unref(ud); + free(quirks_file); +} +END_TEST + START_TEST(quirks_model_alps) { struct litest_device *dev = litest_current_device(); @@ -1424,59 +1472,62 @@ TEST_COLLECTION(quirks) { - litest_add_deviceless("quirks:datadir", quirks_invalid_dir); - litest_add_deviceless("quirks:datadir", quirks_empty_dir); + struct range boolean = {0, 2}; + + litest_add_deviceless(quirks_invalid_dir); + litest_add_deviceless(quirks_empty_dir); - litest_add_deviceless("quirks:structure", quirks_section_empty); - litest_add_deviceless("quirks:structure", quirks_section_double); - litest_add_deviceless("quirks:structure", quirks_section_missing_match); - litest_add_deviceless("quirks:structure", quirks_section_missing_attr); - litest_add_deviceless("quirks:structure", quirks_section_match_after_attr); - litest_add_deviceless("quirks:structure", quirks_section_duplicate_match); - litest_add_deviceless("quirks:structure", quirks_section_duplicate_attr); - - litest_add_deviceless("quirks:parsing", quirks_parse_error_section); - litest_add_deviceless("quirks:parsing", quirks_parse_error_trailing_whitespace); - litest_add_deviceless("quirks:parsing", quirks_parse_error_unknown_match); - litest_add_deviceless("quirks:parsing", quirks_parse_error_unknown_attr); - litest_add_deviceless("quirks:parsing", quirks_parse_error_unknown_model); - litest_add_deviceless("quirks:parsing", quirks_parse_error_unknown_prefix); - litest_add_deviceless("quirks:parsing", quirks_parse_error_model_not_one); - litest_add_deviceless("quirks:parsing", quirks_parse_comment_inline); - litest_add_deviceless("quirks:parsing", quirks_parse_comment_empty); - litest_add_deviceless("quirks:parsing", quirks_parse_string_quotes_single); - litest_add_deviceless("quirks:parsing", quirks_parse_string_quotes_double); - - litest_add_deviceless("quirks:parsing", quirks_parse_bustype); - litest_add_deviceless("quirks:parsing", quirks_parse_bustype_invalid); - litest_add_deviceless("quirks:parsing", quirks_parse_vendor); - litest_add_deviceless("quirks:parsing", quirks_parse_vendor_invalid); - litest_add_deviceless("quirks:parsing", quirks_parse_product); - litest_add_deviceless("quirks:parsing", quirks_parse_product_invalid); - litest_add_deviceless("quirks:parsing", quirks_parse_version); - litest_add_deviceless("quirks:parsing", quirks_parse_version_invalid); - litest_add_deviceless("quirks:parsing", quirks_parse_name); - litest_add_deviceless("quirks:parsing", quirks_parse_name_invalid); - litest_add_deviceless("quirks:parsing", quirks_parse_udev); - litest_add_deviceless("quirks:parsing", quirks_parse_udev_invalid); - litest_add_deviceless("quirks:parsing", quirks_parse_dmi); - litest_add_deviceless("quirks:parsing", quirks_parse_dmi_invalid); - - litest_add_for_device("quirks:parsing", quirks_parse_dimension_attr, LITEST_MOUSE); - litest_add_for_device("quirks:parsing", quirks_parse_range_attr, LITEST_MOUSE); - litest_add_for_device("quirks:parsing", quirks_parse_uint_attr, LITEST_MOUSE); - litest_add_for_device("quirks:parsing", quirks_parse_double_attr, LITEST_MOUSE); - litest_add_for_device("quirks:parsing", quirks_parse_string_attr, LITEST_MOUSE); - litest_add_for_device("quirks:parsing", quirks_parse_integration_attr, LITEST_MOUSE); - - litest_add_for_device("quirks:model", quirks_model_one, LITEST_MOUSE); - litest_add_for_device("quirks:model", quirks_model_zero, LITEST_MOUSE); - - litest_add("quirks:devices", quirks_model_alps, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("quirks:devices", quirks_model_wacom, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("quirks:devices", quirks_model_apple, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("quirks:devices", quirks_model_synaptics_serial, LITEST_TOUCHPAD, LITEST_ANY); + litest_add_deviceless(quirks_section_empty); + litest_add_deviceless(quirks_section_double); + litest_add_deviceless(quirks_section_missing_match); + litest_add_deviceless(quirks_section_missing_attr); + litest_add_deviceless(quirks_section_match_after_attr); + litest_add_deviceless(quirks_section_duplicate_match); + litest_add_deviceless(quirks_section_duplicate_attr); + + litest_add_deviceless(quirks_parse_error_section); + litest_add_deviceless(quirks_parse_error_trailing_whitespace); + litest_add_deviceless(quirks_parse_error_unknown_match); + litest_add_deviceless(quirks_parse_error_unknown_attr); + litest_add_deviceless(quirks_parse_error_unknown_model); + litest_add_deviceless(quirks_parse_error_unknown_prefix); + litest_add_deviceless(quirks_parse_error_model_not_one); + litest_add_deviceless(quirks_parse_comment_inline); + litest_add_deviceless(quirks_parse_comment_empty); + litest_add_deviceless(quirks_parse_string_quotes_single); + litest_add_deviceless(quirks_parse_string_quotes_double); + + litest_add_deviceless(quirks_parse_bustype); + litest_add_deviceless(quirks_parse_bustype_invalid); + litest_add_deviceless(quirks_parse_vendor); + litest_add_deviceless(quirks_parse_vendor_invalid); + litest_add_deviceless(quirks_parse_product); + litest_add_deviceless(quirks_parse_product_invalid); + litest_add_deviceless(quirks_parse_version); + litest_add_deviceless(quirks_parse_version_invalid); + litest_add_deviceless(quirks_parse_name); + litest_add_deviceless(quirks_parse_name_invalid); + litest_add_deviceless(quirks_parse_udev); + litest_add_deviceless(quirks_parse_udev_invalid); + litest_add_deviceless(quirks_parse_dmi); + litest_add_deviceless(quirks_parse_dmi_invalid); + + litest_add_for_device(quirks_parse_dimension_attr, LITEST_MOUSE); + litest_add_for_device(quirks_parse_range_attr, LITEST_MOUSE); + litest_add_for_device(quirks_parse_uint_attr, LITEST_MOUSE); + litest_add_for_device(quirks_parse_double_attr, LITEST_MOUSE); + litest_add_for_device(quirks_parse_string_attr, LITEST_MOUSE); + litest_add_for_device(quirks_parse_integration_attr, LITEST_MOUSE); + + litest_add_for_device(quirks_model_one, LITEST_MOUSE); + litest_add_for_device(quirks_model_zero, LITEST_MOUSE); + litest_add_ranged_for_device(quirks_model_override, LITEST_MOUSE, &boolean); + + litest_add(quirks_model_alps, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(quirks_model_wacom, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(quirks_model_apple, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(quirks_model_synaptics_serial, LITEST_TOUCHPAD, LITEST_ANY); - litest_add_deviceless("quirks:misc", quirks_call_NULL); - litest_add_deviceless("quirks:misc", quirks_ctx_ref); + litest_add_deviceless(quirks_call_NULL); + litest_add_deviceless(quirks_ctx_ref); } diff -Nru libinput-1.16.4/test/test-switch.c libinput-1.17.2/test/test-switch.c --- libinput-1.16.4/test/test-switch.c 2020-11-27 01:38:59.392086000 +0000 +++ libinput-1.17.2/test/test-switch.c 2021-04-30 04:25:41.541076400 +0000 @@ -1370,40 +1370,40 @@ struct range switches = { LIBINPUT_SWITCH_LID, LIBINPUT_SWITCH_TABLET_MODE + 1}; - litest_add("switch:has", switch_has_cap, LITEST_SWITCH, LITEST_ANY); - litest_add("switch:has", switch_has_lid_switch, LITEST_SWITCH, LITEST_ANY); - litest_add("switch:has", switch_has_tablet_mode_switch, LITEST_SWITCH, LITEST_ANY); - litest_add_ranged("switch:toggle", switch_toggle, LITEST_SWITCH, LITEST_ANY, &switches); - litest_add_ranged("switch:toggle", switch_toggle_double, LITEST_SWITCH, LITEST_ANY, &switches); - litest_add_ranged("switch:toggle", switch_down_on_init, LITEST_SWITCH, LITEST_ANY, &switches); - litest_add("switch:toggle", switch_not_down_on_init, LITEST_SWITCH, LITEST_ANY); - litest_add_ranged("switch:touchpad", switch_disable_touchpad, LITEST_SWITCH, LITEST_ANY, &switches); - litest_add_ranged("switch:touchpad", switch_disable_touchpad_during_touch, LITEST_SWITCH, LITEST_ANY, &switches); - litest_add_ranged("switch:touchpad", switch_disable_touchpad_edge_scroll, LITEST_SWITCH, LITEST_ANY, &switches); - litest_add_ranged("switch:touchpad", switch_disable_touchpad_edge_scroll_interrupt, LITEST_SWITCH, LITEST_ANY, &switches); - litest_add_ranged("switch:touchpad", switch_disable_touchpad_already_open, LITEST_SWITCH, LITEST_ANY, &switches); - litest_add_ranged("switch:touchpad", switch_dont_resume_disabled_touchpad, LITEST_SWITCH, LITEST_ANY, &switches); - litest_add_ranged("switch:touchpad", switch_dont_resume_disabled_touchpad_external_mouse, LITEST_SWITCH, LITEST_ANY, &switches); + litest_add(switch_has_cap, LITEST_SWITCH, LITEST_ANY); + litest_add(switch_has_lid_switch, LITEST_SWITCH, LITEST_ANY); + litest_add(switch_has_tablet_mode_switch, LITEST_SWITCH, LITEST_ANY); + litest_add_ranged(switch_toggle, LITEST_SWITCH, LITEST_ANY, &switches); + litest_add_ranged(switch_toggle_double, LITEST_SWITCH, LITEST_ANY, &switches); + litest_add_ranged(switch_down_on_init, LITEST_SWITCH, LITEST_ANY, &switches); + litest_add(switch_not_down_on_init, LITEST_SWITCH, LITEST_ANY); + litest_add_ranged(switch_disable_touchpad, LITEST_SWITCH, LITEST_ANY, &switches); + litest_add_ranged(switch_disable_touchpad_during_touch, LITEST_SWITCH, LITEST_ANY, &switches); + litest_add_ranged(switch_disable_touchpad_edge_scroll, LITEST_SWITCH, LITEST_ANY, &switches); + litest_add_ranged(switch_disable_touchpad_edge_scroll_interrupt, LITEST_SWITCH, LITEST_ANY, &switches); + litest_add_ranged(switch_disable_touchpad_already_open, LITEST_SWITCH, LITEST_ANY, &switches); + litest_add_ranged(switch_dont_resume_disabled_touchpad, LITEST_SWITCH, LITEST_ANY, &switches); + litest_add_ranged(switch_dont_resume_disabled_touchpad_external_mouse, LITEST_SWITCH, LITEST_ANY, &switches); - litest_add_ranged_no_device("switch:keyboard", switch_suspend_with_keyboard, &switches); - litest_add_ranged_no_device("switch:touchpad", switch_suspend_with_touchpad, &switches); + litest_add_ranged_no_device(switch_suspend_with_keyboard, &switches); + litest_add_ranged_no_device(switch_suspend_with_touchpad, &switches); - litest_add("lid:keyboard", lid_open_on_key, LITEST_SWITCH, LITEST_ANY); - litest_add("lid:keyboard", lid_open_on_key_touchpad_enabled, LITEST_SWITCH, LITEST_ANY); - litest_add_for_device("lid:buggy", lid_update_hw_on_key, LITEST_LID_SWITCH_SURFACE3); - litest_add_for_device("lid:buggy", lid_update_hw_on_key_closed_on_init, LITEST_LID_SWITCH_SURFACE3); - litest_add_for_device("lid:buggy", lid_update_hw_on_key_multiple_keyboards, LITEST_LID_SWITCH_SURFACE3); - litest_add_for_device("lid:keypress", lid_key_press, LITEST_GPIO_KEYS); + litest_add(lid_open_on_key, LITEST_SWITCH, LITEST_ANY); + litest_add(lid_open_on_key_touchpad_enabled, LITEST_SWITCH, LITEST_ANY); + litest_add_for_device(lid_update_hw_on_key, LITEST_LID_SWITCH_SURFACE3); + litest_add_for_device(lid_update_hw_on_key_closed_on_init, LITEST_LID_SWITCH_SURFACE3); + litest_add_for_device(lid_update_hw_on_key_multiple_keyboards, LITEST_LID_SWITCH_SURFACE3); + litest_add_for_device(lid_key_press, LITEST_GPIO_KEYS); - litest_add("tablet-mode:touchpad", tablet_mode_disable_touchpad_on_init, LITEST_SWITCH, LITEST_ANY); - litest_add("tablet-mode:touchpad", tablet_mode_disable_touchpad_on_resume, LITEST_SWITCH, LITEST_ANY); - litest_add("tablet-mode:touchpad", tablet_mode_enable_touchpad_on_resume, LITEST_SWITCH, LITEST_ANY); - litest_add("tablet-mode:keyboard", tablet_mode_disable_keyboard, LITEST_SWITCH, LITEST_ANY); - litest_add("tablet-mode:keyboard", tablet_mode_disable_keyboard_on_init, LITEST_SWITCH, LITEST_ANY); - litest_add("tablet-mode:keyboard", tablet_mode_disable_keyboard_on_resume, LITEST_SWITCH, LITEST_ANY); - litest_add("tablet-mode:keyboard", tablet_mode_enable_keyboard_on_resume, LITEST_SWITCH, LITEST_ANY); - litest_add("tablet-mode:trackpoint", tablet_mode_disable_trackpoint, LITEST_SWITCH, LITEST_ANY); - litest_add("tablet-mode:trackpoint", tablet_mode_disable_trackpoint_on_init, LITEST_SWITCH, LITEST_ANY); + litest_add(tablet_mode_disable_touchpad_on_init, LITEST_SWITCH, LITEST_ANY); + litest_add(tablet_mode_disable_touchpad_on_resume, LITEST_SWITCH, LITEST_ANY); + litest_add(tablet_mode_enable_touchpad_on_resume, LITEST_SWITCH, LITEST_ANY); + litest_add(tablet_mode_disable_keyboard, LITEST_SWITCH, LITEST_ANY); + litest_add(tablet_mode_disable_keyboard_on_init, LITEST_SWITCH, LITEST_ANY); + litest_add(tablet_mode_disable_keyboard_on_resume, LITEST_SWITCH, LITEST_ANY); + litest_add(tablet_mode_enable_keyboard_on_resume, LITEST_SWITCH, LITEST_ANY); + litest_add(tablet_mode_disable_trackpoint, LITEST_SWITCH, LITEST_ANY); + litest_add(tablet_mode_disable_trackpoint_on_init, LITEST_SWITCH, LITEST_ANY); - litest_add("lid:dock", dock_toggle, LITEST_SWITCH, LITEST_ANY); + litest_add(dock_toggle, LITEST_SWITCH, LITEST_ANY); } diff -Nru libinput-1.16.4/test/test-tablet.c libinput-1.17.2/test/test-tablet.c --- libinput-1.16.4/test/test-tablet.c 2020-11-27 01:38:59.393086200 +0000 +++ libinput-1.17.2/test/test-tablet.c 2021-04-30 04:25:41.542076300 +0000 @@ -635,19 +635,42 @@ }; unsigned int axis = _i; /* ranged test */ double x, y, last_x, last_y; + double start_x = 20, + start_y = 20; - litest_tablet_proximity_in(dev, 10, 10, axes); - litest_drain_events(li); + switch (axis) { + case ABS_X: + start_x = 15; + start_y = 20; + break; + case ABS_Y: + start_x = 20; + start_y = 15; + break; + default: + abort(); + } - /* enough events to get the history going */ + /* generate enough events to fill the history and move alonge the + * current axis to avoid axis smoothing interference */ + litest_tablet_proximity_in(dev, start_x, start_y, axes); litest_axis_set_value(axes, ABS_PRESSURE, 20); - for (int i = 1; i < 10; i++) { + for (int i = 0; i < 5; i++) { litest_push_event_frame(dev); - litest_tablet_motion(dev, 10 + i, 10 + i, axes); + litest_tablet_motion(dev, start_x, start_y, axes); litest_event(dev, EV_KEY, BTN_TOUCH, 1); litest_event(dev, EV_SYN, SYN_REPORT, 0); litest_pop_event_frame(dev); + switch (axis) { + case ABS_X: + start_x++; + break; + case ABS_Y: + start_y++; + break; + } + } litest_drain_events(li); @@ -670,8 +693,6 @@ case ABS_Y: litest_tablet_motion(dev, 20, 40, axes); break; - default: - abort(); } litest_event(dev, EV_KEY, BTN_TOUCH, 0); litest_pop_event_frame(dev); @@ -682,12 +703,24 @@ LIBINPUT_EVENT_TABLET_TOOL_TIP); ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event), LIBINPUT_TABLET_TOOL_TIP_UP); - ck_assert(libinput_event_tablet_tool_x_has_changed(tablet_event)); - ck_assert(libinput_event_tablet_tool_y_has_changed(tablet_event)); x = libinput_event_tablet_tool_get_x(tablet_event); y = libinput_event_tablet_tool_get_y(tablet_event); - ck_assert_double_ne(last_x, x); - ck_assert_double_ne(last_y, y); + + switch(axis) { + case ABS_X: + ck_assert(libinput_event_tablet_tool_x_has_changed(tablet_event)); + ck_assert(!libinput_event_tablet_tool_y_has_changed(tablet_event)); + ck_assert_double_ne(last_x, x); + ck_assert_double_eq(last_y, y); + break; + case ABS_Y: + ck_assert(!libinput_event_tablet_tool_x_has_changed(tablet_event)); + ck_assert(libinput_event_tablet_tool_y_has_changed(tablet_event)); + ck_assert_double_eq(last_x, x); + ck_assert_double_ne(last_y, y); + break; + } + libinput_event_destroy(event); litest_assert_empty_queue(li); @@ -2800,7 +2833,6 @@ { BTN_TOOL_PEN, LIBINPUT_TABLET_TOOL_TYPE_PEN }, { BTN_TOOL_RUBBER, LIBINPUT_TABLET_TOOL_TYPE_ERASER }, { BTN_TOOL_BRUSH, LIBINPUT_TABLET_TOOL_TYPE_BRUSH }, - { BTN_TOOL_BRUSH, LIBINPUT_TABLET_TOOL_TYPE_BRUSH }, { BTN_TOOL_PENCIL, LIBINPUT_TABLET_TOOL_TYPE_PENCIL }, { BTN_TOOL_AIRBRUSH, LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH }, { BTN_TOOL_MOUSE, LIBINPUT_TABLET_TOOL_TYPE_MOUSE }, @@ -2808,10 +2840,13 @@ { -1, -1 } }; struct tool_type_match *tt; + double x = 50, y = 50; litest_drain_events(li); for (tt = types; tt->code != -1; tt++) { + enum libinput_tablet_tool_type type; + if (!libevdev_has_event_code(dev->evdev, EV_KEY, tt->code)) @@ -2821,32 +2856,44 @@ !tablet_has_mouse(dev)) continue; - litest_push_event_frame(dev); - litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN); - litest_tablet_proximity_in(dev, 50, 50, axes); - litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN); - litest_event(dev, EV_KEY, tt->code, 1); - litest_pop_event_frame(dev); + litest_tablet_set_tool_type(dev, tt->code); + litest_tablet_proximity_in(dev, x, y, axes); libinput_dispatch(li); event = libinput_get_event(li); t = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY); tool = libinput_event_tablet_tool_get_tool(t); + type = libinput_tablet_tool_get_type(tool); + + /* Devices with doubled-up tool bits send the pen + * in-prox and immediately out-of-prox before the real tool + * type. Drop those two and continue with what we expect is + * the real prox in event */ + if (tt->type != LIBINPUT_TABLET_TOOL_TYPE_PEN && + type == LIBINPUT_TABLET_TOOL_TYPE_PEN) { + libinput_event_destroy(event); + event = libinput_get_event(li); + litest_is_tablet_event(event, + LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY); + libinput_event_destroy(event); + event = libinput_get_event(li); + t = litest_is_tablet_event(event, + LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY); + tool = libinput_event_tablet_tool_get_tool(t); + type = libinput_tablet_tool_get_type(tool); + } - ck_assert_int_eq(libinput_tablet_tool_get_type(tool), - tt->type); + ck_assert_int_eq(type, tt->type); libinput_event_destroy(event); litest_assert_empty_queue(li); - litest_push_event_frame(dev); - litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN); litest_tablet_proximity_out(dev); - litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN); - litest_event(dev, EV_KEY, tt->code, 0); - litest_pop_event_frame(dev); litest_drain_events(li); + + x++; + y++; } } END_TEST @@ -3961,18 +4008,6 @@ } END_TEST -static void pressure_threshold_warning(struct libinput *libinput, - enum libinput_log_priority priority, - const char *format, - va_list args) -{ - int *warning_triggered = (int*)libinput_get_user_data(libinput); - - if (priority == LIBINPUT_LOG_PRIORITY_ERROR && - strstr(format, "pressure offset greater")) - (*warning_triggered)++; -} - START_TEST(tablet_pressure_min_max) { struct litest_device *dev = litest_current_device(); @@ -4060,6 +4095,20 @@ } END_TEST +static void +pressure_threshold_warning(struct libinput *libinput, + enum libinput_log_priority priority, + const char *format, + va_list args) +{ + struct litest_user_data *user_data = libinput_get_user_data(libinput); + int *warning_triggered = user_data->private; + + if (priority == LIBINPUT_LOG_PRIORITY_ERROR && + strstr(format, "pressure offset greater")) + (*warning_triggered)++; +} + START_TEST(tablet_pressure_offset_exceed_threshold) { struct litest_device *dev = litest_current_device(); @@ -4073,12 +4122,11 @@ }; double pressure; int warning_triggered = 0; - void *old_user_data; + struct litest_user_data *user_data = libinput_get_user_data(li); litest_drain_events(li); - old_user_data = libinput_get_user_data(li); - libinput_set_user_data(li, &warning_triggered); + user_data->private = &warning_triggered; libinput_log_set_handler(li, pressure_threshold_warning); litest_tablet_proximity_in(dev, 5, 100, axes); @@ -4092,8 +4140,6 @@ ck_assert_int_eq(warning_triggered, 1); litest_restore_log_handler(li); - - libinput_set_user_data(li, old_user_data); } END_TEST @@ -4668,6 +4714,12 @@ ck_assert(dy == 0.0); libinput_event_destroy(event); + /* work around axis smoothing */ + litest_tablet_motion(dev, 19, 10, axes); + litest_tablet_motion(dev, 18, 10, axes); + litest_tablet_motion(dev, 17, 10, axes); + litest_drain_events(li); + litest_tablet_motion(dev, 5, 10, axes); libinput_dispatch(li); event = libinput_get_event(li); @@ -4679,7 +4731,13 @@ ck_assert(dy == 0.0); libinput_event_destroy(event); - litest_tablet_motion(dev, 10, 20, axes); + /* work around axis smoothing */ + litest_tablet_motion(dev, 5, 11, axes); + litest_tablet_motion(dev, 5, 12, axes); + litest_tablet_motion(dev, 5, 13, axes); + litest_drain_events(li); + + litest_tablet_motion(dev, 5, 20, axes); libinput_dispatch(li); event = libinput_get_event(li); tev = litest_is_tablet_event(event, @@ -4690,7 +4748,13 @@ ck_assert(dy < 0.0); libinput_event_destroy(event); - litest_tablet_motion(dev, 10, 5, axes); + /* work around axis smoothing */ + litest_tablet_motion(dev, 5, 19, axes); + litest_tablet_motion(dev, 5, 18, axes); + litest_tablet_motion(dev, 5, 17, axes); + litest_drain_events(li); + + litest_tablet_motion(dev, 5, 5, axes); libinput_dispatch(li); event = libinput_get_event(li); tev = litest_is_tablet_event(event, @@ -5923,128 +5987,212 @@ } END_TEST +START_TEST(tablet_smoothing) +{ +#if HAVE_LIBWACOM + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + double x, y; + struct point { + double x, y; + } coordinates[100] = {0}; + size_t npoints = 0; + size_t idx = 0; + struct axis_replacement axes[] = { + { ABS_DISTANCE, 10 }, + { ABS_PRESSURE, 0 }, + { -1, -1 } + }; + + litest_drain_events(li); + + litest_tablet_proximity_in(dev, 10, 10, axes); + libinput_dispatch(li); + litest_drain_events(li); + + /* Move in a straight line, collect the resulting points */ + for (x = 11, y = 11; x < 50; x++, y++) { + struct libinput_event *event; + struct libinput_event_tablet_tool *tev; + struct point *p = &coordinates[npoints++]; + + litest_assert(npoints <= ARRAY_LENGTH(coordinates)); + + litest_tablet_motion(dev, x, y, axes); + libinput_dispatch(li); + + event = libinput_get_event(li); + tev = litest_is_tablet_event(event, + LIBINPUT_EVENT_TABLET_TOOL_AXIS); + p->x = libinput_event_tablet_tool_get_x(tev); + p->y = libinput_event_tablet_tool_get_y(tev); + + libinput_event_destroy(event); + } + + litest_tablet_proximity_out(dev); + litest_tablet_proximity_in(dev, 10, 10, axes); + libinput_dispatch(li); + litest_drain_events(li); + + /* Move in a wobbly line, collect every second point */ + for (x = 11, y = 11; x < 50; x++, y++) { + struct libinput_event *event; + struct libinput_event_tablet_tool *tev; + double ex, ey; + struct point *p = &coordinates[idx++]; + + litest_assert(idx <= npoints); + + /* point off position */ + litest_tablet_motion(dev, x - 2, y + 1, axes); + libinput_dispatch(li); + event = libinput_get_event(li); + litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS); + libinput_event_destroy(event); + + /* same position as before */ + litest_tablet_motion(dev, x, y, axes); + libinput_dispatch(li); + event = libinput_get_event(li); + tev = litest_is_tablet_event(event, + LIBINPUT_EVENT_TABLET_TOOL_AXIS); + ex = libinput_event_tablet_tool_get_x(tev); + ey = libinput_event_tablet_tool_get_y(tev); + + ck_assert_double_eq(ex, p->x); + ck_assert_double_eq(ey, p->y); + + libinput_event_destroy(event); + } +#endif +} +END_TEST + TEST_COLLECTION(tablet) { struct range with_timeout = { 0, 2 }; struct range xyaxes = { ABS_X, ABS_Y + 1 }; struct range lh_transitions = {0, 16}; /* 2 bits for in, 2 bits for out */ - litest_add("tablet:tool", tool_ref, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); - litest_add("tablet:tool", tool_user_data, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); - litest_add("tablet:tool", tool_capability, LITEST_TABLET, LITEST_ANY); - litest_add_no_device("tablet:tool", tool_capabilities); - litest_add("tablet:tool", tool_type, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:tool", tool_in_prox_before_start, LITEST_TABLET, LITEST_TOTEM); - litest_add("tablet:tool", tool_direct_switch_skip_tool_update, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:tool", tool_direct_switch_with_forced_proxout, LITEST_TABLET, LITEST_ANY); + litest_add(tool_ref, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); + litest_add(tool_user_data, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); + litest_add(tool_capability, LITEST_TABLET, LITEST_ANY); + litest_add_no_device(tool_capabilities); + litest_add(tool_type, LITEST_TABLET, LITEST_FORCED_PROXOUT); + litest_add(tool_in_prox_before_start, LITEST_TABLET, LITEST_TOTEM); + litest_add(tool_direct_switch_skip_tool_update, LITEST_TABLET, LITEST_ANY); + litest_add(tool_direct_switch_with_forced_proxout, LITEST_TABLET, LITEST_ANY); /* Tablets hold back the proximity until the first event from the * kernel, the totem sends it immediately */ - litest_add("tablet:tool", tool_in_prox_before_start, LITEST_TABLET, LITEST_TOTEM); - litest_add("tablet:tool_serial", tool_unique, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); - litest_add("tablet:tool_serial", tool_serial, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); - litest_add("tablet:tool_serial", tool_id, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); - litest_add("tablet:tool_serial", serial_changes_tool, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); - litest_add("tablet:tool_serial", invalid_serials, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); - litest_add_no_device("tablet:tool_serial", tools_with_serials); - litest_add_no_device("tablet:tool_serial", tools_without_serials); - litest_add_for_device("tablet:tool_serial", tool_delayed_serial, LITEST_WACOM_HID4800_PEN); - litest_add("tablet:proximity", proximity_out_clear_buttons, LITEST_TABLET, LITEST_FORCED_PROXOUT); - litest_add("tablet:proximity", proximity_in_out, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:proximity", proximity_in_button_down, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:proximity", proximity_out_button_up, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:proximity", proximity_has_axes, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:proximity", bad_distance_events, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY); - litest_add("tablet:proximity", proximity_range_enter, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY); - litest_add("tablet:proximity", proximity_range_in_out, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY); - litest_add("tablet:proximity", proximity_range_button_click, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY); - litest_add("tablet:proximity", proximity_range_button_press, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY); - litest_add("tablet:proximity", proximity_range_button_release, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY); - litest_add("tablet:proximity", proximity_out_slow_event, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY); - litest_add("tablet:proximity", proximity_out_not_during_contact, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY); - litest_add("tablet:proximity", proximity_out_not_during_buttonpress, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY); - litest_add("tablet:proximity", proximity_out_disables_forced, LITEST_TABLET, LITEST_FORCED_PROXOUT|LITEST_TOTEM); - litest_add("tablet:proximity", proximity_out_disables_forced_after_forced, LITEST_TABLET, LITEST_FORCED_PROXOUT|LITEST_TOTEM); - litest_add_no_device("tablet:proximity", proximity_out_on_delete); - litest_add("tablet:button", button_down_up, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:button", button_seat_count, LITEST_TABLET, LITEST_ANY); - litest_add_no_device("tablet:button", button_up_on_delete); - litest_add("tablet:tip", tip_down_up, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); - litest_add("tablet:tip", tip_down_prox_in, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:tip", tip_up_prox_out, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:tip", tip_down_btn_change, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); - litest_add("tablet:tip", tip_up_btn_change, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); - litest_add("tablet:tip", tip_down_motion, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); - litest_add("tablet:tip", tip_up_motion, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); - litest_add_ranged("tablet:tip", tip_up_motion_one_axis, LITEST_TABLET|LITEST_HOVER, LITEST_ANY, &xyaxes); - litest_add("tablet:tip", tip_state_proximity, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); - litest_add("tablet:tip", tip_state_axis, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); - litest_add("tablet:tip", tip_state_button, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); - litest_add_no_device("tablet:tip", tip_up_on_delete); - litest_add("tablet:motion", motion, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:motion", motion_event_state, LITEST_TABLET, LITEST_ANY); - litest_add_for_device("tablet:motion", motion_outside_bounds, LITEST_WACOM_CINTIQ_24HD); - litest_add("tablet:tilt", tilt_available, LITEST_TABLET|LITEST_TILT, LITEST_ANY); - litest_add("tablet:tilt", tilt_not_available, LITEST_TABLET, LITEST_TILT); - litest_add("tablet:tilt", tilt_x, LITEST_TABLET|LITEST_TILT, LITEST_ANY); - litest_add("tablet:tilt", tilt_y, LITEST_TABLET|LITEST_TILT, LITEST_ANY); - litest_add_for_device("tablet:left_handed", left_handed, LITEST_WACOM_INTUOS); - litest_add_for_device("tablet:left_handed", left_handed_tilt, LITEST_WACOM_INTUOS); - litest_add_for_device("tablet:left_handed", left_handed_mouse_rotation, LITEST_WACOM_INTUOS); - litest_add_for_device("tablet:left_handed", left_handed_artpen_rotation, LITEST_WACOM_INTUOS); - litest_add_for_device("tablet:left_handed", no_left_handed, LITEST_WACOM_CINTIQ); - litest_add("tablet:pad", pad_buttons_ignored, LITEST_TABLET, LITEST_TOTEM); - litest_add("tablet:mouse", mouse_tool, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_ANY); - litest_add("tablet:mouse", mouse_buttons, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_ANY); - litest_add("tablet:mouse", mouse_rotation, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_ANY); - litest_add("tablet:mouse", mouse_wheel, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_WHEEL); - litest_add("tablet:airbrush", airbrush_tool, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:airbrush", airbrush_slider, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:artpen", artpen_tool, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:artpen", artpen_rotation, LITEST_TABLET, LITEST_ANY); + litest_add(tool_in_prox_before_start, LITEST_TABLET, LITEST_TOTEM); + litest_add(tool_unique, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); + litest_add(tool_serial, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); + litest_add(tool_id, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); + litest_add(serial_changes_tool, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); + litest_add(invalid_serials, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); + litest_add_no_device(tools_with_serials); + litest_add_no_device(tools_without_serials); + litest_add_for_device(tool_delayed_serial, LITEST_WACOM_HID4800_PEN); + litest_add(proximity_out_clear_buttons, LITEST_TABLET, LITEST_FORCED_PROXOUT); + litest_add(proximity_in_out, LITEST_TABLET, LITEST_ANY); + litest_add(proximity_in_button_down, LITEST_TABLET, LITEST_ANY); + litest_add(proximity_out_button_up, LITEST_TABLET, LITEST_ANY); + litest_add(proximity_has_axes, LITEST_TABLET, LITEST_ANY); + litest_add(bad_distance_events, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY); + litest_add(proximity_range_enter, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY); + litest_add(proximity_range_in_out, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY); + litest_add(proximity_range_button_click, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY); + litest_add(proximity_range_button_press, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY); + litest_add(proximity_range_button_release, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY); + litest_add(proximity_out_slow_event, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY); + litest_add(proximity_out_not_during_contact, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY); + litest_add(proximity_out_not_during_buttonpress, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY); + litest_add(proximity_out_disables_forced, LITEST_TABLET, LITEST_FORCED_PROXOUT|LITEST_TOTEM); + litest_add(proximity_out_disables_forced_after_forced, LITEST_TABLET, LITEST_FORCED_PROXOUT|LITEST_TOTEM); + litest_add_no_device(proximity_out_on_delete); + litest_add(button_down_up, LITEST_TABLET, LITEST_ANY); + litest_add(button_seat_count, LITEST_TABLET, LITEST_ANY); + litest_add_no_device(button_up_on_delete); + litest_add(tip_down_up, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); + litest_add(tip_down_prox_in, LITEST_TABLET, LITEST_ANY); + litest_add(tip_up_prox_out, LITEST_TABLET, LITEST_ANY); + litest_add(tip_down_btn_change, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); + litest_add(tip_up_btn_change, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); + litest_add(tip_down_motion, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); + litest_add(tip_up_motion, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); + litest_add_ranged(tip_up_motion_one_axis, LITEST_TABLET|LITEST_HOVER, LITEST_ANY, &xyaxes); + litest_add(tip_state_proximity, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); + litest_add(tip_state_axis, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); + litest_add(tip_state_button, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); + litest_add_no_device(tip_up_on_delete); + litest_add(motion, LITEST_TABLET, LITEST_ANY); + litest_add(motion_event_state, LITEST_TABLET, LITEST_ANY); + litest_add_for_device(motion_outside_bounds, LITEST_WACOM_CINTIQ_24HD); + litest_add(tilt_available, LITEST_TABLET|LITEST_TILT, LITEST_ANY); + litest_add(tilt_not_available, LITEST_TABLET, LITEST_TILT); + litest_add(tilt_x, LITEST_TABLET|LITEST_TILT, LITEST_ANY); + litest_add(tilt_y, LITEST_TABLET|LITEST_TILT, LITEST_ANY); + litest_add_for_device(left_handed, LITEST_WACOM_INTUOS); + litest_add_for_device(left_handed_tilt, LITEST_WACOM_INTUOS); + litest_add_for_device(left_handed_mouse_rotation, LITEST_WACOM_INTUOS); + litest_add_for_device(left_handed_artpen_rotation, LITEST_WACOM_INTUOS); + litest_add_for_device(no_left_handed, LITEST_WACOM_CINTIQ); + litest_add(pad_buttons_ignored, LITEST_TABLET, LITEST_TOTEM); + litest_add(mouse_tool, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_ANY); + litest_add(mouse_buttons, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_ANY); + litest_add(mouse_rotation, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_ANY); + litest_add(mouse_wheel, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_WHEEL); + litest_add(airbrush_tool, LITEST_TABLET, LITEST_ANY); + litest_add(airbrush_slider, LITEST_TABLET, LITEST_ANY); + litest_add(artpen_tool, LITEST_TABLET, LITEST_ANY); + litest_add(artpen_rotation, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:time", tablet_time_usec, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:pressure", tablet_pressure_distance_exclusive, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY); + litest_add(tablet_time_usec, LITEST_TABLET, LITEST_ANY); + litest_add(tablet_pressure_distance_exclusive, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY); /* The totem doesn't need calibration */ - litest_add("tablet:calibration", tablet_calibration_has_matrix, LITEST_TABLET, LITEST_TOTEM); - litest_add("tablet:calibration", tablet_calibration_set_matrix, LITEST_TABLET, LITEST_TOTEM); - litest_add("tablet:calibration", tablet_calibration_set_matrix_delta, LITEST_TABLET, LITEST_TOTEM); - - litest_add("tablet:pressure", tablet_pressure_min_max, LITEST_TABLET, LITEST_ANY); - litest_add_for_device("tablet:pressure", tablet_pressure_range, LITEST_WACOM_INTUOS); - litest_add_for_device("tablet:pressure", tablet_pressure_offset, LITEST_WACOM_INTUOS); - litest_add_for_device("tablet:pressure", tablet_pressure_offset_decrease, LITEST_WACOM_INTUOS); - litest_add_for_device("tablet:pressure", tablet_pressure_offset_increase, LITEST_WACOM_INTUOS); - litest_add_for_device("tablet:pressure", tablet_pressure_offset_exceed_threshold, LITEST_WACOM_INTUOS); - litest_add_for_device("tablet:pressure", tablet_pressure_offset_none_for_zero_distance, LITEST_WACOM_INTUOS); - litest_add_for_device("tablet:pressure", tablet_pressure_offset_none_for_small_distance, LITEST_WACOM_INTUOS); - litest_add_for_device("tablet:distance", tablet_distance_range, LITEST_WACOM_INTUOS); - - litest_add("tablet:relative", relative_no_profile, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:relative", relative_no_delta_prox_in, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:relative", relative_delta, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:relative", relative_no_delta_on_tip, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); - litest_add("tablet:relative", relative_calibration, LITEST_TABLET, LITEST_ANY); - - litest_add("tablet:touch-arbitration", touch_arbitration, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:touch-arbitration", touch_arbitration_stop_touch, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:touch-arbitration", touch_arbitration_suspend_touch_device, LITEST_TOUCH, LITEST_ANY); - litest_add("tablet:touch-arbitration", touch_arbitration_remove_touch, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:touch-arbitration", touch_arbitration_remove_tablet, LITEST_TOUCH, LITEST_ANY); - litest_add("tablet:touch-arbitration", touch_arbitration_keep_ignoring, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:touch-arbitration", touch_arbitration_late_touch_lift, LITEST_TABLET, LITEST_ANY); - litest_add("tablet:touch-arbitration", touch_arbitration_outside_rect, LITEST_TABLET | LITEST_DIRECT, LITEST_ANY); - litest_add("tablet:touch-arbitration", touch_arbitration_remove_after, LITEST_TABLET | LITEST_DIRECT, LITEST_ANY); - - litest_add_ranged("tablet:touch-rotation", tablet_rotation_left_handed, LITEST_TABLET, LITEST_ANY, &lh_transitions); - litest_add_ranged("tablet:touch-rotation", tablet_rotation_left_handed_configuration, LITEST_TABLET, LITEST_ANY, &lh_transitions); - litest_add_ranged("tablet:touch-rotation", tablet_rotation_left_handed_while_in_prox, LITEST_TABLET, LITEST_ANY, &lh_transitions); - litest_add_ranged("tablet:touch-rotation", tablet_rotation_left_handed_while_touch_down, LITEST_TABLET, LITEST_ANY, &lh_transitions); - litest_add_ranged("tablet:touch-rotation", tablet_rotation_left_handed_add_touchpad, LITEST_TABLET, LITEST_ANY, &lh_transitions); - litest_add_ranged("tablet:touch-rotation", tablet_rotation_left_handed_add_tablet, LITEST_TOUCHPAD, LITEST_ANY, &lh_transitions); - - litest_add_for_device("tablet:quirks", huion_static_btn_tool_pen, LITEST_HUION_TABLET); - litest_add_for_device("tablet:quirks", huion_static_btn_tool_pen_no_timeout_during_usage, LITEST_HUION_TABLET); - litest_add_ranged_for_device("tablet:quirks", huion_static_btn_tool_pen_disable_quirk_on_prox_out, LITEST_HUION_TABLET, &with_timeout); + litest_add(tablet_calibration_has_matrix, LITEST_TABLET, LITEST_TOTEM); + litest_add(tablet_calibration_set_matrix, LITEST_TABLET, LITEST_TOTEM); + litest_add(tablet_calibration_set_matrix_delta, LITEST_TABLET, LITEST_TOTEM); + + litest_add(tablet_pressure_min_max, LITEST_TABLET, LITEST_ANY); + litest_add_for_device(tablet_pressure_range, LITEST_WACOM_INTUOS); + litest_add_for_device(tablet_pressure_offset, LITEST_WACOM_INTUOS); + litest_add_for_device(tablet_pressure_offset_decrease, LITEST_WACOM_INTUOS); + litest_add_for_device(tablet_pressure_offset_increase, LITEST_WACOM_INTUOS); + litest_add_for_device(tablet_pressure_offset_exceed_threshold, LITEST_WACOM_INTUOS); + litest_add_for_device(tablet_pressure_offset_none_for_zero_distance, LITEST_WACOM_INTUOS); + litest_add_for_device(tablet_pressure_offset_none_for_small_distance, LITEST_WACOM_INTUOS); + litest_add_for_device(tablet_distance_range, LITEST_WACOM_INTUOS); + + litest_add(relative_no_profile, LITEST_TABLET, LITEST_ANY); + litest_add(relative_no_delta_prox_in, LITEST_TABLET, LITEST_ANY); + litest_add(relative_delta, LITEST_TABLET, LITEST_ANY); + litest_add(relative_no_delta_on_tip, LITEST_TABLET|LITEST_HOVER, LITEST_ANY); + litest_add(relative_calibration, LITEST_TABLET, LITEST_ANY); + + litest_add(touch_arbitration, LITEST_TABLET, LITEST_ANY); + litest_add(touch_arbitration_stop_touch, LITEST_TABLET, LITEST_ANY); + litest_add(touch_arbitration_suspend_touch_device, LITEST_TOUCH, LITEST_ANY); + litest_add(touch_arbitration_remove_touch, LITEST_TABLET, LITEST_ANY); + litest_add(touch_arbitration_remove_tablet, LITEST_TOUCH, LITEST_ANY); + litest_add(touch_arbitration_keep_ignoring, LITEST_TABLET, LITEST_ANY); + litest_add(touch_arbitration_late_touch_lift, LITEST_TABLET, LITEST_ANY); + litest_add(touch_arbitration_outside_rect, LITEST_TABLET | LITEST_DIRECT, LITEST_ANY); + litest_add(touch_arbitration_remove_after, LITEST_TABLET | LITEST_DIRECT, LITEST_ANY); + + litest_add_ranged(tablet_rotation_left_handed, LITEST_TABLET, LITEST_ANY, &lh_transitions); + litest_add_ranged(tablet_rotation_left_handed_configuration, LITEST_TABLET, LITEST_ANY, &lh_transitions); + litest_add_ranged(tablet_rotation_left_handed_while_in_prox, LITEST_TABLET, LITEST_ANY, &lh_transitions); + litest_add_ranged(tablet_rotation_left_handed_while_touch_down, LITEST_TABLET, LITEST_ANY, &lh_transitions); + litest_add_ranged(tablet_rotation_left_handed_add_touchpad, LITEST_TABLET, LITEST_ANY, &lh_transitions); + litest_add_ranged(tablet_rotation_left_handed_add_tablet, LITEST_TOUCHPAD, LITEST_ANY, &lh_transitions); + + litest_add_for_device(huion_static_btn_tool_pen, LITEST_HUION_TABLET); + litest_add_for_device(huion_static_btn_tool_pen_no_timeout_during_usage, LITEST_HUION_TABLET); + litest_add_ranged_for_device(huion_static_btn_tool_pen_disable_quirk_on_prox_out, LITEST_HUION_TABLET, &with_timeout); + + litest_add_for_device(tablet_smoothing, LITEST_WACOM_HID4800_PEN); } diff -Nru libinput-1.16.4/test/test-totem.c libinput-1.17.2/test/test-totem.c --- libinput-1.16.4/test/test-totem.c 2020-11-27 01:38:59.393086200 +0000 +++ libinput-1.17.2/test/test-totem.c 2021-04-30 04:25:41.542076300 +0000 @@ -586,20 +586,20 @@ TEST_COLLECTION(totem) { - litest_add("totem:tool", totem_type, LITEST_TOTEM, LITEST_ANY); - litest_add("totem:tool", totem_axes, LITEST_TOTEM, LITEST_ANY); - litest_add("totem:proximity", totem_proximity_in_out, LITEST_TOTEM, LITEST_ANY); - litest_add("totem:proximity", totem_proximity_in_on_init, LITEST_TOTEM, LITEST_ANY); - litest_add("totem:proximity", totem_proximity_out_on_suspend, LITEST_TOTEM, LITEST_ANY); + litest_add(totem_type, LITEST_TOTEM, LITEST_ANY); + litest_add(totem_axes, LITEST_TOTEM, LITEST_ANY); + litest_add(totem_proximity_in_out, LITEST_TOTEM, LITEST_ANY); + litest_add(totem_proximity_in_on_init, LITEST_TOTEM, LITEST_ANY); + litest_add(totem_proximity_out_on_suspend, LITEST_TOTEM, LITEST_ANY); - litest_add("totem:axes", totem_motion, LITEST_TOTEM, LITEST_ANY); - litest_add("totem:axes", totem_rotation, LITEST_TOTEM, LITEST_ANY); - litest_add("totem:axes", totem_size, LITEST_TOTEM, LITEST_ANY); - litest_add("totem:button", totem_button, LITEST_TOTEM, LITEST_ANY); - litest_add("totem:button", totem_button_down_on_init, LITEST_TOTEM, LITEST_ANY); - litest_add_no_device("totem:button", totem_button_up_on_delete); + litest_add(totem_motion, LITEST_TOTEM, LITEST_ANY); + litest_add(totem_rotation, LITEST_TOTEM, LITEST_ANY); + litest_add(totem_size, LITEST_TOTEM, LITEST_ANY); + litest_add(totem_button, LITEST_TOTEM, LITEST_ANY); + litest_add(totem_button_down_on_init, LITEST_TOTEM, LITEST_ANY); + litest_add_no_device(totem_button_up_on_delete); - litest_add("totem:arbitration", totem_arbitration_below, LITEST_TOTEM, LITEST_ANY); - litest_add("totem:arbitration", totem_arbitration_during, LITEST_TOTEM, LITEST_ANY); - litest_add("totem:arbitration", totem_arbitration_outside_rect, LITEST_TOTEM, LITEST_ANY); + litest_add(totem_arbitration_below, LITEST_TOTEM, LITEST_ANY); + litest_add(totem_arbitration_during, LITEST_TOTEM, LITEST_ANY); + litest_add(totem_arbitration_outside_rect, LITEST_TOTEM, LITEST_ANY); } diff -Nru libinput-1.16.4/test/test-touch.c libinput-1.17.2/test/test-touch.c --- libinput-1.16.4/test/test-touch.c 2020-11-27 01:38:59.394086100 +0000 +++ libinput-1.17.2/test/test-touch.c 2021-04-30 04:25:41.542076300 +0000 @@ -987,7 +987,7 @@ litest_touch_move_to(dev, 0, 50, 50, 70, 70, 10); litest_drain_events(li); - /* Touch is still down when device is removed, espect a release */ + /* Touch is still down when device is removed, expect a release */ litest_delete_device(dev); libinput_dispatch(li); @@ -1342,53 +1342,53 @@ { struct range axes = { ABS_X, ABS_Y + 1}; - litest_add("touch:frame", touch_frame_events, LITEST_TOUCH, LITEST_ANY); - litest_add("touch:down", touch_downup_no_motion, LITEST_TOUCH, LITEST_ANY); - litest_add("touch:down", touch_downup_no_motion, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD); - litest_add_no_device("touch:abs-transform", touch_abs_transform); - litest_add("touch:slots", touch_seat_slot, LITEST_TOUCH, LITEST_TOUCHPAD); - litest_add_no_device("touch:slots", touch_many_slots); - litest_add("touch:double-touch-down-up", touch_double_touch_down_up, LITEST_TOUCH, LITEST_PROTOCOL_A); - litest_add("touch:calibration", touch_calibration_scale, LITEST_TOUCH, LITEST_TOUCHPAD); - litest_add("touch:calibration", touch_calibration_scale, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD); - litest_add("touch:calibration", touch_calibration_rotation, LITEST_TOUCH, LITEST_TOUCHPAD); - litest_add("touch:calibration", touch_calibration_rotation, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD); - litest_add("touch:calibration", touch_calibration_translation, LITEST_TOUCH, LITEST_TOUCHPAD); - litest_add("touch:calibration", touch_calibration_translation, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD); - litest_add_for_device("touch:calibration", touch_calibrated_screen_path, LITEST_CALIBRATED_TOUCHSCREEN); - litest_add_for_device("touch:calibration", touch_calibrated_screen_udev, LITEST_CALIBRATED_TOUCHSCREEN); - litest_add("touch:calibration", touch_calibration_config, LITEST_TOUCH, LITEST_ANY); - - litest_add("touch:left-handed", touch_no_left_handed, LITEST_TOUCH, LITEST_ANY); - - litest_add("touch:fake-mt", fake_mt_exists, LITEST_FAKE_MT, LITEST_ANY); - litest_add("touch:fake-mt", fake_mt_no_touch_events, LITEST_FAKE_MT, LITEST_ANY); - - litest_add("touch:protocol a", touch_protocol_a_init, LITEST_PROTOCOL_A, LITEST_ANY); - litest_add("touch:protocol a", touch_protocol_a_touch, LITEST_PROTOCOL_A, LITEST_ANY); - litest_add("touch:protocol a", touch_protocol_a_2fg_touch, LITEST_PROTOCOL_A, LITEST_ANY); - - litest_add_ranged("touch:state", touch_initial_state, LITEST_TOUCH, LITEST_PROTOCOL_A, &axes); - - litest_add("touch:time", touch_time_usec, LITEST_TOUCH, LITEST_TOUCHPAD); - - litest_add_for_device("touch:fuzz", touch_fuzz, LITEST_MULTITOUCH_FUZZ_SCREEN); - litest_add_for_device("touch:fuzz", touch_fuzz_property, LITEST_MULTITOUCH_FUZZ_SCREEN); - - litest_add_no_device("touch:release", touch_release_on_unplug); - - 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); - - litest_add("touch:tool", touch_palm_detect_tool_palm, LITEST_TOUCH, LITEST_ANY); - litest_add("touch:tool", touch_palm_detect_tool_palm_on_off, LITEST_TOUCH, LITEST_ANY); - litest_add("touch:tool", touch_palm_detect_tool_palm_keep_type, LITEST_TOUCH, LITEST_ANY); - litest_add("touch:tool", touch_palm_detect_tool_palm_2fg, LITEST_TOUCH, LITEST_SINGLE_TOUCH); - litest_add("touch:tool", touch_palm_detect_tool_palm_on_off_2fg, LITEST_TOUCH, LITEST_SINGLE_TOUCH); - litest_add("touch:tool", touch_palm_detect_tool_palm_keep_type_2fg, LITEST_TOUCH, LITEST_ANY); + litest_add(touch_frame_events, LITEST_TOUCH, LITEST_ANY); + litest_add(touch_downup_no_motion, LITEST_TOUCH, LITEST_ANY); + litest_add(touch_downup_no_motion, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD); + litest_add_no_device(touch_abs_transform); + litest_add(touch_seat_slot, LITEST_TOUCH, LITEST_TOUCHPAD); + litest_add_no_device(touch_many_slots); + litest_add(touch_double_touch_down_up, LITEST_TOUCH, LITEST_PROTOCOL_A); + litest_add(touch_calibration_scale, LITEST_TOUCH, LITEST_TOUCHPAD); + litest_add(touch_calibration_scale, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD); + litest_add(touch_calibration_rotation, LITEST_TOUCH, LITEST_TOUCHPAD); + litest_add(touch_calibration_rotation, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD); + litest_add(touch_calibration_translation, LITEST_TOUCH, LITEST_TOUCHPAD); + litest_add(touch_calibration_translation, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD); + litest_add_for_device(touch_calibrated_screen_path, LITEST_CALIBRATED_TOUCHSCREEN); + litest_add_for_device(touch_calibrated_screen_udev, LITEST_CALIBRATED_TOUCHSCREEN); + litest_add(touch_calibration_config, LITEST_TOUCH, LITEST_ANY); + + litest_add(touch_no_left_handed, LITEST_TOUCH, LITEST_ANY); + + litest_add(fake_mt_exists, LITEST_FAKE_MT, LITEST_ANY); + litest_add(fake_mt_no_touch_events, LITEST_FAKE_MT, LITEST_ANY); + + litest_add(touch_protocol_a_init, LITEST_PROTOCOL_A, LITEST_ANY); + litest_add(touch_protocol_a_touch, LITEST_PROTOCOL_A, LITEST_ANY); + litest_add(touch_protocol_a_2fg_touch, LITEST_PROTOCOL_A, LITEST_ANY); + + litest_add_ranged(touch_initial_state, LITEST_TOUCH, LITEST_PROTOCOL_A, &axes); + + litest_add(touch_time_usec, LITEST_TOUCH, LITEST_TOUCHPAD); + + litest_add_for_device(touch_fuzz, LITEST_MULTITOUCH_FUZZ_SCREEN); + litest_add_for_device(touch_fuzz_property, LITEST_MULTITOUCH_FUZZ_SCREEN); + + litest_add_no_device(touch_release_on_unplug); + + litest_add_for_device(touch_invalid_range_over, LITEST_TOUCHSCREEN_INVALID_RANGE); + litest_add_for_device(touch_invalid_range_under, LITEST_TOUCHSCREEN_INVALID_RANGE); + + litest_add(touch_count_st, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD); + litest_add(touch_count_mt, LITEST_TOUCH, LITEST_SINGLE_TOUCH|LITEST_PROTOCOL_A); + litest_add(touch_count_unknown, LITEST_PROTOCOL_A, LITEST_ANY); + litest_add(touch_count_invalid, LITEST_ANY, LITEST_TOUCH|LITEST_SINGLE_TOUCH|LITEST_PROTOCOL_A); + + litest_add(touch_palm_detect_tool_palm, LITEST_TOUCH, LITEST_ANY); + litest_add(touch_palm_detect_tool_palm_on_off, LITEST_TOUCH, LITEST_ANY); + litest_add(touch_palm_detect_tool_palm_keep_type, LITEST_TOUCH, LITEST_ANY); + litest_add(touch_palm_detect_tool_palm_2fg, LITEST_TOUCH, LITEST_SINGLE_TOUCH); + litest_add(touch_palm_detect_tool_palm_on_off_2fg, LITEST_TOUCH, LITEST_SINGLE_TOUCH); + litest_add(touch_palm_detect_tool_palm_keep_type_2fg, LITEST_TOUCH, LITEST_ANY); } diff -Nru libinput-1.16.4/test/test-touchpad-buttons.c libinput-1.17.2/test/test-touchpad-buttons.c --- libinput-1.16.4/test/test-touchpad-buttons.c 2020-11-27 01:38:59.394086100 +0000 +++ libinput-1.17.2/test/test-touchpad-buttons.c 2021-04-30 04:25:41.542076300 +0000 @@ -2096,71 +2096,69 @@ { struct range finger_count = {1, 4}; - litest_add("touchpad:button", touchpad_button, LITEST_TOUCHPAD, LITEST_CLICKPAD); + litest_add(touchpad_button, LITEST_TOUCHPAD, LITEST_CLICKPAD); - litest_add("touchpad:clickfinger", touchpad_1fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:clickfinger", touchpad_1fg_clickfinger_no_touch, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:clickfinger", touchpad_2fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:clickfinger", touchpad_3fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:clickfinger", touchpad_3fg_clickfinger_btntool, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:clickfinger", touchpad_4fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:clickfinger", touchpad_4fg_clickfinger_btntool_2slots, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:clickfinger", touchpad_4fg_clickfinger_btntool_3slots, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:clickfinger", touchpad_2fg_clickfinger_distance, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:clickfinger", touchpad_3fg_clickfinger_distance, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:clickfinger", touchpad_3fg_clickfinger_distance_btntool, LITEST_CLICKPAD, LITEST_ANY); - litest_add_for_device("touchpad:clickfinger", touchpad_2fg_clickfinger_bottom, LITEST_SYNAPTICS_TOPBUTTONPAD); - litest_add("touchpad:clickfinger", touchpad_clickfinger_to_area_method, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:clickfinger", - touchpad_clickfinger_to_area_method_while_down, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:clickfinger", touchpad_area_to_clickfinger_method, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:clickfinger", - touchpad_area_to_clickfinger_method_while_down, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_1fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_1fg_clickfinger_no_touch, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_2fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_3fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_3fg_clickfinger_btntool, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_4fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_4fg_clickfinger_btntool_2slots, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_4fg_clickfinger_btntool_3slots, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_2fg_clickfinger_distance, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_3fg_clickfinger_distance, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_3fg_clickfinger_distance_btntool, LITEST_CLICKPAD, LITEST_ANY); + litest_add_for_device(touchpad_2fg_clickfinger_bottom, LITEST_SYNAPTICS_TOPBUTTONPAD); + litest_add(touchpad_clickfinger_to_area_method, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_clickfinger_to_area_method_while_down, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_area_to_clickfinger_method, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_area_to_clickfinger_method_while_down, LITEST_CLICKPAD, LITEST_ANY); /* run those two for the T440 one only so we don't have to worry * about small touchpads messing with thumb detection expectations */ - litest_add_for_device("touchpad:clickfinger", touchpad_clickfinger_3fg_tool_position, LITEST_SYNAPTICS_TOPBUTTONPAD); - litest_add_for_device("touchpad:clickfinger", touchpad_clickfinger_4fg_tool_position, LITEST_SYNAPTICS_TOPBUTTONPAD); + litest_add_for_device(touchpad_clickfinger_3fg_tool_position, LITEST_SYNAPTICS_TOPBUTTONPAD); + litest_add_for_device(touchpad_clickfinger_4fg_tool_position, LITEST_SYNAPTICS_TOPBUTTONPAD); - litest_add_for_device("touchpad:clickfinger", touchpad_clickfinger_appletouch_config, LITEST_APPLETOUCH); - litest_add_for_device("touchpad:clickfinger", touchpad_clickfinger_appletouch_1fg, LITEST_APPLETOUCH); - litest_add_for_device("touchpad:clickfinger", touchpad_clickfinger_appletouch_2fg, LITEST_APPLETOUCH); - litest_add_for_device("touchpad:clickfinger", touchpad_clickfinger_appletouch_3fg, LITEST_APPLETOUCH); - - litest_add_ranged("touchpad:clickfinger", touchpad_clickfinger_click_drag, LITEST_CLICKPAD, LITEST_ANY, &finger_count); - - litest_add("touchpad:click", touchpad_click_defaults_clickfinger, LITEST_APPLE_CLICKPAD, LITEST_ANY); - litest_add("touchpad:click", touchpad_click_defaults_btnarea, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); - litest_add("touchpad:click", touchpad_click_defaults_none, LITEST_TOUCHPAD, LITEST_CLICKPAD); - litest_add("touchpad:click", touchpad_click_defaults_none, LITEST_ANY, LITEST_TOUCHPAD); - - litest_add("touchpad:click", touchpad_btn_left, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_CLICKPAD); - litest_add("touchpad:click", clickpad_btn_left, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:click", clickpad_click_n_drag, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:click", clickpad_finger_pin, LITEST_CLICKPAD, LITEST_ANY); - - litest_add("touchpad:softbutton", clickpad_softbutton_left, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); - litest_add("touchpad:softbutton", clickpad_softbutton_middle, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); - litest_add("touchpad:softbutton", clickpad_softbutton_right, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); - litest_add("touchpad:softbutton", clickpad_softbutton_left_tap_n_drag, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); - litest_add("touchpad:softbutton", clickpad_softbutton_right_tap_n_drag, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); - litest_add("touchpad:softbutton", clickpad_softbutton_left_1st_fg_move, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); - litest_add("touchpad:softbutton", clickpad_softbutton_left_2nd_fg_move, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); - litest_add("touchpad:softbutton", clickpad_softbutton_left_to_right, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); - litest_add("touchpad:softbutton", clickpad_softbutton_right_to_left, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); - litest_add("touchpad:softbutton", clickpad_softbutton_hover_into_buttons, LITEST_CLICKPAD|LITEST_HOVER, LITEST_APPLE_CLICKPAD); - - litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_left, LITEST_TOPBUTTONPAD, LITEST_ANY); - litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_right, LITEST_TOPBUTTONPAD, LITEST_ANY); - litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_middle, LITEST_TOPBUTTONPAD, LITEST_ANY); - litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_move_out_leftclick, LITEST_TOPBUTTONPAD, LITEST_ANY); - litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_move_out_leftclick_before_timeout, LITEST_TOPBUTTONPAD, LITEST_ANY); - litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_clickfinger, LITEST_TOPBUTTONPAD, LITEST_ANY); - litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_clickfinger_dev_disabled, LITEST_TOPBUTTONPAD, LITEST_ANY); - - litest_add("touchpad:middleemulation", clickpad_middleemulation_config_delayed, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:middleemulation", clickpad_middleemulation_click, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:middleemulation", clickpad_middleemulation_click_middle_left, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:middleemulation", clickpad_middleemulation_click_middle_right, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:middleemulation", clickpad_middleemulation_click_enable_while_down, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:middleemulation", clickpad_middleemulation_click_disable_while_down, LITEST_CLICKPAD, LITEST_ANY); + litest_add_for_device(touchpad_clickfinger_appletouch_config, LITEST_APPLETOUCH); + litest_add_for_device(touchpad_clickfinger_appletouch_1fg, LITEST_APPLETOUCH); + litest_add_for_device(touchpad_clickfinger_appletouch_2fg, LITEST_APPLETOUCH); + litest_add_for_device(touchpad_clickfinger_appletouch_3fg, LITEST_APPLETOUCH); + + litest_add_ranged(touchpad_clickfinger_click_drag, LITEST_CLICKPAD, LITEST_ANY, &finger_count); + + litest_add(touchpad_click_defaults_clickfinger, LITEST_APPLE_CLICKPAD, LITEST_ANY); + litest_add(touchpad_click_defaults_btnarea, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); + litest_add(touchpad_click_defaults_none, LITEST_TOUCHPAD, LITEST_CLICKPAD); + litest_add(touchpad_click_defaults_none, LITEST_ANY, LITEST_TOUCHPAD); + + litest_add(touchpad_btn_left, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_CLICKPAD); + litest_add(clickpad_btn_left, LITEST_CLICKPAD, LITEST_ANY); + litest_add(clickpad_click_n_drag, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH); + litest_add(clickpad_finger_pin, LITEST_CLICKPAD, LITEST_ANY); + + litest_add(clickpad_softbutton_left, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); + litest_add(clickpad_softbutton_middle, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); + litest_add(clickpad_softbutton_right, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); + litest_add(clickpad_softbutton_left_tap_n_drag, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); + litest_add(clickpad_softbutton_right_tap_n_drag, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); + litest_add(clickpad_softbutton_left_1st_fg_move, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); + litest_add(clickpad_softbutton_left_2nd_fg_move, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); + litest_add(clickpad_softbutton_left_to_right, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); + litest_add(clickpad_softbutton_right_to_left, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); + litest_add(clickpad_softbutton_hover_into_buttons, LITEST_CLICKPAD|LITEST_HOVER, LITEST_APPLE_CLICKPAD); + + litest_add(clickpad_topsoftbuttons_left, LITEST_TOPBUTTONPAD, LITEST_ANY); + litest_add(clickpad_topsoftbuttons_right, LITEST_TOPBUTTONPAD, LITEST_ANY); + litest_add(clickpad_topsoftbuttons_middle, LITEST_TOPBUTTONPAD, LITEST_ANY); + litest_add(clickpad_topsoftbuttons_move_out_leftclick, LITEST_TOPBUTTONPAD, LITEST_ANY); + litest_add(clickpad_topsoftbuttons_move_out_leftclick_before_timeout, LITEST_TOPBUTTONPAD, LITEST_ANY); + litest_add(clickpad_topsoftbuttons_clickfinger, LITEST_TOPBUTTONPAD, LITEST_ANY); + litest_add(clickpad_topsoftbuttons_clickfinger_dev_disabled, LITEST_TOPBUTTONPAD, LITEST_ANY); + + litest_add(clickpad_middleemulation_config_delayed, LITEST_CLICKPAD, LITEST_ANY); + litest_add(clickpad_middleemulation_click, LITEST_CLICKPAD, LITEST_ANY); + litest_add(clickpad_middleemulation_click_middle_left, LITEST_CLICKPAD, LITEST_ANY); + litest_add(clickpad_middleemulation_click_middle_right, LITEST_CLICKPAD, LITEST_ANY); + litest_add(clickpad_middleemulation_click_enable_while_down, LITEST_CLICKPAD, LITEST_ANY); + litest_add(clickpad_middleemulation_click_disable_while_down, LITEST_CLICKPAD, LITEST_ANY); } diff -Nru libinput-1.16.4/test/test-touchpad.c libinput-1.17.2/test/test-touchpad.c --- libinput-1.16.4/test/test-touchpad.c 2020-11-27 01:38:59.396086200 +0000 +++ libinput-1.17.2/test/test-touchpad.c 2021-04-30 04:25:41.543076300 +0000 @@ -1795,8 +1795,12 @@ { struct libevdev *evdev = dev->evdev; + if (dev->which == LITEST_SYNAPTICS_PRESSUREPAD) + return false; + if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_PRESSURE)) - return true; + return libevdev_get_abs_resolution(evdev, + ABS_MT_PRESSURE) == 0; return false; } @@ -5913,8 +5917,12 @@ { struct libevdev *evdev = dev->evdev; + if (dev->which == LITEST_SYNAPTICS_PRESSUREPAD) + return false; + if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_PRESSURE)) - return true; + return libevdev_get_abs_resolution(evdev, + ABS_MT_PRESSURE) == 0; if (libevdev_has_event_code(evdev, EV_ABS, ABS_PRESSURE) && !libevdev_has_event_code(evdev, EV_ABS, ABS_MT_SLOT)) @@ -6986,203 +6994,203 @@ struct range twice = {0, 2 }; struct range five_fingers = {1, 6}; - litest_add("touchpad:motion", touchpad_1fg_motion, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:motion", touchpad_2fg_no_motion, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_1fg_motion, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_2fg_no_motion, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:scroll", touchpad_2fg_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("touchpad:scroll", touchpad_2fg_scroll_initially_diagonal, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("touchpad:scroll", touchpad_2fg_scroll_axis_lock, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("touchpad:scroll", touchpad_2fg_scroll_axis_lock_switch, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - - litest_add("touchpad:scroll", touchpad_2fg_scroll_slow_distance, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:scroll", touchpad_2fg_scroll_return_to_motion, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:scroll", touchpad_2fg_scroll_source, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:scroll", touchpad_2fg_scroll_semi_mt, LITEST_SEMI_MT, LITEST_SINGLE_TOUCH); - litest_add("touchpad:scroll", touchpad_2fg_scroll_from_btnareas, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:scroll", touchpad_scroll_natural_defaults, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:scroll", touchpad_scroll_natural_enable_config, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:scroll", touchpad_scroll_natural_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:scroll", touchpad_scroll_natural_edge, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:scroll", touchpad_scroll_defaults, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:scroll", touchpad_edge_scroll_vert, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:scroll", touchpad_edge_scroll_horiz, LITEST_TOUCHPAD, LITEST_CLICKPAD); - litest_add("touchpad:scroll", touchpad_edge_scroll_horiz_clickpad, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:scroll", touchpad_edge_scroll_no_horiz, LITEST_TOUCHPAD, LITEST_CLICKPAD); - litest_add("touchpad:scroll", touchpad_edge_scroll_no_motion, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:scroll", touchpad_edge_scroll_no_edge_after_motion, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:scroll", touchpad_edge_scroll_timeout, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:scroll", touchpad_edge_scroll_source, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:scroll", touchpad_edge_scroll_no_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:scroll", touchpad_edge_scroll_into_buttonareas, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:scroll", touchpad_edge_scroll_within_buttonareas, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:scroll", touchpad_edge_scroll_buttonareas_click_stops_scroll, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:scroll", touchpad_edge_scroll_clickfinger_click_stops_scroll, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:scroll", touchpad_edge_scroll_into_area, LITEST_TOUCHPAD, LITEST_ANY); - - litest_add("touchpad:palm", touchpad_palm_detect_at_edge, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_palm_detect_at_top, LITEST_TOUCHPAD, LITEST_TOPBUTTONPAD); - litest_add("touchpad:palm", touchpad_palm_detect_at_bottom_corners, LITEST_TOUCHPAD, LITEST_CLICKPAD); - litest_add("touchpad:palm", touchpad_palm_detect_at_top_corners, LITEST_TOUCHPAD, LITEST_TOPBUTTONPAD); - litest_add("touchpad:palm", touchpad_palm_detect_palm_becomes_pointer, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_palm_detect_top_palm_becomes_pointer, LITEST_TOUCHPAD, LITEST_TOPBUTTONPAD); - litest_add("touchpad:palm", touchpad_palm_detect_palm_stays_palm, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_palm_detect_top_palm_stays_palm, LITEST_TOUCHPAD, LITEST_TOPBUTTONPAD); - litest_add("touchpad:palm", touchpad_palm_detect_no_palm_moving_into_edges, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_palm_detect_no_palm_moving_into_top, LITEST_TOUCHPAD, LITEST_TOPBUTTONPAD); - litest_add("touchpad:palm", touchpad_palm_detect_no_tap_top_edge, LITEST_TOUCHPAD, LITEST_TOPBUTTONPAD); - litest_add("touchpad:palm", touchpad_palm_detect_tap_hardbuttons, LITEST_TOUCHPAD, LITEST_CLICKPAD); - litest_add("touchpad:palm", touchpad_palm_detect_tap_softbuttons, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_palm_detect_tap_clickfinger, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_no_palm_detect_at_edge_for_edge_scrolling, LITEST_TOUCHPAD, LITEST_CLICKPAD); - litest_add("touchpad:palm", touchpad_no_palm_detect_2fg_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:palm", touchpad_palm_detect_both_edges, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:palm", touchpad_palm_detect_tool_palm, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:palm", touchpad_palm_detect_tool_palm_on_off, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:palm", touchpad_palm_detect_tool_palm_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:palm", touchpad_palm_detect_tool_palm_tap_after, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - - litest_add("touchpad:palm", touchpad_palm_detect_touch_size, LITEST_APPLE_CLICKPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_palm_detect_touch_size_late, LITEST_APPLE_CLICKPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_palm_detect_touch_size_keep_palm, LITEST_APPLE_CLICKPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_palm_detect_touch_size_after_edge, LITEST_APPLE_CLICKPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_palm_detect_touch_size_after_dwt, LITEST_APPLE_CLICKPAD, LITEST_ANY); - - litest_add("touchpad:palm", touchpad_palm_detect_pressure, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:palm", touchpad_palm_detect_pressure_late_tap, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_palm_detect_pressure_tap_hold, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_palm_detect_pressure_tap_hold_2ndfg, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:palm", touchpad_palm_detect_move_and_tap, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_palm_detect_pressure_late, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:palm", touchpad_palm_detect_pressure_keep_palm, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:palm", touchpad_palm_detect_pressure_after_edge, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:palm", touchpad_palm_detect_pressure_after_dwt, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:palm", touchpad_palm_clickfinger_pressure, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_palm_clickfinger_pressure_2fg, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_palm_clickfinger_size, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:palm", touchpad_palm_clickfinger_size_2fg, LITEST_CLICKPAD, LITEST_ANY); - - litest_add("touchpad:left-handed", touchpad_left_handed, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_CLICKPAD); - litest_add_for_device("touchpad:left-handed", touchpad_left_handed_appletouch, LITEST_APPLETOUCH); - litest_add("touchpad:left-handed", touchpad_left_handed_clickpad, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); - litest_add("touchpad:left-handed", touchpad_left_handed_clickfinger, LITEST_APPLE_CLICKPAD, LITEST_ANY); - litest_add("touchpad:left-handed", touchpad_left_handed_tapping, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:left-handed", touchpad_left_handed_tapping_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:left-handed", touchpad_left_handed_delayed, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_CLICKPAD); - litest_add("touchpad:left-handed", touchpad_left_handed_clickpad_delayed, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); - litest_add("touchpad:left-handed", touchpad_left_handed_rotation, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_2fg_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add(touchpad_2fg_scroll_initially_diagonal, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add(touchpad_2fg_scroll_axis_lock, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add(touchpad_2fg_scroll_axis_lock_switch, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + + litest_add(touchpad_2fg_scroll_slow_distance, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_2fg_scroll_return_to_motion, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_2fg_scroll_source, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_2fg_scroll_semi_mt, LITEST_SEMI_MT, LITEST_SINGLE_TOUCH); + litest_add(touchpad_2fg_scroll_from_btnareas, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_scroll_natural_defaults, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_scroll_natural_enable_config, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_scroll_natural_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_scroll_natural_edge, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_scroll_defaults, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_edge_scroll_vert, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_edge_scroll_horiz, LITEST_TOUCHPAD, LITEST_CLICKPAD); + litest_add(touchpad_edge_scroll_horiz_clickpad, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_edge_scroll_no_horiz, LITEST_TOUCHPAD, LITEST_CLICKPAD); + litest_add(touchpad_edge_scroll_no_motion, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_edge_scroll_no_edge_after_motion, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_edge_scroll_timeout, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_edge_scroll_source, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_edge_scroll_no_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_edge_scroll_into_buttonareas, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_edge_scroll_within_buttonareas, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_edge_scroll_buttonareas_click_stops_scroll, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_edge_scroll_clickfinger_click_stops_scroll, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_edge_scroll_into_area, LITEST_TOUCHPAD, LITEST_ANY); + + litest_add(touchpad_palm_detect_at_edge, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_palm_detect_at_top, LITEST_TOUCHPAD, LITEST_TOPBUTTONPAD); + litest_add(touchpad_palm_detect_at_bottom_corners, LITEST_TOUCHPAD, LITEST_CLICKPAD); + litest_add(touchpad_palm_detect_at_top_corners, LITEST_TOUCHPAD, LITEST_TOPBUTTONPAD); + litest_add(touchpad_palm_detect_palm_becomes_pointer, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_palm_detect_top_palm_becomes_pointer, LITEST_TOUCHPAD, LITEST_TOPBUTTONPAD); + litest_add(touchpad_palm_detect_palm_stays_palm, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_palm_detect_top_palm_stays_palm, LITEST_TOUCHPAD, LITEST_TOPBUTTONPAD); + litest_add(touchpad_palm_detect_no_palm_moving_into_edges, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_palm_detect_no_palm_moving_into_top, LITEST_TOUCHPAD, LITEST_TOPBUTTONPAD); + litest_add(touchpad_palm_detect_no_tap_top_edge, LITEST_TOUCHPAD, LITEST_TOPBUTTONPAD); + litest_add(touchpad_palm_detect_tap_hardbuttons, LITEST_TOUCHPAD, LITEST_CLICKPAD); + litest_add(touchpad_palm_detect_tap_softbuttons, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_palm_detect_tap_clickfinger, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_no_palm_detect_at_edge_for_edge_scrolling, LITEST_TOUCHPAD, LITEST_CLICKPAD); + litest_add(touchpad_no_palm_detect_2fg_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_palm_detect_both_edges, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_palm_detect_tool_palm, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_palm_detect_tool_palm_on_off, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_palm_detect_tool_palm_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_palm_detect_tool_palm_tap_after, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + + litest_add(touchpad_palm_detect_touch_size, LITEST_APPLE_CLICKPAD, LITEST_ANY); + litest_add(touchpad_palm_detect_touch_size_late, LITEST_APPLE_CLICKPAD, LITEST_ANY); + litest_add(touchpad_palm_detect_touch_size_keep_palm, LITEST_APPLE_CLICKPAD, LITEST_ANY); + litest_add(touchpad_palm_detect_touch_size_after_edge, LITEST_APPLE_CLICKPAD, LITEST_ANY); + litest_add(touchpad_palm_detect_touch_size_after_dwt, LITEST_APPLE_CLICKPAD, LITEST_ANY); + + litest_add(touchpad_palm_detect_pressure, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_palm_detect_pressure_late_tap, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_palm_detect_pressure_tap_hold, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_palm_detect_pressure_tap_hold_2ndfg, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_palm_detect_move_and_tap, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_palm_detect_pressure_late, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_palm_detect_pressure_keep_palm, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_palm_detect_pressure_after_edge, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_palm_detect_pressure_after_dwt, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_palm_clickfinger_pressure, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_palm_clickfinger_pressure_2fg, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_palm_clickfinger_size, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_palm_clickfinger_size_2fg, LITEST_CLICKPAD, LITEST_ANY); + + litest_add(touchpad_left_handed, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_CLICKPAD); + litest_add_for_device(touchpad_left_handed_appletouch, LITEST_APPLETOUCH); + litest_add(touchpad_left_handed_clickpad, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); + litest_add(touchpad_left_handed_clickfinger, LITEST_APPLE_CLICKPAD, LITEST_ANY); + litest_add(touchpad_left_handed_tapping, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_left_handed_tapping_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_left_handed_delayed, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_CLICKPAD); + litest_add(touchpad_left_handed_clickpad_delayed, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); + litest_add(touchpad_left_handed_rotation, LITEST_TOUCHPAD, LITEST_ANY); /* Semi-MT hover tests aren't generic, they only work on this device and * ignore the semi-mt capability (it doesn't matter for the tests) */ - litest_add_for_device("touchpad:semi-mt-hover", touchpad_semi_mt_hover_noevent, LITEST_SYNAPTICS_HOVER_SEMI_MT); - litest_add_for_device("touchpad:semi-mt-hover", touchpad_semi_mt_hover_down, LITEST_SYNAPTICS_HOVER_SEMI_MT); - litest_add_for_device("touchpad:semi-mt-hover", touchpad_semi_mt_hover_down_up, LITEST_SYNAPTICS_HOVER_SEMI_MT); - litest_add_for_device("touchpad:semi-mt-hover", touchpad_semi_mt_hover_down_hover_down, LITEST_SYNAPTICS_HOVER_SEMI_MT); - litest_add_for_device("touchpad:semi-mt-hover", touchpad_semi_mt_hover_2fg_noevent, LITEST_SYNAPTICS_HOVER_SEMI_MT); - litest_add_for_device("touchpad:semi-mt-hover", touchpad_semi_mt_hover_2fg_1fg_down, LITEST_SYNAPTICS_HOVER_SEMI_MT); - litest_add_for_device("touchpad:semi-mt-hover", touchpad_semi_mt_hover_2fg_up, LITEST_SYNAPTICS_HOVER_SEMI_MT); - - litest_add("touchpad:hover", touchpad_hover_noevent, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY); - litest_add("touchpad:hover", touchpad_hover_down, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY); - litest_add("touchpad:hover", touchpad_hover_down_up, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY); - litest_add("touchpad:hover", touchpad_hover_down_hover_down, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY); - litest_add("touchpad:hover", touchpad_hover_2fg_noevent, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY); - litest_add("touchpad:hover", touchpad_hover_2fg_1fg_down, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY); - litest_add("touchpad:hover", touchpad_hover_1fg_tap, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY); - - litest_add_for_device("touchpad:trackpoint", touchpad_trackpoint_buttons, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS); - litest_add_for_device("touchpad:trackpoint", touchpad_trackpoint_mb_scroll, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS); - litest_add_for_device("touchpad:trackpoint", touchpad_trackpoint_mb_click, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS); - litest_add_for_device("touchpad:trackpoint", touchpad_trackpoint_buttons_softbuttons, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS); - litest_add_for_device("touchpad:trackpoint", touchpad_trackpoint_buttons_2fg_scroll, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS); - litest_add_for_device("touchpad:trackpoint", touchpad_trackpoint_no_trackpoint, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS); - - litest_add_ranged("touchpad:state", touchpad_initial_state, LITEST_TOUCHPAD, LITEST_ANY, &axis_range); - litest_add_ranged("touchpad:state", touchpad_fingers_down_before_init, LITEST_TOUCHPAD, LITEST_ANY, &five_fingers); - litest_add("touchpad:state", touchpad_state_after_syn_dropped_2fg_change, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - - litest_add("touchpad:dwt", touchpad_dwt, LITEST_TOUCHPAD, LITEST_ANY); - litest_add_for_device("touchpad:dwt", touchpad_dwt_ext_and_int_keyboard, LITEST_SYNAPTICS_I2C); - litest_add("touchpad:dwt", touchpad_dwt_enable_touch, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_touch_hold, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_key_hold, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_key_hold_timeout, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_key_hold_timeout_existing_touch, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_key_hold_timeout_existing_touch_cornercase, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_type, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_type_short_timeout, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_modifier_no_dwt, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_modifier_combo_no_dwt, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_modifier_combo_dwt_after, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_modifier_combo_dwt_remains, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_fkeys_no_dwt, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_tap, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_tap_drag, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_click, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_edge_scroll, LITEST_TOUCHPAD, LITEST_CLICKPAD); - litest_add("touchpad:dwt", touchpad_dwt_edge_scroll_interrupt, LITEST_TOUCHPAD, LITEST_CLICKPAD); - litest_add("touchpad:dwt", touchpad_dwt_config_default_on, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_config_default_off, LITEST_ANY, LITEST_TOUCHPAD); - litest_add("touchpad:dwt", touchpad_dwt_disabled, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_disable_during_touch, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_disable_before_touch, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_disable_during_key_release, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_disable_during_key_hold, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_enable_during_touch, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_enable_before_touch, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_enable_during_tap, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:dwt", touchpad_dwt_remove_kbd_while_active, LITEST_TOUCHPAD, LITEST_ANY); - litest_add_for_device("touchpad:dwt", touchpad_dwt_apple, LITEST_BCM5974); - litest_add_for_device("touchpad:dwt", touchpad_dwt_acer_hawaii, LITEST_ACER_HAWAII_TOUCHPAD); - litest_add_for_device("touchpad:dwt", touchpad_dwt_multiple_keyboards, LITEST_SYNAPTICS_I2C); - litest_add_for_device("touchpad:dwt", touchpad_dwt_multiple_keyboards_bothkeys, LITEST_SYNAPTICS_I2C); - litest_add_for_device("touchpad:dwt", touchpad_dwt_multiple_keyboards_bothkeys_modifier, LITEST_SYNAPTICS_I2C); - litest_add_ranged_for_device("touchpad:dwt", touchpad_dwt_multiple_keyboards_remove, LITEST_SYNAPTICS_I2C, &twice); - - litest_add("touchpad:thumb", touchpad_thumb_lower_area_movement, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:thumb", touchpad_thumb_lower_area_movement_rethumb, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:thumb", touchpad_thumb_speed_empty_slots, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:thumb", touchpad_thumb_area_clickfinger, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:thumb", touchpad_thumb_area_btnarea, LITEST_CLICKPAD, LITEST_ANY); - litest_add("touchpad:thumb", touchpad_thumb_no_doublethumb, LITEST_CLICKPAD, LITEST_ANY); - - litest_add_for_device("touchpad:bugs", touchpad_tool_tripletap_touch_count, LITEST_SYNAPTICS_TOPBUTTONPAD); - litest_add_for_device("touchpad:bugs", touchpad_tool_tripletap_touch_count_late, LITEST_SYNAPTICS_TOPBUTTONPAD); - litest_add_for_device("touchpad:bugs", touchpad_slot_swap, LITEST_SYNAPTICS_TOPBUTTONPAD); - litest_add_for_device("touchpad:bugs", touchpad_finger_always_down, LITEST_SYNAPTICS_TOPBUTTONPAD); - - litest_add("touchpad:time", touchpad_time_usec, LITEST_TOUCHPAD, LITEST_ANY); - - litest_add_for_device("touchpad:jumps", touchpad_jump_finger_motion, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_for_device("touchpad:jumps", touchpad_jump_delta, LITEST_SYNAPTICS_CLICKPAD_X220); - - litest_add_for_device("touchpad:sendevents", touchpad_disabled_on_mouse, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_for_device("touchpad:sendevents", touchpad_disabled_on_mouse_suspend_mouse, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_for_device("touchpad:sendevents", touchpad_disabled_double_mouse, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_for_device("touchpad:sendevents", touchpad_disabled_double_mouse_one_suspended, LITEST_SYNAPTICS_CLICKPAD_X220); - - litest_add("touchpad:pressure", touchpad_pressure, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:pressure", touchpad_pressure_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:pressure", touchpad_pressure_2fg_st, LITEST_TOUCHPAD|LITEST_SINGLE_TOUCH, LITEST_ANY); - litest_add("touchpad:pressure", touchpad_pressure_tap, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("touchpad:pressure", touchpad_pressure_tap_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:pressure", touchpad_pressure_tap_2fg_1fg_light, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:pressure", touchpad_pressure_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:pressure", touchpad_pressure_semi_mt_2fg_goes_light, LITEST_SEMI_MT, LITEST_ANY); - - litest_add("touchpad:touch-size", touchpad_touch_size, LITEST_APPLE_CLICKPAD, LITEST_ANY); - litest_add("touchpad:touch-size", touchpad_touch_size_2fg, LITEST_APPLE_CLICKPAD, LITEST_ANY); - - litest_add("touchpad:speed", touchpad_speed_ignore_finger, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("touchpad:speed", touchpad_speed_allow_nearby_finger, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("touchpad:speed", touchpad_speed_ignore_finger_edgescroll, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add_for_device("touchpad:speed", touchpad_speed_ignore_hovering_finger, LITEST_BCM5974); + litest_add_for_device(touchpad_semi_mt_hover_noevent, LITEST_SYNAPTICS_HOVER_SEMI_MT); + litest_add_for_device(touchpad_semi_mt_hover_down, LITEST_SYNAPTICS_HOVER_SEMI_MT); + litest_add_for_device(touchpad_semi_mt_hover_down_up, LITEST_SYNAPTICS_HOVER_SEMI_MT); + litest_add_for_device(touchpad_semi_mt_hover_down_hover_down, LITEST_SYNAPTICS_HOVER_SEMI_MT); + litest_add_for_device(touchpad_semi_mt_hover_2fg_noevent, LITEST_SYNAPTICS_HOVER_SEMI_MT); + litest_add_for_device(touchpad_semi_mt_hover_2fg_1fg_down, LITEST_SYNAPTICS_HOVER_SEMI_MT); + litest_add_for_device(touchpad_semi_mt_hover_2fg_up, LITEST_SYNAPTICS_HOVER_SEMI_MT); + + litest_add(touchpad_hover_noevent, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY); + litest_add(touchpad_hover_down, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY); + litest_add(touchpad_hover_down_up, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY); + litest_add(touchpad_hover_down_hover_down, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY); + litest_add(touchpad_hover_2fg_noevent, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY); + litest_add(touchpad_hover_2fg_1fg_down, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY); + litest_add(touchpad_hover_1fg_tap, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY); + + litest_add_for_device(touchpad_trackpoint_buttons, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS); + litest_add_for_device(touchpad_trackpoint_mb_scroll, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS); + litest_add_for_device(touchpad_trackpoint_mb_click, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS); + litest_add_for_device(touchpad_trackpoint_buttons_softbuttons, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS); + litest_add_for_device(touchpad_trackpoint_buttons_2fg_scroll, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS); + litest_add_for_device(touchpad_trackpoint_no_trackpoint, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS); + + litest_add_ranged(touchpad_initial_state, LITEST_TOUCHPAD, LITEST_ANY, &axis_range); + litest_add_ranged(touchpad_fingers_down_before_init, LITEST_TOUCHPAD, LITEST_ANY, &five_fingers); + litest_add(touchpad_state_after_syn_dropped_2fg_change, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + + litest_add(touchpad_dwt, LITEST_TOUCHPAD, LITEST_ANY); + litest_add_for_device(touchpad_dwt_ext_and_int_keyboard, LITEST_SYNAPTICS_I2C); + litest_add(touchpad_dwt_enable_touch, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_touch_hold, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_key_hold, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_key_hold_timeout, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_key_hold_timeout_existing_touch, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_key_hold_timeout_existing_touch_cornercase, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_type, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_type_short_timeout, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_modifier_no_dwt, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_modifier_combo_no_dwt, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_modifier_combo_dwt_after, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_modifier_combo_dwt_remains, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_fkeys_no_dwt, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_tap, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_tap_drag, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_click, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_edge_scroll, LITEST_TOUCHPAD, LITEST_CLICKPAD); + litest_add(touchpad_dwt_edge_scroll_interrupt, LITEST_TOUCHPAD, LITEST_CLICKPAD); + litest_add(touchpad_dwt_config_default_on, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_config_default_off, LITEST_ANY, LITEST_TOUCHPAD); + litest_add(touchpad_dwt_disabled, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_disable_during_touch, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_disable_before_touch, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_disable_during_key_release, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_disable_during_key_hold, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_enable_during_touch, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_enable_before_touch, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_enable_during_tap, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_dwt_remove_kbd_while_active, LITEST_TOUCHPAD, LITEST_ANY); + litest_add_for_device(touchpad_dwt_apple, LITEST_BCM5974); + litest_add_for_device(touchpad_dwt_acer_hawaii, LITEST_ACER_HAWAII_TOUCHPAD); + litest_add_for_device(touchpad_dwt_multiple_keyboards, LITEST_SYNAPTICS_I2C); + litest_add_for_device(touchpad_dwt_multiple_keyboards_bothkeys, LITEST_SYNAPTICS_I2C); + litest_add_for_device(touchpad_dwt_multiple_keyboards_bothkeys_modifier, LITEST_SYNAPTICS_I2C); + litest_add_ranged_for_device(touchpad_dwt_multiple_keyboards_remove, LITEST_SYNAPTICS_I2C, &twice); + + litest_add(touchpad_thumb_lower_area_movement, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_thumb_lower_area_movement_rethumb, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_thumb_speed_empty_slots, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_thumb_area_clickfinger, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_thumb_area_btnarea, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_thumb_no_doublethumb, LITEST_CLICKPAD, LITEST_ANY); + + litest_add_for_device(touchpad_tool_tripletap_touch_count, LITEST_SYNAPTICS_TOPBUTTONPAD); + litest_add_for_device(touchpad_tool_tripletap_touch_count_late, LITEST_SYNAPTICS_TOPBUTTONPAD); + litest_add_for_device(touchpad_slot_swap, LITEST_SYNAPTICS_TOPBUTTONPAD); + litest_add_for_device(touchpad_finger_always_down, LITEST_SYNAPTICS_TOPBUTTONPAD); + + litest_add(touchpad_time_usec, LITEST_TOUCHPAD, LITEST_ANY); + + litest_add_for_device(touchpad_jump_finger_motion, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_for_device(touchpad_jump_delta, LITEST_SYNAPTICS_CLICKPAD_X220); + + litest_add_for_device(touchpad_disabled_on_mouse, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_for_device(touchpad_disabled_on_mouse_suspend_mouse, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_for_device(touchpad_disabled_double_mouse, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_for_device(touchpad_disabled_double_mouse_one_suspended, LITEST_SYNAPTICS_CLICKPAD_X220); + + litest_add(touchpad_pressure, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_pressure_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_pressure_2fg_st, LITEST_TOUCHPAD|LITEST_SINGLE_TOUCH, LITEST_ANY); + litest_add(touchpad_pressure_tap, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_pressure_tap_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_pressure_tap_2fg_1fg_light, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_pressure_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_pressure_semi_mt_2fg_goes_light, LITEST_SEMI_MT, LITEST_ANY); + + litest_add(touchpad_touch_size, LITEST_APPLE_CLICKPAD, LITEST_ANY); + litest_add(touchpad_touch_size_2fg, LITEST_APPLE_CLICKPAD, LITEST_ANY); + + litest_add(touchpad_speed_ignore_finger, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add(touchpad_speed_allow_nearby_finger, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add(touchpad_speed_ignore_finger_edgescroll, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add_for_device(touchpad_speed_ignore_hovering_finger, LITEST_BCM5974); - litest_add_ranged("touchpad:suspend", touchpad_suspend_abba, LITEST_TOUCHPAD, LITEST_ANY, &suspends); - litest_add_ranged("touchpad:suspend", touchpad_suspend_abab, LITEST_TOUCHPAD, LITEST_ANY, &suspends); + litest_add_ranged(touchpad_suspend_abba, LITEST_TOUCHPAD, LITEST_ANY, &suspends); + litest_add_ranged(touchpad_suspend_abab, LITEST_TOUCHPAD, LITEST_ANY, &suspends); /* Happens on the "Wacom Intuos Pro M Finger" but our test device * has the same properties */ - litest_add_for_device("touchpad:bugs", touchpad_end_start_touch, LITEST_WACOM_FINGER); + litest_add_for_device(touchpad_end_start_touch, LITEST_WACOM_FINGER); - litest_add("touchpad:fuzz", touchpad_fuzz, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_fuzz, LITEST_TOUCHPAD, LITEST_ANY); } diff -Nru libinput-1.16.4/test/test-touchpad-tap.c libinput-1.17.2/test/test-touchpad-tap.c --- libinput-1.16.4/test/test-touchpad-tap.c 2020-11-27 01:38:59.394086100 +0000 +++ libinput-1.17.2/test/test-touchpad-tap.c 2021-04-30 04:25:41.542076300 +0000 @@ -56,25 +56,108 @@ } END_TEST -START_TEST(touchpad_1fg_doubletap) +START_TEST(touchpad_doubletap) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct libinput_event *event; struct libinput_event_pointer *ptrev; uint32_t oldtime, curtime; + int nfingers = (_i % 3) + 1, /* ranged test */ + nfingers2 = _i / 3; + unsigned int button = 0, + button2 = 0; + + if (nfingers > litest_slot_count(dev)) + return; + if (nfingers2 > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + switch (nfingers2) { + case 1: + button2 = BTN_LEFT; + break; + case 2: + button2 = BTN_RIGHT; + break; + case 3: + button2 = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); - litest_touch_down(dev, 0, 50, 50); + /* one to three finger down, all fingers up, repeat with possibly + different number of fingers -> two button event pairs */ + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } msleep(10); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } msleep(10); - litest_touch_down(dev, 0, 50, 50); + + switch (nfingers2) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } msleep(10); - litest_touch_up(dev, 0); + switch (nfingers2) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } libinput_dispatch(li); litest_timeout_tap(); @@ -82,14 +165,14 @@ libinput_dispatch(li); event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); oldtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -97,7 +180,7 @@ event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button2, LIBINPUT_BUTTON_STATE_PRESSED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -106,7 +189,7 @@ event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button2, LIBINPUT_BUTTON_STATE_RELEASED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -116,7 +199,7 @@ } END_TEST -START_TEST(touchpad_1fg_multitap) +START_TEST(touchpad_multitap) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; @@ -124,17 +207,59 @@ struct libinput_event_pointer *ptrev; uint32_t oldtime = 0, curtime; - int range = _i, /* looped test */ + int nfingers = (_i % 3) + 1, /* ranged test */ + range = _i / 3, /* looped test */ ntaps; + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_enable_drag_lock(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); for (ntaps = 0; ntaps <= range; ntaps++) { - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + libinput_dispatch(li); msleep(10); } @@ -145,7 +270,7 @@ for (ntaps = 0; ntaps <= range; ntaps++) { event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -153,19 +278,19 @@ event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); ck_assert_int_ge(curtime, oldtime); oldtime = curtime; } - litest_timeout_tap(); + litest_timeout_tapndrag(); litest_assert_empty_queue(li); } END_TEST -START_TEST(touchpad_1fg_multitap_n_drag_move) +START_TEST(touchpad_multitap_n_drag_move) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; @@ -173,17 +298,58 @@ struct libinput_event_pointer *ptrev; uint32_t oldtime = 0, curtime; - int range = _i, /* looped test */ + int nfingers = (_i % 3) + 1, /* ranged test */ + range = _i / 3, /* looped test */ ntaps; + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_enable_drag_lock(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); for (ntaps = 0; ntaps <= range; ntaps++) { - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } libinput_dispatch(li); msleep(10); } @@ -196,7 +362,7 @@ for (ntaps = 0; ntaps < range; ntaps++) { event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -204,7 +370,7 @@ event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -214,7 +380,7 @@ event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -224,15 +390,17 @@ LIBINPUT_EVENT_POINTER_MOTION); litest_touch_up(dev, 0); + libinput_dispatch(li); + litest_timeout_tapndrag(); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_empty_queue(li); } END_TEST -START_TEST(touchpad_1fg_multitap_n_drag_2fg) +START_TEST(touchpad_multitap_n_drag_2fg) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; @@ -240,34 +408,76 @@ struct libinput_event_pointer *ptrev; uint32_t oldtime = 0, curtime; - int range = _i, + int nfingers = (_i % 3) + 1, /* ranged test */ + range = _i / 3, /* looped test */ ntaps; + unsigned int button = 0; if (libevdev_has_property(dev->evdev, INPUT_PROP_SEMI_MT)) return; + if (nfingers > litest_slot_count(dev)) + return; + litest_enable_tap(dev->libinput_device); litest_enable_drag_lock(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); for (ntaps = 0; ntaps <= range; ntaps++) { - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + libinput_dispatch(li); msleep(10); } libinput_dispatch(li); litest_touch_down(dev, 0, 50, 50); - msleep(10); + litest_touch_move_to(dev, 0, 50, 50, 30, 50, 10); litest_touch_down(dev, 1, 70, 50); libinput_dispatch(li); for (ntaps = 0; ntaps < range; ntaps++) { event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -275,7 +485,7 @@ event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -285,7 +495,7 @@ event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -298,16 +508,17 @@ litest_touch_up(dev, 1); litest_touch_up(dev, 0); - litest_timeout_tap(); + libinput_dispatch(li); + litest_timeout_tapndrag(); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_empty_queue(li); } END_TEST -START_TEST(touchpad_1fg_multitap_n_drag_click) +START_TEST(touchpad_multitap_n_drag_click) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; @@ -315,17 +526,59 @@ struct libinput_event_pointer *ptrev; uint32_t oldtime = 0, curtime; - int range = _i, /* looped test */ + int nfingers = (_i % 3) + 1, /* ranged test */ + range = _i / 3, /* looped test */ ntaps; + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_enable_drag_lock(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); for (ntaps = 0; ntaps <= range; ntaps++) { - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + libinput_dispatch(li); msleep(10); } @@ -339,7 +592,7 @@ for (ntaps = 0; ntaps <= range; ntaps++) { event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -347,7 +600,7 @@ event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -362,31 +615,73 @@ BTN_LEFT, LIBINPUT_BUTTON_STATE_RELEASED); litest_touch_up(dev, 0); - litest_timeout_tap(); + litest_timeout_tapndrag(); litest_assert_empty_queue(li); } END_TEST -START_TEST(touchpad_1fg_multitap_timeout) +START_TEST(touchpad_multitap_timeout) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct libinput_event *event; struct libinput_event_pointer *ptrev; uint32_t ptime, rtime; - int range = _i, /* looped test */ + int nfingers = (_i % 3) + 1, /* ranged test */ + range = _i / 3, /* looped test */ ntaps; + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_enable_drag_lock(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); for (ntaps = 0; ntaps <= range; ntaps++) { - litest_touch_down(dev, 0, 50, 50); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } msleep(10); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + libinput_dispatch(li); msleep(10); } @@ -398,14 +693,14 @@ for (ntaps = 0; ntaps <= range; ntaps++) { event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); ptime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); rtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -416,7 +711,7 @@ } END_TEST -START_TEST(touchpad_1fg_multitap_n_drag_timeout) +START_TEST(touchpad_multitap_n_drag_timeout) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; @@ -424,18 +719,60 @@ struct libinput_event_pointer *ptrev; uint32_t oldtime = 0, curtime; - int range = _i, /* looped test */ + int nfingers = (_i % 3) + 1, /* ranged test */ + range = _i / 3, /* looped test */ ntaps; + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_enable_drag_lock(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); for (ntaps = 0; ntaps <= range; ntaps++) { - litest_touch_down(dev, 0, 50, 50); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } msleep(10); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + libinput_dispatch(li); msleep(10); } @@ -450,7 +787,7 @@ for (ntaps = 0; ntaps < range; ntaps++) { event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -458,7 +795,7 @@ event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -468,7 +805,7 @@ event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -480,34 +817,78 @@ LIBINPUT_EVENT_POINTER_MOTION); litest_touch_up(dev, 0); + libinput_dispatch(li); + litest_timeout_tapndrag(); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_empty_queue(li); } END_TEST -START_TEST(touchpad_1fg_tap_drag_high_delay) +START_TEST(touchpad_multitap_n_drag_high_delay) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - int range = _i, /* looped test */ + int nfingers = (_i % 3) + 1, /* ranged test */ + range = _i / 3, /* looped test */ ntaps; + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_enable_drag_lock(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); for (ntaps = 0; ntaps <= range; ntaps++) { /* Tap timeout is 180ms after a touch or release. Make sure we * go over 180ms for touch+release, but stay under 180ms for * each single event. */ - litest_touch_down(dev, 0, 50, 50); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } libinput_dispatch(li); msleep(100); - litest_touch_up(dev, 0); + + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } libinput_dispatch(li); msleep(100); } @@ -518,26 +899,28 @@ libinput_dispatch(li); for (ntaps = 0; ntaps < range; ntaps++) { - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_PRESSED); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_RELEASED); } - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); litest_touch_up(dev, 0); - litest_assert_button_event(li, BTN_LEFT, + libinput_dispatch(li); + litest_timeout_tapndrag(); + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_empty_queue(li); } END_TEST -START_TEST(touchpad_1fg_multitap_n_drag_tap) +START_TEST(touchpad_multitap_n_drag_tap) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; @@ -545,20 +928,62 @@ struct libinput_event_pointer *ptrev; uint32_t oldtime = 0, curtime; - int range = _i, /* looped test */ + int nfingers = (_i % 3) + 1, /* ranged test */ + range = _i / 3, /* looped test */ ntaps; + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_enable_drag_lock(dev->libinput_device); - litest_drain_events(li); - - for (ntaps = 0; ntaps <= range; ntaps++) { - litest_touch_down(dev, 0, 50, 50); - msleep(10); - litest_touch_up(dev, 0); - libinput_dispatch(li); - msleep(10); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + + litest_drain_events(li); + + for (ntaps = 0; ntaps <= range; ntaps++) { + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + msleep(10); + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + + libinput_dispatch(li); + msleep(10); } libinput_dispatch(li); @@ -571,7 +996,7 @@ for (ntaps = 0; ntaps < range; ntaps++) { event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -579,7 +1004,7 @@ event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -589,7 +1014,7 @@ event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -604,14 +1029,14 @@ litest_touch_down(dev, 0, 70, 50); litest_touch_up(dev, 0); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_empty_queue(li); } END_TEST -START_TEST(touchpad_1fg_multitap_n_drag_tap_click) +START_TEST(touchpad_multitap_n_drag_tap_click) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; @@ -619,18 +1044,60 @@ struct libinput_event_pointer *ptrev; uint32_t oldtime = 0, curtime; - int range = _i, /* looped test */ + int nfingers = (_i % 3) + 1, /* ranged test */ + range = _i / 3, /* looped test */ ntaps; + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_enable_drag_lock(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); for (ntaps = 0; ntaps <= range; ntaps++) { - litest_touch_down(dev, 0, 50, 50); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } msleep(10); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + libinput_dispatch(li); msleep(10); } @@ -645,7 +1112,7 @@ for (ntaps = 0; ntaps < range; ntaps++) { event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -653,7 +1120,7 @@ event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -663,7 +1130,7 @@ event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -681,7 +1148,7 @@ libinput_dispatch(li); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); /* the physical click */ @@ -697,25 +1164,66 @@ } END_TEST -START_TEST(touchpad_1fg_tap_n_drag) +START_TEST(touchpad_tap_n_drag) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct libinput_event *event; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_disable_drag_lock(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } litest_touch_down(dev, 0, 50, 50); litest_touch_move_to(dev, 0, 50, 50, 80, 80, 20); libinput_dispatch(li); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_PRESSED); libinput_dispatch(li); @@ -732,7 +1240,7 @@ event = libinput_get_event(li); ck_assert_notnull(event); litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); libinput_event_destroy(event); @@ -740,25 +1248,66 @@ } END_TEST -START_TEST(touchpad_1fg_tap_n_drag_draglock) +START_TEST(touchpad_tap_n_drag_draglock) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_enable_drag_lock(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } litest_touch_down(dev, 0, 50, 50); litest_touch_move_to(dev, 0, 50, 50, 80, 80, 20); litest_touch_up(dev, 0); libinput_dispatch(li); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_PRESSED); libinput_dispatch(li); @@ -774,32 +1323,77 @@ litest_timeout_tap(); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_empty_queue(li); } END_TEST -START_TEST(touchpad_1fg_tap_n_drag_draglock_tap) +START_TEST(touchpad_tap_n_drag_draglock_tap) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + int nfingers = (_i % 3) + 1, /* ranged test */ + nfingers2 = _i / 3; + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; + + if (nfingers2 > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_enable_drag_lock(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } litest_touch_down(dev, 0, 50, 50); litest_touch_move_to(dev, 0, 50, 50, 80, 80, 20); litest_touch_up(dev, 0); libinput_dispatch(li); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_PRESSED); libinput_dispatch(li); @@ -813,33 +1407,97 @@ litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); litest_touch_up(dev, 0); - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); - litest_assert_button_event(li, BTN_LEFT, + switch (nfingers2) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers2) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_empty_queue(li); } END_TEST -START_TEST(touchpad_1fg_tap_n_drag_draglock_tap_click) +START_TEST(touchpad_tap_n_drag_draglock_tap_click) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_enable_drag_lock(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } litest_touch_down(dev, 0, 50, 50); litest_touch_move_to(dev, 0, 50, 50, 80, 80, 20); libinput_dispatch(li); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_PRESSED); libinput_dispatch(li); @@ -852,7 +1510,7 @@ litest_button_click(dev, BTN_LEFT, false); libinput_dispatch(li); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_RELEASED); /* the physical click */ @@ -868,23 +1526,64 @@ } END_TEST -START_TEST(touchpad_1fg_tap_n_drag_draglock_timeout) +START_TEST(touchpad_tap_n_drag_draglock_timeout) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_enable_drag_lock(dev->libinput_device); - litest_drain_events(li); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + litest_drain_events(li); + + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } litest_touch_down(dev, 0, 50, 50); libinput_dispatch(li); litest_timeout_tap(); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_empty_queue(li); @@ -892,126 +1591,638 @@ libinput_dispatch(li); litest_timeout_tapndrag(); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, + LIBINPUT_BUTTON_STATE_RELEASED); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(touchpad_tap_n_drag_2fg) +{ + /* Test: tap with 1-3 fingers (multiple times), then a 1fg move + * followed by a second finger down and *both* fingers moving. + * This is a special behavior catering for the use-case when a user + * needs a second finger down to "hold" the drag while resetting the + * first finger. + * Even though it's 2fg movement, we expect it to behave like a 1fg + * drag. This behavior may change in the future. + */ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; + + litest_enable_tap(dev->libinput_device); + litest_disable_drag_lock(dev->libinput_device); + + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + + litest_drain_events(li); + + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + litest_touch_down(dev, 0, 30, 70); + libinput_dispatch(li); + litest_timeout_tap(); + libinput_dispatch(li); + litest_touch_down(dev, 1, 80, 70); + litest_touch_move_to(dev, 0, 30, 70, 30, 30, 10); + libinput_dispatch(li); + + litest_assert_button_event(li, button, + LIBINPUT_BUTTON_STATE_PRESSED); + + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + litest_touch_up(dev, 0); + litest_touch_up(dev, 1); + + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_empty_queue(li); } END_TEST -START_TEST(touchpad_2fg_tap_n_drag) +START_TEST(touchpad_tap_n_drag_2fg_scroll) { + /* Test: tap with 1-3 fingers, then immediate 2fg scroll. + * We expect this to be a tap followed by a scroll. + */ struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; + if (nfingers > litest_slot_count(dev)) + return; + + litest_enable_2fg_scroll(dev); litest_enable_tap(dev->libinput_device); litest_disable_drag_lock(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + + litest_drain_events(li); + + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + + /* Two fingers down + move to trigger scrolling */ + libinput_dispatch(li); + litest_touch_down(dev, 0, 50, 50); + litest_touch_down(dev, 1, 70, 50); + libinput_dispatch(li); + litest_touch_move_two_touches(dev, 50, 50, 70, 50, 0, 20, 10); + libinput_dispatch(li); + litest_touch_up(dev, 0); + litest_touch_up(dev, 1); + libinput_dispatch(li); + + litest_assert_button_event(li, button, + LIBINPUT_BUTTON_STATE_PRESSED); + litest_assert_button_event(li, button, + LIBINPUT_BUTTON_STATE_RELEASED); + + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(touchpad_tap_n_drag_draglock_2fg_scroll) +{ + /* Test: tap with 1-3 fingers, trigger drag-lock, + * then immediate 2fg scroll. + * We expect this to be a tap-and-drag followed by a scroll. + */ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; + + litest_enable_2fg_scroll(dev); + litest_enable_tap(dev->libinput_device); + litest_enable_drag_lock(dev->libinput_device); + + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + + litest_drain_events(li); + + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + + /* Drag with one finger */ + litest_touch_down(dev, 0, 50, 50); + litest_touch_move_to(dev, 0, 50, 50, 50, 70, 10); + + litest_assert_button_event(li, button, + LIBINPUT_BUTTON_STATE_PRESSED); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + /* Release finger to trigger drag-lock */ + litest_touch_up(dev, 0); + + /* Two fingers down + move to trigger scrolling */ + libinput_dispatch(li); + litest_touch_down(dev, 0, 50, 50); + litest_touch_down(dev, 1, 70, 50); + libinput_dispatch(li); + litest_touch_move_two_touches(dev, 50, 50, 70, 50, 0, 20, 10); + libinput_dispatch(li); + litest_touch_up(dev, 0); + litest_touch_up(dev, 1); + libinput_dispatch(li); + + litest_assert_button_event(li, button, + LIBINPUT_BUTTON_STATE_RELEASED); + + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(touchpad_tap_n_drag_3fg_btntool) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; + + if (litest_slot_count(dev) > 2 || + !libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_TRIPLETAP)) + return; + + litest_enable_tap(dev->libinput_device); + + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + + litest_drain_events(li); + + switch (nfingers) { + case 3: + litest_touch_down(dev, 0, 40, 30); + litest_touch_down(dev, 1, 50, 30); + litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 1); + litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + break; + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 0); + litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + litest_touch_down(dev, 0, 30, 70); + libinput_dispatch(li); + litest_timeout_tap(); + libinput_dispatch(li); + litest_touch_down(dev, 1, 80, 90); + litest_touch_move_to(dev, 0, 30, 70, 30, 30, 5); + libinput_dispatch(li); + + litest_assert_button_event(li, button, + LIBINPUT_BUTTON_STATE_PRESSED); + + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + /* Putting down a third finger should end the drag */ + litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 1); + litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + litest_assert_button_event(li, button, + LIBINPUT_BUTTON_STATE_RELEASED); + + /* Releasing the fingers should not cause any events */ + litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 0); + litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_touch_up(dev, 1); + litest_touch_up(dev, 0); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(touchpad_tap_n_drag_3fg) +{ + /* Test: tap with 1-3 fingers (multiple times), then a 1fg move + * followed by a second finger down and *both* fingers moving. + * This is a special behavior catering for the use-case when a user + * needs a second finger down to "hold" the drag while resetting the + * first finger. + * Even though it's 2fg movement, we expect it to behave like a 1fg + * drag. This behavior may change in the future. + */ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; + + if (litest_slot_count(dev) < 3) + return; + + litest_enable_tap(dev->libinput_device); + + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + /* 1fg down triggers the drag */ litest_touch_down(dev, 0, 30, 70); - litest_touch_up(dev, 0); - litest_touch_down(dev, 0, 30, 70); - litest_touch_down(dev, 1, 80, 70); + libinput_dispatch(li); + litest_timeout_tap(); + libinput_dispatch(li); + /* 2fg is allowed now without cancelling the drag */ + litest_touch_down(dev, 1, 80, 90); litest_touch_move_to(dev, 0, 30, 70, 30, 30, 10); libinput_dispatch(li); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); - litest_touch_up(dev, 0); - litest_touch_up(dev, 1); + /* Putting down a third finger should end the drag */ + litest_touch_down(dev, 2, 50, 50); - litest_assert_button_event(li, BTN_LEFT, + libinput_dispatch(li); + + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_RELEASED); + /* Releasing the fingers should not cause any events */ + litest_touch_up(dev, 2); + litest_touch_up(dev, 1); + litest_touch_up(dev, 0); + litest_assert_empty_queue(li); } END_TEST -START_TEST(touchpad_2fg_tap_n_drag_3fg_btntool) +START_TEST(touchpad_tap_n_drag_3fg_swipe) { + /* Test: tap with 1-3 fingers, then immediate 3fg swipe. + * We expect this to be a tap followed by a swipe. + */ struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; - if (litest_slot_count(dev) > 2 || - !libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_TRIPLETAP)) + if (litest_slot_count(dev) < 3) return; litest_enable_tap(dev->libinput_device); - litest_drain_events(li); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } - litest_touch_down(dev, 0, 30, 70); - litest_touch_up(dev, 0); - litest_touch_down(dev, 0, 30, 70); - litest_touch_down(dev, 1, 80, 90); - litest_touch_move_to(dev, 0, 30, 70, 30, 30, 5); - libinput_dispatch(li); + litest_drain_events(li); - litest_assert_button_event(li, BTN_LEFT, - LIBINPUT_BUTTON_STATE_PRESSED); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } - litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); - /* Putting down a third finger should end the drag */ - litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 1); - litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0); - litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_touch_down(dev, 0, 30, 50); + litest_touch_down(dev, 1, 50, 50); + litest_touch_down(dev, 2, 80, 50); + libinput_dispatch(li); + litest_touch_move_three_touches(dev, + 30, 50, + 50, 50, + 80, 50, + 0, 20, + 10); libinput_dispatch(li); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, + LIBINPUT_BUTTON_STATE_PRESSED); + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_RELEASED); - /* Releasing the fingers should not cause any events */ - litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 0); - litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 1); - litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_assert_gesture_event(li, + LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN, + 3); + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE); + + litest_touch_up(dev, 2); litest_touch_up(dev, 1); litest_touch_up(dev, 0); + litest_assert_gesture_event(li, + LIBINPUT_EVENT_GESTURE_SWIPE_END, + 3); litest_assert_empty_queue(li); } END_TEST -START_TEST(touchpad_2fg_tap_n_drag_3fg) +START_TEST(touchpad_tap_n_drag_draglock_3fg_swipe) { + /* Test: tap with 1-3 fingers, trigger drag-lock, + * then immediate 3fg swipe. + * We expect this to be a tap-and-drag followed by a swipe. + */ struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; if (litest_slot_count(dev) < 3) return; litest_enable_tap(dev->libinput_device); + litest_enable_drag_lock(dev->libinput_device); + + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } litest_drain_events(li); - litest_touch_down(dev, 0, 30, 70); - litest_touch_up(dev, 0); - litest_touch_down(dev, 0, 30, 70); - litest_touch_down(dev, 1, 80, 90); - litest_touch_move_to(dev, 0, 30, 70, 30, 30, 10); - libinput_dispatch(li); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } - litest_assert_button_event(li, BTN_LEFT, - LIBINPUT_BUTTON_STATE_PRESSED); + /* Drag with one finger */ + litest_touch_down(dev, 0, 50, 50); + litest_touch_move_to(dev, 0, 50, 50, 50, 70, 10); + litest_assert_button_event(li, button, + LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); - /* Putting down a third finger should end the drag */ - litest_touch_down(dev, 2, 50, 50); + /* Release finger to trigger drag-lock */ + litest_touch_up(dev, 0); + litest_touch_down(dev, 0, 30, 50); + litest_touch_down(dev, 1, 50, 50); + litest_touch_down(dev, 2, 80, 50); + libinput_dispatch(li); + litest_touch_move_three_touches(dev, + 30, 50, + 50, 50, + 80, 50, + 0, 20, + 10); libinput_dispatch(li); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_RELEASED); - /* Releasing the fingers should not cause any events */ + litest_assert_gesture_event(li, + LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN, + 3); + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE); + litest_touch_up(dev, 2); litest_touch_up(dev, 1); litest_touch_up(dev, 0); + litest_assert_gesture_event(li, + LIBINPUT_EVENT_GESTURE_SWIPE_END, + 3); litest_assert_empty_queue(li); } @@ -1049,6 +2260,8 @@ litest_touch_up(dev, 1); libinput_dispatch(li); + litest_timeout_tap(); + libinput_dispatch(li); ev = libinput_get_event(li); ptrev = litest_is_button_event(ev, @@ -1101,6 +2314,8 @@ litest_touch_up(dev, 0); libinput_dispatch(li); + litest_timeout_tap(); + libinput_dispatch(li); ev = libinput_get_event(li); ptrev = litest_is_button_event(ev, @@ -1437,19 +2652,60 @@ } END_TEST -START_TEST(touchpad_1fg_double_tap_click) +START_TEST(touchpad_double_tap_click) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(dev->libinput); - /* one finger down, up, down, button click, finger up - -> two button left event pairs */ - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + /* finger(s) down, up, one finger down, button click, finger up + -> two button event pairs */ + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } litest_touch_down(dev, 0, 50, 50); litest_event(dev, EV_KEY, BTN_LEFT, 1); litest_event(dev, EV_SYN, SYN_REPORT, 0); @@ -1459,9 +2715,9 @@ libinput_dispatch(li); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_PRESSED); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED); @@ -1472,23 +2728,65 @@ } END_TEST -START_TEST(touchpad_1fg_tap_n_drag_click) +START_TEST(touchpad_tap_n_drag_click) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; + litest_enable_tap(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(dev->libinput); - /* one finger down, up, down, move, button click, finger up - -> two button left event pairs, motion allowed */ - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + /* finger(s) down, up, one finger down, move, button click, finger up + -> two button event pairs, motion allowed */ + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } litest_touch_down(dev, 0, 50, 50); litest_touch_move_to(dev, 0, 50, 50, 80, 50, 10); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); @@ -1496,7 +2794,7 @@ litest_event(dev, EV_KEY, BTN_LEFT, 1); litest_event(dev, EV_SYN, SYN_REPORT, 0); - litest_assert_button_event(li, BTN_LEFT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED); @@ -1558,6 +2856,8 @@ litest_touch_up(dev, (i + 0) % 3); libinput_dispatch(li); + litest_timeout_tap(); + libinput_dispatch(li); ev = libinput_get_event(li); ptrev = litest_is_button_event(ev, @@ -1610,6 +2910,8 @@ litest_touch_up(dev, 2); libinput_dispatch(li); + litest_timeout_tap(); + libinput_dispatch(li); for (i = 0; i < 2; i++) { ev = libinput_get_event(li); @@ -2590,14 +3892,57 @@ { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_disable_tap_drag(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + /* lift fingers up */ + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + libinput_dispatch(li); litest_touch_down(dev, 0, 50, 50); litest_touch_move_to(dev, 0, 50, 50, 90, 90, 10); @@ -2605,10 +3950,10 @@ libinput_dispatch(li); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); @@ -2623,28 +3968,69 @@ struct libinput_event *ev; struct libinput_event_pointer *ptrev; uint64_t press_time, release_time; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_disable_tap_drag(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); - litest_touch_down(dev, 0, 50, 50); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } msleep(10); /* to force a time difference */ libinput_dispatch(li); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } libinput_dispatch(li); ev = libinput_get_event(li); ptrev = litest_is_button_event(ev, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); press_time = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(ev); ev = libinput_get_event(li); ptrev = litest_is_button_event(ev, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); release_time = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(ev); @@ -2661,17 +4047,59 @@ struct libinput_event_pointer *ptrev; uint32_t oldtime = 0, curtime; - int range = _i, /* looped test */ + int nfingers = (_i % 3) + 1, /* ranged test */ + range = _i / 3, /* looped test */ ntaps; + unsigned int button = 0; + + if (nfingers > litest_slot_count(dev)) + return; litest_enable_tap(dev->libinput_device); litest_disable_tap_drag(dev->libinput_device); + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); for (ntaps = 0; ntaps <= range; ntaps++) { - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + libinput_dispatch(li); msleep(10); } @@ -2684,7 +4112,7 @@ for (ntaps = 0; ntaps <= range; ntaps++) { event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -2692,7 +4120,7 @@ event = libinput_get_event(li); ptrev = litest_is_button_event(event, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); curtime = libinput_event_pointer_get_time(ptrev); libinput_event_destroy(event); @@ -2765,8 +4193,12 @@ { struct libevdev *evdev = dev->evdev; + if (dev->which == LITEST_SYNAPTICS_PRESSUREPAD) + return false; + if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_PRESSURE)) - return true; + return libevdev_get_abs_resolution(evdev, + ABS_MT_PRESSURE) == 0; return false; } @@ -2892,21 +4324,63 @@ { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; if (!touchpad_has_palm_pressure(dev)) return; + if (nfingers > litest_slot_count(dev)) + return; + litest_enable_tap(dev->libinput_device); + + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); /* tap + palm down */ - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } libinput_dispatch(li); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); litest_touch_down(dev, 0, 50, 50); @@ -2918,7 +4392,7 @@ libinput_dispatch(li); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_empty_queue(li); @@ -2933,21 +4407,63 @@ { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; if (!touchpad_has_palm_pressure(dev)) return; + if (nfingers > litest_slot_count(dev)) + return; + litest_enable_tap(dev->libinput_device); + + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); /* tap + palm down */ - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } libinput_dispatch(li); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); litest_touch_down_extended(dev, 0, 50, 50, axes); @@ -2959,14 +4475,14 @@ libinput_dispatch(li); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_empty_queue(li); } END_TEST -START_TEST(touchpad_tap_palm_on_tapped_2fg) +START_TEST(touchpad_tap_palm_on_tapped_doubletap) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; @@ -2974,21 +4490,81 @@ { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; + int nfingers = (_i % 3) + 1, /* ranged test */ + nfingers2 = _i / 3; + unsigned int button = 0, + button2 = 0; if (!touchpad_has_palm_pressure(dev)) return; + if (nfingers > litest_slot_count(dev)) + return; + + if (nfingers2 + 1 > litest_slot_count(dev)) + return; + litest_enable_tap(dev->libinput_device); + + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + switch (nfingers2) { + case 1: + button2 = BTN_LEFT; + break; + case 2: + button2 = BTN_RIGHT; + break; + case 3: + button2 = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); - /* tap + palm down + tap with second finger */ + /* tap + palm down + tap with additional finger(s) */ - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } libinput_dispatch(li); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); litest_touch_down(dev, 0, 50, 50); @@ -2996,21 +4572,43 @@ libinput_dispatch(li); - litest_touch_down(dev, 1, 50, 50); - litest_touch_up(dev, 1); + switch (nfingers2) { + case 3: + litest_touch_down(dev, 3, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 2, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 1, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers2) { + case 3: + litest_touch_up(dev, 3); + /* fallthrough */ + case 2: + litest_touch_up(dev, 2); + /* fallthrough */ + case 1: + litest_touch_up(dev, 1); + /* fallthrough */ + break; + } libinput_dispatch(li); litest_timeout_tap(); libinput_dispatch(li); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_button_event(li, - BTN_LEFT, + button2, LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_button_event(li, - BTN_LEFT, + button2, LIBINPUT_BUTTON_STATE_RELEASED); litest_touch_up(dev, 0); @@ -3026,21 +4624,63 @@ { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; if (!touchpad_has_palm_pressure(dev)) return; + if (nfingers > litest_slot_count(dev)) + return; + litest_enable_tap(dev->libinput_device); + + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); /* tap + finger down (->drag), finger turns into palm */ - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } libinput_dispatch(li); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); litest_touch_down(dev, 0, 50, 50); @@ -3052,7 +4692,7 @@ libinput_dispatch(li); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); litest_touch_up(dev, 0); @@ -3068,27 +4708,71 @@ { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; - int which = _i; /* ranged test */ - int this = which % 2, - other = (which + 1) % 2; + int this = _i % 2, /* ranged test */ + other = (_i + 1) % 2, + nfingers = _i / 2; + unsigned int button = 0; if (!touchpad_has_palm_pressure(dev)) return; + if (nfingers > litest_slot_count(dev)) + return; + litest_enable_tap(dev->libinput_device); + + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); /* tap + finger down, 2nd finger down, finger turns to palm */ - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } libinput_dispatch(li); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); litest_touch_down(dev, this, 50, 50); + libinput_dispatch(li); + litest_timeout_tap(); + libinput_dispatch(li); litest_touch_down(dev, other, 60, 50); libinput_dispatch(li); @@ -3101,7 +4785,7 @@ litest_touch_up(dev, other); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); litest_touch_up(dev, this); @@ -3337,20 +5021,62 @@ { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; + int nfingers = _i; /* ranged test */ + unsigned int button = 0; if (!touchpad_has_palm_pressure(dev)) return; + if (nfingers > litest_slot_count(dev)) + return; + litest_enable_tap(dev->libinput_device); + + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } libinput_dispatch(li); libinput_dispatch(li); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); litest_touch_down(dev, 0, 50, 50); @@ -3360,7 +5086,7 @@ litest_timeout_tap(); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); litest_assert_empty_queue(li); @@ -3375,18 +5101,61 @@ { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; - int range = _i, /* ranged test */ + int nfingers = (_i % 3) + 1, /* ranged test */ + range = _i / 3, /* looped test */ ntaps; + unsigned int button = 0; if (!touchpad_has_palm_pressure(dev)) return; + if (nfingers > litest_slot_count(dev)) + return; + litest_enable_tap(dev->libinput_device); + + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); for (ntaps = 0; ntaps <= range; ntaps++) { - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + libinput_dispatch(li); msleep(10); } @@ -3400,10 +5169,10 @@ for (ntaps = 0; ntaps <= range; ntaps++) { litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); } @@ -3419,18 +5188,61 @@ { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; - int range = _i, /* ranged test */ + int nfingers = (_i % 3) + 1, /* ranged test */ + range = _i / 3, /* looped test */ ntaps; + unsigned int button = 0; if (!touchpad_has_palm_pressure(dev)) return; + if (nfingers > litest_slot_count(dev)) + return; + litest_enable_tap(dev->libinput_device); + + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); for (ntaps = 0; ntaps <= range; ntaps++) { - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + libinput_dispatch(li); msleep(10); } @@ -3443,10 +5255,10 @@ for (ntaps = 0; ntaps <= range; ntaps++) { litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); } @@ -3462,18 +5274,61 @@ { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; - int range = _i, /* ranged test */ + int nfingers = (_i % 3) + 1, /* ranged test */ + range = _i / 3, /* looped test */ ntaps; + unsigned int button = 0; if (!touchpad_has_palm_pressure(dev)) return; + if (nfingers + 1 > litest_slot_count(dev)) + return; + litest_enable_tap(dev->libinput_device); + + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); for (ntaps = 0; ntaps <= range; ntaps++) { - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + libinput_dispatch(li); msleep(10); } @@ -3484,8 +5339,31 @@ /* keep palm finger down */ for (ntaps = 0; ntaps <= range; ntaps++) { - litest_touch_down(dev, 1, 50, 50); - litest_touch_up(dev, 1); + switch (nfingers) { + case 3: + litest_touch_down(dev, 3, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 2, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 1, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 3); + /* fallthrough */ + case 2: + litest_touch_up(dev, 2); + /* fallthrough */ + case 1: + litest_touch_up(dev, 1); + /* fallthrough */ + break; + } + libinput_dispatch(li); msleep(10); } @@ -3495,10 +5373,10 @@ for (ntaps = 0; ntaps <= 2 * range + 1; ntaps++) { litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); } @@ -3515,18 +5393,61 @@ { ABS_MT_PRESSURE, 75 }, { -1, 0 } }; - int range = _i, /* ranged test */ + int nfingers = (_i % 3) + 1, /* ranged test */ + range = _i / 3, /* looped test */ ntaps; + unsigned int button = 0; if (!touchpad_has_palm_pressure(dev)) return; + if (nfingers > litest_slot_count(dev)) + return; + litest_enable_tap(dev->libinput_device); + + switch (nfingers) { + case 1: + button = BTN_LEFT; + break; + case 2: + button = BTN_RIGHT; + break; + case 3: + button = BTN_MIDDLE; + break; + default: + abort(); + } + litest_drain_events(li); for (ntaps = 0; ntaps <= range; ntaps++) { - litest_touch_down(dev, 0, 50, 50); - litest_touch_up(dev, 0); + switch (nfingers) { + case 3: + litest_touch_down(dev, 2, 60, 30); + /* fallthrough */ + case 2: + litest_touch_down(dev, 1, 50, 30); + /* fallthrough */ + case 1: + litest_touch_down(dev, 0, 40, 30); + /* fallthrough */ + break; + } + switch (nfingers) { + case 3: + litest_touch_up(dev, 2); + /* fallthrough */ + case 2: + litest_touch_up(dev, 1); + /* fallthrough */ + case 1: + litest_touch_up(dev, 0); + /* fallthrough */ + break; + } + libinput_dispatch(li); msleep(10); } @@ -3542,10 +5463,10 @@ for (ntaps = 0; ntaps <= range; ntaps++) { litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_button_event(li, - BTN_LEFT, + button, LIBINPUT_BUTTON_STATE_RELEASED); } @@ -3690,118 +5611,126 @@ TEST_COLLECTION(touchpad_tap) { - struct range any_tap_range = {1, 4}; - struct range multitap_range = {3, 5}; + struct range any_tap_range = {3, 12}; + struct range multitap_range = {9, 15}; struct range tap_map_range = { LIBINPUT_CONFIG_TAP_MAP_LRM, LIBINPUT_CONFIG_TAP_MAP_LMR + 1 }; struct range range_2fg = {0, 2}; + struct range range_2fg_multifinger_tap = {2, 8}; struct range range_3fg = {0, 3}; struct range range_4fg = {0, 4}; struct range range_multifinger = {2, 5}; + struct range range_multifinger_tap = {1, 4}; + struct range range_multifinger_doubletap = {3, 12}; - litest_add("tap:1fg", touchpad_1fg_tap, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:1fg", touchpad_1fg_doubletap, LITEST_TOUCHPAD, LITEST_ANY); - litest_add_ranged("tap:1fg", touchpad_1fg_tap_drag_high_delay, LITEST_TOUCHPAD, LITEST_ANY, &any_tap_range); - litest_add_ranged("tap:1fg", touchpad_1fg_multitap, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); - litest_add_ranged("tap:1fg", touchpad_1fg_multitap_timeout, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); - litest_add_ranged("tap:1fg", touchpad_1fg_multitap_n_drag_timeout, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); - litest_add_ranged("tap:1fg", touchpad_1fg_multitap_n_drag_tap, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); - litest_add_ranged("tap:1fg", touchpad_1fg_multitap_n_drag_move, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); - litest_add_ranged("tap:1fg", touchpad_1fg_multitap_n_drag_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &multitap_range); - litest_add_ranged("tap:1fg", touchpad_1fg_multitap_n_drag_click, LITEST_CLICKPAD, LITEST_ANY, &multitap_range); - litest_add("tap:1fg", touchpad_1fg_tap_n_drag, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:1fg", touchpad_1fg_tap_n_drag_draglock, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:1fg", touchpad_1fg_tap_n_drag_draglock_tap, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:1fg", touchpad_1fg_tap_n_drag_draglock_timeout, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:2fg", touchpad_2fg_tap_n_drag, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:2fg", touchpad_2fg_tap_n_drag_3fg_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD); - litest_add("tap:2fg", touchpad_2fg_tap_n_drag_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add_ranged("tap:2fg", touchpad_2fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT, &tap_map_range); - litest_add_ranged("tap:2fg", touchpad_2fg_tap_inverted, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &tap_map_range); - litest_add("tap:2fg", touchpad_2fg_tap_move_on_release, LITEST_TOUCHPAD|LITEST_SEMI_MT, LITEST_SINGLE_TOUCH); - litest_add("tap:2fg", touchpad_2fg_tap_n_hold_first, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:2fg", touchpad_2fg_tap_n_hold_second, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:2fg", touchpad_2fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("tap:2fg", touchpad_1fg_tap_click, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_CLICKPAD); - litest_add("tap:2fg", touchpad_2fg_tap_click, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_SINGLE_TOUCH|LITEST_CLICKPAD); - - litest_add("tap:2fg", touchpad_2fg_tap_click_apple, LITEST_APPLE_CLICKPAD, LITEST_ANY); - litest_add("tap:2fg", touchpad_no_2fg_tap_after_move, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("tap:2fg", touchpad_no_2fg_tap_after_timeout, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("tap:2fg", touchpad_no_first_fg_tap_after_move, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add_ranged("tap:3fg", touchpad_3fg_tap_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &tap_map_range); - litest_add_ranged("tap:3fg", touchpad_3fg_tap_btntool_inverted, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &tap_map_range); - litest_add_ranged("tap:3fg", touchpad_3fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &tap_map_range); - litest_add("tap:3fg", touchpad_3fg_tap_tap_again, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:3fg", touchpad_3fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:3fg", touchpad_3fg_tap_hover_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:3fg", touchpad_3fg_tap_pressure_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add_for_device("tap:3fg", touchpad_3fg_tap_btntool_pointerjump, LITEST_SYNAPTICS_TOPBUTTONPAD); - litest_add_for_device("tap:3fg", touchpad_3fg_tap_slot_release_btntool, LITEST_SYNAPTICS_TOPBUTTONPAD); - litest_add("tap:3fg", touchpad_3fg_tap_after_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - - litest_add("tap:4fg", touchpad_4fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("tap:4fg", touchpad_4fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("tap:5fg", touchpad_5fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("tap:5fg", touchpad_5fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - - litest_add_ranged("tap:multifinger", touchpad_move_after_touch, LITEST_TOUCHPAD, LITEST_ANY, &range_multifinger); + litest_add(touchpad_1fg_tap, LITEST_TOUCHPAD, LITEST_ANY); + litest_add_ranged(touchpad_doubletap, LITEST_TOUCHPAD, LITEST_ANY, &range_multifinger_doubletap); + litest_add_ranged(touchpad_multitap, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); + litest_add_ranged(touchpad_multitap_timeout, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); + litest_add_ranged(touchpad_multitap_n_drag_timeout, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); + litest_add_ranged(touchpad_multitap_n_drag_high_delay, LITEST_TOUCHPAD, LITEST_ANY, &any_tap_range); + litest_add_ranged(touchpad_multitap_n_drag_tap, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); + litest_add_ranged(touchpad_multitap_n_drag_move, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); + litest_add_ranged(touchpad_multitap_n_drag_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &multitap_range); + litest_add_ranged(touchpad_multitap_n_drag_click, LITEST_CLICKPAD, LITEST_ANY, &multitap_range); + litest_add_ranged(touchpad_2fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT, &tap_map_range); + litest_add_ranged(touchpad_2fg_tap_inverted, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &tap_map_range); + litest_add(touchpad_2fg_tap_move_on_release, LITEST_TOUCHPAD|LITEST_SEMI_MT, LITEST_SINGLE_TOUCH); + litest_add(touchpad_2fg_tap_n_hold_first, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_2fg_tap_n_hold_second, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_2fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add(touchpad_1fg_tap_click, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_CLICKPAD); + litest_add(touchpad_2fg_tap_click, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_SINGLE_TOUCH|LITEST_CLICKPAD); + + litest_add(touchpad_2fg_tap_click_apple, LITEST_APPLE_CLICKPAD, LITEST_ANY); + litest_add(touchpad_no_2fg_tap_after_move, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add(touchpad_no_2fg_tap_after_timeout, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add(touchpad_no_first_fg_tap_after_move, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add_ranged(touchpad_3fg_tap_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &tap_map_range); + litest_add_ranged(touchpad_3fg_tap_btntool_inverted, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &tap_map_range); + litest_add_ranged(touchpad_3fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &tap_map_range); + litest_add(touchpad_3fg_tap_tap_again, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_3fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_3fg_tap_hover_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add(touchpad_3fg_tap_pressure_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add_for_device(touchpad_3fg_tap_btntool_pointerjump, LITEST_SYNAPTICS_TOPBUTTONPAD); + litest_add_for_device(touchpad_3fg_tap_slot_release_btntool, LITEST_SYNAPTICS_TOPBUTTONPAD); + litest_add(touchpad_3fg_tap_after_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + + litest_add(touchpad_4fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add(touchpad_4fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add(touchpad_5fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add(touchpad_5fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + + litest_add_ranged(touchpad_move_after_touch, LITEST_TOUCHPAD, LITEST_ANY, &range_multifinger); + + litest_add_ranged(touchpad_tap_n_drag, LITEST_TOUCHPAD, LITEST_ANY, &range_multifinger_tap); + litest_add_ranged(touchpad_tap_n_drag_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_multifinger_tap); + litest_add_ranged(touchpad_tap_n_drag_2fg_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_multifinger_tap); + litest_add_ranged(touchpad_tap_n_drag_draglock_2fg_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_multifinger_tap); + litest_add_ranged(touchpad_tap_n_drag_3fg_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD, &range_multifinger_tap); + litest_add_ranged(touchpad_tap_n_drag_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_multifinger_tap); + litest_add_ranged(touchpad_tap_n_drag_3fg_swipe, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_multifinger_tap); + litest_add_ranged(touchpad_tap_n_drag_draglock_3fg_swipe, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_multifinger_tap); + litest_add_ranged(touchpad_tap_n_drag_draglock, LITEST_TOUCHPAD, LITEST_ANY, &range_multifinger_tap); + litest_add_ranged(touchpad_tap_n_drag_draglock_tap, LITEST_TOUCHPAD, LITEST_ANY, &range_multifinger_doubletap); + litest_add_ranged(touchpad_tap_n_drag_draglock_timeout, LITEST_TOUCHPAD, LITEST_ANY, &range_multifinger_tap); /* Real buttons don't interfere with tapping, so don't run those for pads with buttons */ - litest_add("tap:1fg", touchpad_1fg_double_tap_click, LITEST_CLICKPAD, LITEST_ANY); - litest_add("tap:1fg", touchpad_1fg_tap_n_drag_click, LITEST_CLICKPAD, LITEST_ANY); - litest_add_ranged("tap:1fg", touchpad_1fg_multitap_n_drag_tap_click, LITEST_CLICKPAD, LITEST_ANY, &multitap_range); - litest_add("tap:1fg", touchpad_1fg_tap_n_drag_draglock_tap_click, LITEST_CLICKPAD, LITEST_ANY); - - litest_add("tap:config", touchpad_tap_default_disabled, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_ANY); - litest_add("tap:config", touchpad_tap_default_enabled, LITEST_TOUCHPAD, LITEST_BUTTON); - litest_add("tap:config", touchpad_tap_invalid, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:config", touchpad_tap_is_available, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:config", touchpad_tap_is_not_available, LITEST_ANY, LITEST_TOUCHPAD); - - litest_add("tap:config", touchpad_tap_default_map, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:config", touchpad_tap_map_unsupported, LITEST_ANY, LITEST_TOUCHPAD); - litest_add("tap:config", touchpad_tap_set_map, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:config", touchpad_tap_set_map_no_tapping, LITEST_ANY, LITEST_TOUCHPAD); - litest_add("tap:config", touchpad_tap_get_map_no_tapping, LITEST_ANY, LITEST_TOUCHPAD); - litest_add("tap:config", touchpad_tap_map_delayed, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - - litest_add("tap:1fg", clickpad_1fg_tap_click, LITEST_CLICKPAD, LITEST_ANY); - litest_add("tap:2fg", clickpad_2fg_tap_click, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD); - - litest_add("tap:draglock", touchpad_drag_lock_default_disabled, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:draglock", touchpad_drag_lock_default_unavailable, LITEST_ANY, LITEST_TOUCHPAD); - - litest_add("tap:drag", touchpad_drag_default_disabled, LITEST_ANY, LITEST_TOUCHPAD); - litest_add("tap:drag", touchpad_drag_default_enabled, LITEST_TOUCHPAD, LITEST_BUTTON); - litest_add("tap:drag", touchpad_drag_config_invalid, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:drag", touchpad_drag_config_unsupported, LITEST_ANY, LITEST_TOUCHPAD); - litest_add("tap:drag", touchpad_drag_config_enabledisable, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:drag", touchpad_drag_disabled, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:drag", touchpad_drag_disabled_immediate, LITEST_TOUCHPAD, LITEST_ANY); - litest_add_ranged("tap:1fg", touchpad_drag_disabled_multitap_no_drag, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); - - litest_add("tap:palm", touchpad_tap_palm_on_idle, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:palm", touchpad_tap_palm_on_touch, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:palm", touchpad_tap_palm_on_touch_hold_timeout, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:palm", touchpad_tap_palm_on_touch_hold_move, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:palm", touchpad_tap_palm_on_tapped, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:palm", touchpad_tap_palm_on_tapped_palm_down, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:palm", touchpad_tap_palm_on_tapped_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:palm", touchpad_tap_palm_on_drag, LITEST_TOUCHPAD, LITEST_ANY); - litest_add_ranged("tap:palm", touchpad_tap_palm_on_drag_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_2fg); - litest_add_ranged("tap:palm", touchpad_tap_palm_on_touch_2, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_2fg); - litest_add_ranged("tap:palm", touchpad_tap_palm_on_touch_2_retouch, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_2fg); - litest_add_ranged("tap:palm", touchpad_tap_palm_on_touch_3, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_3fg); - litest_add_ranged("tap:palm", touchpad_tap_palm_on_touch_3_retouch, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_3fg); - litest_add_ranged("tap:palm", touchpad_tap_palm_on_touch_4, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_4fg); - litest_add("tap:palm", touchpad_tap_palm_after_tap, LITEST_TOUCHPAD, LITEST_ANY); - litest_add_ranged("tap:palm", touchpad_tap_palm_multitap, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); - litest_add_ranged("tap:palm", touchpad_tap_palm_multitap_timeout, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); - litest_add_ranged("tap:palm", touchpad_tap_palm_multitap_down_again, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &multitap_range); - litest_add_ranged("tap:palm", touchpad_tap_palm_multitap_click, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); - litest_add("tap:palm", touchpad_tap_palm_click_then_tap, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:palm", touchpad_tap_palm_dwt_tap, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:palm", touchpad_tap_palm_3fg_start, LITEST_TOUCHPAD, LITEST_ANY); + litest_add_ranged(touchpad_double_tap_click, LITEST_CLICKPAD, LITEST_ANY, &range_multifinger_tap); + litest_add_ranged(touchpad_tap_n_drag_click, LITEST_CLICKPAD, LITEST_ANY, &range_multifinger_tap); + litest_add_ranged(touchpad_multitap_n_drag_tap_click, LITEST_CLICKPAD, LITEST_ANY, &multitap_range); + litest_add_ranged(touchpad_tap_n_drag_draglock_tap_click, LITEST_CLICKPAD, LITEST_ANY, &range_multifinger_tap); + + litest_add(touchpad_tap_default_disabled, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_ANY); + litest_add(touchpad_tap_default_enabled, LITEST_TOUCHPAD, LITEST_BUTTON); + litest_add(touchpad_tap_invalid, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_tap_is_available, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_tap_is_not_available, LITEST_ANY, LITEST_TOUCHPAD); + + litest_add(touchpad_tap_default_map, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_tap_map_unsupported, LITEST_ANY, LITEST_TOUCHPAD); + litest_add(touchpad_tap_set_map, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_tap_set_map_no_tapping, LITEST_ANY, LITEST_TOUCHPAD); + litest_add(touchpad_tap_get_map_no_tapping, LITEST_ANY, LITEST_TOUCHPAD); + litest_add(touchpad_tap_map_delayed, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + + litest_add(clickpad_1fg_tap_click, LITEST_CLICKPAD, LITEST_ANY); + litest_add(clickpad_2fg_tap_click, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD); + + litest_add(touchpad_drag_lock_default_disabled, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_drag_lock_default_unavailable, LITEST_ANY, LITEST_TOUCHPAD); + + litest_add(touchpad_drag_default_disabled, LITEST_ANY, LITEST_TOUCHPAD); + litest_add(touchpad_drag_default_enabled, LITEST_TOUCHPAD, LITEST_BUTTON); + litest_add(touchpad_drag_config_invalid, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_drag_config_unsupported, LITEST_ANY, LITEST_TOUCHPAD); + litest_add(touchpad_drag_config_enabledisable, LITEST_TOUCHPAD, LITEST_ANY); + litest_add_ranged(touchpad_drag_disabled, LITEST_TOUCHPAD, LITEST_ANY, &range_multifinger_tap); + litest_add_ranged(touchpad_drag_disabled_immediate, LITEST_TOUCHPAD, LITEST_ANY, &range_multifinger_tap); + litest_add_ranged(touchpad_drag_disabled_multitap_no_drag, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); + + litest_add(touchpad_tap_palm_on_idle, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_tap_palm_on_touch, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_tap_palm_on_touch_hold_timeout, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_tap_palm_on_touch_hold_move, LITEST_TOUCHPAD, LITEST_ANY); + litest_add_ranged(touchpad_tap_palm_on_tapped, LITEST_TOUCHPAD, LITEST_ANY, &range_multifinger_tap); + litest_add_ranged(touchpad_tap_palm_on_tapped_palm_down, LITEST_TOUCHPAD, LITEST_ANY, &range_multifinger_tap); + litest_add_ranged(touchpad_tap_palm_on_tapped_doubletap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_multifinger_doubletap); + litest_add_ranged(touchpad_tap_palm_on_drag, LITEST_TOUCHPAD, LITEST_ANY, &range_multifinger_tap); + litest_add_ranged(touchpad_tap_palm_on_drag_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_2fg_multifinger_tap); + litest_add_ranged(touchpad_tap_palm_on_touch_2, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_2fg); + litest_add_ranged(touchpad_tap_palm_on_touch_2_retouch, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_2fg); + litest_add_ranged(touchpad_tap_palm_on_touch_3, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_3fg); + litest_add_ranged(touchpad_tap_palm_on_touch_3_retouch, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_3fg); + litest_add_ranged(touchpad_tap_palm_on_touch_4, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &range_4fg); + litest_add_ranged(touchpad_tap_palm_after_tap, LITEST_TOUCHPAD, LITEST_ANY, &range_multifinger_tap); + litest_add_ranged(touchpad_tap_palm_multitap, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); + litest_add_ranged(touchpad_tap_palm_multitap_timeout, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); + litest_add_ranged(touchpad_tap_palm_multitap_down_again, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &multitap_range); + litest_add_ranged(touchpad_tap_palm_multitap_click, LITEST_CLICKPAD, LITEST_ANY, &multitap_range); + litest_add(touchpad_tap_palm_click_then_tap, LITEST_CLICKPAD, LITEST_ANY); + litest_add(touchpad_tap_palm_dwt_tap, LITEST_TOUCHPAD, LITEST_ANY); + litest_add(touchpad_tap_palm_3fg_start, LITEST_TOUCHPAD, LITEST_ANY); } diff -Nru libinput-1.16.4/test/test-trackball.c libinput-1.17.2/test/test-trackball.c --- libinput-1.16.4/test/test-trackball.c 2020-11-27 01:38:59.396086200 +0000 +++ libinput-1.17.2/test/test-trackball.c 2021-04-30 04:25:41.544076400 +0000 @@ -261,12 +261,12 @@ TEST_COLLECTION(trackball) { - litest_add("trackball:rotation", trackball_rotation_config_defaults, LITEST_TRACKBALL, LITEST_ANY); - litest_add("trackball:rotation", trackball_rotation_config_invalid_range, LITEST_TRACKBALL, LITEST_ANY); - litest_add("trackball:rotation", trackball_rotation_config_no_rotation, LITEST_ANY, LITEST_TRACKBALL); - litest_add("trackball:rotation", trackball_rotation_config_right_angle, LITEST_TRACKBALL, LITEST_ANY); - litest_add("trackball:rotation", trackball_rotation_config_odd_angle, LITEST_TRACKBALL, LITEST_ANY); - litest_add("trackball:rotation", trackball_rotation_x, LITEST_TRACKBALL, LITEST_ANY); - litest_add("trackball:rotation", trackball_rotation_y, LITEST_TRACKBALL, LITEST_ANY); - litest_add("trackball:rotation", trackball_rotation_accel, LITEST_TRACKBALL, LITEST_ANY); + litest_add(trackball_rotation_config_defaults, LITEST_TRACKBALL, LITEST_ANY); + litest_add(trackball_rotation_config_invalid_range, LITEST_TRACKBALL, LITEST_ANY); + litest_add(trackball_rotation_config_no_rotation, LITEST_ANY, LITEST_TRACKBALL); + litest_add(trackball_rotation_config_right_angle, LITEST_TRACKBALL, LITEST_ANY); + litest_add(trackball_rotation_config_odd_angle, LITEST_TRACKBALL, LITEST_ANY); + litest_add(trackball_rotation_x, LITEST_TRACKBALL, LITEST_ANY); + litest_add(trackball_rotation_y, LITEST_TRACKBALL, LITEST_ANY); + litest_add(trackball_rotation_accel, LITEST_TRACKBALL, LITEST_ANY); } diff -Nru libinput-1.16.4/test/test-trackpoint.c libinput-1.17.2/test/test-trackpoint.c --- libinput-1.16.4/test/test-trackpoint.c 2020-11-27 01:38:59.396086200 +0000 +++ libinput-1.17.2/test/test-trackpoint.c 2021-04-30 04:25:41.544076400 +0000 @@ -410,16 +410,16 @@ TEST_COLLECTION(trackpoint) { - litest_add("trackpoint:middlebutton", trackpoint_middlebutton, LITEST_POINTINGSTICK, LITEST_ANY); - litest_add("trackpoint:middlebutton", trackpoint_middlebutton_noscroll, LITEST_POINTINGSTICK, LITEST_ANY); - litest_add("trackpoint:scroll", trackpoint_scroll, LITEST_POINTINGSTICK, LITEST_ANY); - litest_add("trackpoint:scroll", trackpoint_scroll_source, LITEST_POINTINGSTICK, LITEST_ANY); - litest_add("trackpoint:left-handed", trackpoint_topsoftbuttons_left_handed_trackpoint, LITEST_TOPBUTTONPAD, LITEST_ANY); - litest_add("trackpoint:left-handed", trackpoint_topsoftbuttons_left_handed_touchpad, LITEST_TOPBUTTONPAD, LITEST_ANY); - litest_add("trackpoint:left-handed", trackpoint_topsoftbuttons_left_handed_both, LITEST_TOPBUTTONPAD, LITEST_ANY); + litest_add(trackpoint_middlebutton, LITEST_POINTINGSTICK, LITEST_ANY); + litest_add(trackpoint_middlebutton_noscroll, LITEST_POINTINGSTICK, LITEST_ANY); + litest_add(trackpoint_scroll, LITEST_POINTINGSTICK, LITEST_ANY); + litest_add(trackpoint_scroll_source, LITEST_POINTINGSTICK, LITEST_ANY); + litest_add(trackpoint_topsoftbuttons_left_handed_trackpoint, LITEST_TOPBUTTONPAD, LITEST_ANY); + 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", trackpoint_palmdetect, LITEST_POINTINGSTICK, LITEST_ANY); - litest_add("trackpoint:palmdetect", trackpoint_palmdetect_resume_touch, LITEST_POINTINGSTICK, LITEST_ANY); - litest_add("trackpoint:palmdetect", trackpoint_palmdetect_require_min_events, LITEST_POINTINGSTICK, LITEST_ANY); - litest_add("trackpoint:palmdetect", trackpoint_palmdetect_require_min_events_timeout, LITEST_POINTINGSTICK, LITEST_ANY); + litest_add(trackpoint_palmdetect, 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); + litest_add(trackpoint_palmdetect_require_min_events_timeout, LITEST_POINTINGSTICK, LITEST_ANY); } diff -Nru libinput-1.16.4/test/test-udev.c libinput-1.17.2/test/test-udev.c --- libinput-1.16.4/test/test-udev.c 2020-11-27 01:38:59.396086200 +0000 +++ libinput-1.17.2/test/test-udev.c 2021-04-30 04:25:41.544076400 +0000 @@ -674,25 +674,25 @@ TEST_COLLECTION(udev) { - litest_add_no_device("udev:create", udev_create_NULL); - litest_add_no_device("udev:create", udev_create_seat0); - litest_add_no_device("udev:create", udev_create_empty_seat); - litest_add_no_device("udev:create", udev_create_seat_too_long); - litest_add_no_device("udev:create", udev_set_user_data); + litest_add_no_device(udev_create_NULL); + litest_add_no_device(udev_create_seat0); + litest_add_no_device(udev_create_empty_seat); + litest_add_no_device(udev_create_seat_too_long); + litest_add_no_device(udev_set_user_data); - litest_add_no_device("udev:seat", udev_added_seat_default); - litest_add_no_device("udev:seat", udev_change_seat); + litest_add_no_device(udev_added_seat_default); + litest_add_no_device(udev_change_seat); - litest_add_for_device("udev:suspend", udev_double_suspend, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_for_device("udev:suspend", udev_double_resume, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_for_device("udev:suspend", udev_suspend_resume, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_for_device("udev:suspend", udev_resume_before_seat, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_for_device("udev:suspend", udev_suspend_resume_before_seat, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_for_device("udev:device events", udev_device_sysname, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_for_device("udev:seat", udev_seat_recycle, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_for_device(udev_double_suspend, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_for_device(udev_double_resume, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_for_device(udev_suspend_resume, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_for_device(udev_resume_before_seat, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_for_device(udev_suspend_resume_before_seat, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_for_device(udev_device_sysname, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_for_device(udev_seat_recycle, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_no_device("udev:path", udev_path_add_device); - litest_add_for_device("udev:path", udev_path_remove_device, LITEST_SYNAPTICS_CLICKPAD_X220); + litest_add_no_device(udev_path_add_device); + litest_add_for_device(udev_path_remove_device, LITEST_SYNAPTICS_CLICKPAD_X220); - litest_add_no_device("udev:ignore", udev_ignore_device); + litest_add_no_device(udev_ignore_device); } diff -Nru libinput-1.16.4/test/test-utils.c libinput-1.17.2/test/test-utils.c --- libinput-1.16.4/test/test-utils.c 2020-11-27 01:38:59.397086100 +0000 +++ libinput-1.17.2/test/test-utils.c 2021-04-30 04:25:41.544076400 +0000 @@ -546,6 +546,52 @@ } END_TEST +START_TEST(input_prop_parser) +{ + struct parser_test_val { + const char *prop; + bool success; + size_t nvals; + uint32_t values[20]; + } tests[] = { + { "INPUT_PROP_BUTTONPAD", true, 1, {INPUT_PROP_BUTTONPAD}}, + { "INPUT_PROP_BUTTONPAD;INPUT_PROP_POINTER", true, 2, + { INPUT_PROP_BUTTONPAD, + INPUT_PROP_POINTER }}, + { "INPUT_PROP_BUTTONPAD;0x00;0x03", true, 3, + { INPUT_PROP_BUTTONPAD, + INPUT_PROP_POINTER, + INPUT_PROP_SEMI_MT }}, + { .prop = "", .success = false }, + { .prop = "0xff", .success = false }, + { .prop = "INPUT_PROP", .success = false }, + { .prop = "INPUT_PROP_FOO", .success = false }, + { .prop = "INPUT_PROP_FOO;INPUT_PROP_FOO", .success = false }, + { .prop = "INPUT_PROP_POINTER;INPUT_PROP_FOO", .success = false }, + { .prop = "none", .success = false }, + { .prop = NULL }, + }; + struct parser_test_val *t; + + for (int i = 0; tests[i].prop; i++) { + bool success; + uint32_t props[32]; + size_t nprops = ARRAY_LENGTH(props); + + t = &tests[i]; + success = parse_input_prop_property(t->prop, props, &nprops); + ck_assert(success == t->success); + if (!success) + continue; + + ck_assert_int_eq(nprops, t->nvals); + for (size_t j = 0; j < t->nvals; j++) { + ck_assert_int_eq(t->values[j], props[j]); + } + } +} +END_TEST + START_TEST(evdev_abs_parser) { struct test { @@ -1224,6 +1270,84 @@ } END_TEST +START_TEST(streq_test) +{ + ck_assert(streq("", "") == true); + ck_assert(streq(NULL, NULL) == true); + ck_assert(streq("0.0.1", "") == false); + ck_assert(streq("foo", NULL) == false); + ck_assert(streq(NULL, "foo") == false); + ck_assert(streq("0.0.1", "0.0.1") == true); +} +END_TEST + +START_TEST(strneq_test) +{ + ck_assert(strneq("", "", 1) == true); + ck_assert(strneq(NULL, NULL, 1) == true); + ck_assert(strneq("0.0.1", "", 6) == false); + ck_assert(strneq("foo", NULL, 5) == false); + ck_assert(strneq(NULL, "foo", 5) == false); + ck_assert(strneq("0.0.1", "0.0.1", 6) == true); +} +END_TEST + +START_TEST(basename_test) +{ + struct test { + const char *path; + const char *expected; + } tests[] = { + { "a", "a" }, + { "foo.c", "foo.c" }, + { "foo", "foo" }, + { "/path/to/foo.h", "foo.h" }, + { "../bar.foo", "bar.foo" }, + { "./bar.foo.baz", "bar.foo.baz" }, + { "./", NULL }, + { "/", NULL }, + { "/bar/", NULL }, + { "/bar", "bar" }, + { "", NULL }, + }; + struct test *t; + + ARRAY_FOR_EACH(tests, t) { + const char *result = safe_basename(t->path); + if (t->expected == NULL) + ck_assert(result == NULL); + else + ck_assert_str_eq(result, t->expected); + } +} +END_TEST +START_TEST(trunkname_test) +{ + struct test { + const char *path; + const char *expected; + } tests[] = { + { "foo.c", "foo" }, + { "/path/to/foo.h", "foo" }, + { "/path/to/foo", "foo" }, + { "../bar.foo", "bar" }, + { "./bar.foo.baz", "bar.foo" }, + { "./", "" }, + { "/", "" }, + { "/bar/", "" }, + { "/bar", "bar" }, + { "", "" }, + }; + struct test *t; + + ARRAY_FOR_EACH(tests, t) { + char *result = trunkname(t->path); + ck_assert_str_eq(result, t->expected); + free(result); + } +} +END_TEST + static Suite * litest_utils_suite(void) { @@ -1244,6 +1368,7 @@ tcase_add_test(tc, calibration_prop_parser); tcase_add_test(tc, range_prop_parser); tcase_add_test(tc, evcode_prop_parser); + tcase_add_test(tc, input_prop_parser); tcase_add_test(tc, evdev_abs_parser); tcase_add_test(tc, safe_atoi_test); tcase_add_test(tc, safe_atoi_base_16_test); @@ -1264,6 +1389,10 @@ tcase_add_test(tc, list_test_insert); tcase_add_test(tc, list_test_append); tcase_add_test(tc, strverscmp_test); + tcase_add_test(tc, streq_test); + tcase_add_test(tc, strneq_test); + tcase_add_test(tc, trunkname_test); + tcase_add_test(tc, basename_test); suite_add_tcase(s, tc); diff -Nru libinput-1.16.4/tools/libinput-analyze.man libinput-1.17.2/tools/libinput-analyze.man --- libinput-1.16.4/tools/libinput-analyze.man 2020-11-27 01:38:59.399086000 +0000 +++ libinput-1.17.2/tools/libinput-analyze.man 2021-04-30 04:25:41.544076400 +0000 @@ -24,6 +24,13 @@ .TP 8 .B libinput\-analyze\-per-slot-delta(1) analyze the delta per event per slot +.TP 8 +.B libinput\-analyze\-recording(1) +analyze a recording made with +.B libinput\-record(1) +.TP 8 +.B libinput\-analyze\-touch-down-state(1) +analyze the state of each touch in a recording .SH LIBINPUT Part of the .B libinput(1) diff -Nru libinput-1.16.4/tools/libinput-analyze-per-slot-delta.py libinput-1.17.2/tools/libinput-analyze-per-slot-delta.py --- libinput-1.16.4/tools/libinput-analyze-per-slot-delta.py 2020-11-27 01:38:59.398086000 +0000 +++ libinput-1.17.2/tools/libinput-analyze-per-slot-delta.py 2021-04-30 04:25:41.544076400 +0000 @@ -36,15 +36,16 @@ import libevdev -COLOR_RESET = '\x1b[0m' -COLOR_RED = '\x1b[6;31m' +COLOR_RESET = "\x1b[0m" +COLOR_RED = "\x1b[6;31m" -class SlotFormatter(): +class SlotFormatter: width = 16 - def __init__(self, is_absolute=False, resolution=None, - threshold=None, ignore_below=None): + def __init__( + self, is_absolute=False, resolution=None, threshold=None, ignore_below=None + ): self.threshold = threshold self.ignore_below = ignore_below self.resolution = resolution @@ -54,19 +55,19 @@ self.filtered = False def __str__(self): - return ' | '.join(self.slots) + return " | ".join(self.slots) def format_slot(self, slot): if slot.state == SlotState.BEGIN: - self.slots.append('+++++++'.center(self.width)) + self.slots.append("+++++++".center(self.width)) self.have_data = True elif slot.state == SlotState.END: - self.slots.append('-------'.center(self.width)) + self.slots.append("-------".center(self.width)) self.have_data = True elif slot.state == SlotState.NONE: - self.slots.append(('*' * (self.width - 2)).center(self.width)) + self.slots.append(("*" * (self.width - 2)).center(self.width)) elif not slot.dirty: - self.slots.append(' '.center(self.width)) + self.slots.append(" ".center(self.width)) else: if self.resolution is not None: dx, dy = slot.dx / self.resolution[0], slot.dy / self.resolution[1] @@ -81,35 +82,39 @@ else: t = t * 180.0 / math.pi - directions = ['↖↑', '↖←', '↙←', '↙↓', '↓↘', '→↘', '→↗', '↑↗'] + directions = ["↖↑", "↖←", "↙←", "↙↓", "↓↘", "→↘", "→↗", "↑↗"] direction = directions[int(t / 45)] elif dy == 0: if dx < 0: - direction = '←←' + direction = "←←" else: - direction = '→→' + direction = "→→" else: if dy < 0: - direction = '↑↑' + direction = "↑↑" else: - direction = '↓↓' + direction = "↓↓" - color = '' - reset = '' + color = "" + reset = "" if not self.is_absolute: if self.ignore_below is not None or self.threshold is not None: dist = math.hypot(dx, dy) if self.ignore_below is not None and dist < self.ignore_below: - self.slots.append(' '.center(self.width)) + self.slots.append(" ".center(self.width)) self.filtered = True return if self.threshold is not None and dist >= self.threshold: color = COLOR_RED reset = COLOR_RESET if isinstance(dx, int) and isinstance(dy, int): - string = "{} {}{:+4d}/{:+4d}{}".format(direction, color, dx, dy, reset) + string = "{} {}{:+4d}/{:+4d}{}".format( + direction, color, dx, dy, reset + ) else: - string = "{} {}{:+3.2f}/{:+03.2f}{}".format(direction, color, dx, dy, reset) + string = "{} {}{:+3.2f}/{:+03.2f}{}".format( + direction, color, dx, dy, reset + ) else: x, y = slot.x, slot.y string = "{} {}{:4d}/{:4d}{}".format(direction, color, x, y, reset) @@ -144,23 +149,46 @@ slots = [] xres, yres = 1, 1 - parser = argparse.ArgumentParser(description="Measure delta between event frames for each slot") - parser.add_argument("--use-mm", action='store_true', help="Use mm instead of device deltas") - parser.add_argument("--use-st", action='store_true', help="Use ABS_X/ABS_Y instead of ABS_MT_POSITION_X/Y") - parser.add_argument("--use-absolute", action='store_true', help="Use absolute coordinates, not deltas") - parser.add_argument("path", metavar="recording", - nargs=1, help="Path to libinput-record YAML file") - parser.add_argument("--threshold", type=float, default=None, help="Mark any delta above this treshold") - parser.add_argument("--ignore-below", type=float, default=None, help="Ignore any delta below this theshold") + parser = argparse.ArgumentParser( + description="Measure delta between event frames for each slot" + ) + parser.add_argument( + "--use-mm", action="store_true", help="Use mm instead of device deltas" + ) + parser.add_argument( + "--use-st", + action="store_true", + help="Use ABS_X/ABS_Y instead of ABS_MT_POSITION_X/Y", + ) + parser.add_argument( + "--use-absolute", + action="store_true", + help="Use absolute coordinates, not deltas", + ) + parser.add_argument( + "path", metavar="recording", nargs=1, help="Path to libinput-record YAML file" + ) + parser.add_argument( + "--threshold", + type=float, + default=None, + help="Mark any delta above this threshold", + ) + parser.add_argument( + "--ignore-below", + type=float, + default=None, + help="Ignore any delta below this threshold", + ) args = parser.parse_args() if not sys.stdout.isatty(): - COLOR_RESET = '' - COLOR_RED = '' + COLOR_RESET = "" + COLOR_RED = "" yml = yaml.safe_load(open(args.path[0])) - device = yml['devices'][0] - absinfo = device['evdev']['absinfo'] + device = yml["devices"][0] + absinfo = device["evdev"]["absinfo"] try: nslots = absinfo[libevdev.EV_ABS.ABS_MT_SLOT.value][1] + 1 except KeyError: @@ -195,11 +223,15 @@ nskipped_lines = 0 - for event in device['events']: - for evdev in event['evdev']: + for event in device["events"]: + for evdev in event["evdev"]: s = slots[slot] - e = libevdev.InputEvent(code=libevdev.evbit(evdev[2], evdev[3]), - value=evdev[4], sec=evdev[0], usec=evdev[1]) + e = libevdev.InputEvent( + code=libevdev.evbit(evdev[2], evdev[3]), + value=evdev[4], + sec=evdev[0], + usec=evdev[1], + ) if e.code in tool_bits: tool_bits[e.code] = e.value @@ -208,8 +240,10 @@ # Note: this relies on the EV_KEY events to come in before the # x/y events, otherwise the last/first event in each slot will # be wrong. - if (e.code == libevdev.EV_KEY.BTN_TOOL_FINGER or - e.code == libevdev.EV_KEY.BTN_TOOL_PEN): + if ( + e.code == libevdev.EV_KEY.BTN_TOOL_FINGER + or e.code == libevdev.EV_KEY.BTN_TOOL_PEN + ): slot = 0 s = slots[slot] s.dirty = True @@ -251,7 +285,7 @@ s.dirty = True # bcm5974 cycles through slot numbers, so let's say all below # our current slot number was used - for sl in slots[:slot + 1]: + for sl in slots[: slot + 1]: sl.used = True elif e.code == libevdev.EV_ABS.ABS_MT_TRACKING_ID: if e.value == -1: @@ -290,11 +324,11 @@ last_time = t tools = [ - (libevdev.EV_KEY.BTN_TOOL_QUINTTAP, 'QIN'), - (libevdev.EV_KEY.BTN_TOOL_QUADTAP, 'QAD'), - (libevdev.EV_KEY.BTN_TOOL_TRIPLETAP, 'TRI'), - (libevdev.EV_KEY.BTN_TOOL_DOUBLETAP, 'DBL'), - (libevdev.EV_KEY.BTN_TOUCH, 'TOU'), + (libevdev.EV_KEY.BTN_TOOL_QUINTTAP, "QIN"), + (libevdev.EV_KEY.BTN_TOOL_QUADTAP, "QAD"), + (libevdev.EV_KEY.BTN_TOOL_TRIPLETAP, "TRI"), + (libevdev.EV_KEY.BTN_TOOL_DOUBLETAP, "DBL"), + (libevdev.EV_KEY.BTN_TOUCH, "TOU"), ] for bit, string in tools: @@ -302,12 +336,14 @@ tool_state = string break else: - tool_state = ' ' + tool_state = " " - fmt = SlotFormatter(is_absolute=args.use_absolute, - resolution=(xres, yres) if args.use_mm else None, - threshold=args.threshold, - ignore_below=args.ignore_below) + fmt = SlotFormatter( + is_absolute=args.use_absolute, + resolution=(xres, yres) if args.use_mm else None, + threshold=args.threshold, + ignore_below=args.ignore_below, + ) for sl in [s for s in slots if s.used]: fmt.format_slot(sl) @@ -323,11 +359,21 @@ if nskipped_lines > 0: print("") nskipped_lines = 0 - print("{:2d}.{:06d} {:+5d}ms {}: {}".format(e.sec, e.usec, tdelta, tool_state, fmt)) + print( + "{:2d}.{:06d} {:+5d}ms {}: {}".format( + e.sec, e.usec, tdelta, tool_state, fmt + ) + ) elif fmt.filtered: nskipped_lines += 1 - print("\r", " " * 21, "... {} below threshold".format(nskipped_lines), flush=True, end='') + print( + "\r", + " " * 21, + "... {} below threshold".format(nskipped_lines), + flush=True, + end="", + ) -if __name__ == '__main__': +if __name__ == "__main__": main(sys.argv) diff -Nru libinput-1.16.4/tools/libinput-analyze-recording.man libinput-1.17.2/tools/libinput-analyze-recording.man --- libinput-1.16.4/tools/libinput-analyze-recording.man 1970-01-01 00:00:00.000000000 +0000 +++ libinput-1.17.2/tools/libinput-analyze-recording.man 2021-04-30 04:25:41.544076400 +0000 @@ -0,0 +1,39 @@ +.TH libinput-analyze-recording "1" +.SH NAME +libinput\-analyze\-recording \- analyze a device recording +.SH SYNOPSIS +.B libinput analyze recording [\-\-help] [options] \fIrecording.yml\fI +.SH DESCRIPTION +.PP +The +.B "libinput analyze recording" +tool analyzes a recording made with +.B "libinput record" +and prints a tabular summary of the events in that recording. +.PP +This is a debugging tool only, its output may change at any time. Do not +rely on the output. +.SH OPTIONS +.TP 8 +.B \-\-help +Print help +.SH OUTPUT +An example output for a tablet sequence is below. +.PP +.nf +.sf +Time | X | Y | PRESSURE | DISTANCE | MISC | SERIAL +----------------------------------------------------------------- + 0.000 | 9717 | 6266 | | 63 | 0x862 | 0x9a805597 | BTN_TOOL_PEN + 0.005 | 9709 | | | | | 0x9a805597 | BTN_TOOL_PEN + 0.012 | 9701 | | | | | 0x9a805597 | BTN_TOOL_PEN + 0.020 | 9692 | 6269 | | | | 0x9a805597 | BTN_TOOL_PEN + 0.028 | 9680 | 6277 | | | | 0x9a805597 | BTN_TOOL_PEN + 0.034 | 9668 | 6279 | | | | 0x9a805597 | BTN_TOOL_PEN + 0.042 | 9654 | 6282 | | | | 0x9a805597 | BTN_TOOL_PEN +.fi +.in +.SH LIBINPUT +Part of the +.B libinput(1) +suite diff -Nru libinput-1.16.4/tools/libinput-analyze-recording.py libinput-1.17.2/tools/libinput-analyze-recording.py --- libinput-1.16.4/tools/libinput-analyze-recording.py 1970-01-01 00:00:00.000000000 +0000 +++ libinput-1.17.2/tools/libinput-analyze-recording.py 2021-04-30 04:25:41.544076400 +0000 @@ -0,0 +1,189 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 +# vim: set expandtab shiftwidth=4: +# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ +# +# Copyright © 2021 Red Hat, Inc. +# +# 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. +# +# Prints the data from a libinput recording in a table format to ease +# debugging. +# +# Input is a libinput record yaml file + +import argparse +import sys +import yaml +import libevdev + +# minimum width of a field in the table +MIN_FIELD_WIDTH = 6 + + +# Default is to just return the value of an axis, but some axes want special +# formatting. +def format_value(code, value): + if code in (libevdev.EV_ABS.ABS_MISC, libevdev.EV_MSC.MSC_SERIAL): + return f"{value & 0xFFFFFFFF:#x}" + + # Rel axes we always print the sign + if code.type == libevdev.EV_REL: + return f"{value:+d}" + + return f"{value}" + + +# The list of axes we want to track +def is_tracked_axis(code): + if code.type in (libevdev.EV_KEY, libevdev.EV_SW, libevdev.EV_SYN): + return False + + # We don't do slots in this tool + if code.type == libevdev.EV_ABS: + if libevdev.EV_ABS.ABS_MT_SLOT <= code <= libevdev.EV_ABS.ABS_MAX: + return False + + return True + + +def main(argv): + parser = argparse.ArgumentParser( + description="Display a recording in a tabular format" + ) + parser.add_argument( + "path", metavar="recording", nargs=1, help="Path to libinput-record YAML file" + ) + args = parser.parse_args() + + yml = yaml.safe_load(open(args.path[0])) + if yml["ndevices"] > 1: + print(f"WARNING: Using only first {yml['ndevices']} devices in recording") + device = yml["devices"][0] + + if not device["events"]: + print(f"No events found in recording") + sys.exit(1) + + def events(): + """ + Yields the next event in the recording + """ + for event in device["events"]: + for evdev in event.get("evdev", []): + yield libevdev.InputEvent( + code=libevdev.evbit(evdev[2], evdev[3]), + value=evdev[4], + sec=evdev[0], + usec=evdev[1], + ) + + def interesting_axes(events): + """ + Yields the libevdev codes with the axes in this recording + """ + used_axes = [] + for e in events: + if e.code not in used_axes and is_tracked_axis(e.code): + yield e.code + used_axes.append(e.code) + + # Compile all axes that we want to print first + axes = sorted( + interesting_axes(events()), key=lambda x: x.type.value * 1000 + x.value + ) + # Strip the REL_/ABS_ prefix for the headers + headers = [a.name[4:].rjust(MIN_FIELD_WIDTH) for a in axes] + # for easier formatting later, we keep the header field width in a dict + axes = {a: len(h) for a, h in zip(axes, headers)} + + # Time is a special case, always the first entry + # Format uses ms only, we rarely ever care about µs + headers = [f"{'Time':<7s}"] + headers + ["Keys"] + header_line = f"{' | '.join(headers)}" + print(header_line) + print("-" * len(header_line)) + + current_frame = {} # {evdev-code: value} + axes_in_use = {} # to print axes never sending events + last_fields = [] # to skip duplicate lines + continuation_count = 0 + + keystate = {} + keystate_changed = False + + for e in events(): + axes_in_use[e.code] = True + + if e.code.type == libevdev.EV_KEY: + keystate[e.code] = e.value + keystate_changed = True + elif is_tracked_axis(e.code): + current_frame[e.code] = e.value + elif e.code == libevdev.EV_SYN.SYN_REPORT: + fields = [] + for a in axes: + s = format_value(a, current_frame[a]) if a in current_frame else " " + fields.append(s.rjust(max(MIN_FIELD_WIDTH, axes[a]))) + current_frame = {} + + if last_fields != fields or keystate_changed: + last_fields = fields.copy() + keystate_changed = False + + if continuation_count: + continuation_count = 0 + print("") + + fields.insert(0, f"{e.sec: 3d}.{e.usec//1000:03d}") + keys_down = [k.name for k, v in keystate.items() if v] + fields.append(", ".join(keys_down)) + print(" | ".join(fields)) + else: + continuation_count += 1 + print(f"\r ... +{continuation_count}", end="", flush=True) + + # Print out any rel/abs axes that not generate events in + # this recording + unused_axes = [] + for evtype, evcodes in device["evdev"]["codes"].items(): + for c in evcodes: + code = libevdev.evbit(int(evtype), int(c)) + if is_tracked_axis(code) and code not in axes_in_use: + unused_axes.append(code) + + if unused_axes: + print( + f"Axes present but without events: {', '.join([a.name for a in unused_axes])}" + ) + + for e in events(): + if libevdev.EV_ABS.ABS_MT_SLOT <= code <= libevdev.EV_ABS.ABS_MAX: + print( + "WARNING: This recording contains multitouch data that is not supported by this tool." + ) + break + + +if __name__ == "__main__": + try: + main(sys.argv) + except BrokenPipeError: + pass diff -Nru libinput-1.16.4/tools/libinput-analyze-touch-down-state.man libinput-1.17.2/tools/libinput-analyze-touch-down-state.man --- libinput-1.16.4/tools/libinput-analyze-touch-down-state.man 1970-01-01 00:00:00.000000000 +0000 +++ libinput-1.17.2/tools/libinput-analyze-touch-down-state.man 2021-04-30 04:25:41.544076400 +0000 @@ -0,0 +1,45 @@ +.TH libinput-analyze-touch-down-state "1" +.SH NAME +libinput\-analyze\-touch\-down\-state \- analyze the touch states +.SH SYNOPSIS +.B libinput analyze touch-down-state [\-\-help] [options] \fIrecording.yml\fI +.SH DESCRIPTION +.PP +The +.B "libinput analyze touch\-down\state" +tool analyzes a recording made with +.B "libinput record" +and prints "down" state of each touch. This tool aids with the detection of stuck touches. +.PP +This is a debugging tool only, its output may change at any time. Do not +rely on the output. +.SH OPTIONS +.TP 8 +.B \-\-help +Print help +.TP 8 +.B \-\-use-st +Use the single-touch BTN_TOOL_ bits instead of the slot state. The output +will only show the "highest" finger down at any time. For examples, where +two fingers are down, only the second slot will be marked as down. +.SH OUTPUT +An example output for a two-finger alternating sequence below. +.PP +.nf +.sf + 6.140281 +1062ms: x | x + 7.410377 +1257ms: | x + 7.420200 +9ms: | + 11.233108 +3812ms: x | x + 11.245721 +12ms: x | x + 11.850206 +604ms: | + 13.827740 +1977ms: x | + 13.839723 +11ms: x | + 14.704027 +864ms: x | x + 14.716691 +12ms: x | x +.fi +.in +.SH LIBINPUT +Part of the +.B libinput(1) +suite diff -Nru libinput-1.16.4/tools/libinput-analyze-touch-down-state.py libinput-1.17.2/tools/libinput-analyze-touch-down-state.py --- libinput-1.16.4/tools/libinput-analyze-touch-down-state.py 1970-01-01 00:00:00.000000000 +0000 +++ libinput-1.17.2/tools/libinput-analyze-touch-down-state.py 2021-04-30 04:25:41.544076400 +0000 @@ -0,0 +1,202 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 +# vim: set expandtab shiftwidth=4: +# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ +# +# Copyright © 2020 Red Hat, Inc. +# +# 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. +# +# +# Prints the down/up state of each touch slot +# +# Input is a libinput record yaml file + +import argparse +import enum +import sys +import yaml +import libevdev + + +class Slot: + class State(enum.Enum): + NONE = "NONE" + BEGIN = "BEGIN" + UPDATE = "UPDATE" + END = "END" + + def __init__(self, index): + self._state = Slot.State.NONE + self.index = index + self.used = False + + def begin(self): + assert self.state == Slot.State.NONE + self.state = Slot.State.BEGIN + + def end(self): + assert self.state in (Slot.State.BEGIN, Slot.State.UPDATE) + self.state = Slot.State.END + + def sync(self): + if self.state == Slot.State.BEGIN: + self.state = Slot.State.UPDATE + elif self.state == Slot.State.END: + self.state = Slot.State.NONE + + @property + def state(self): + return self._state + + @state.setter + def state(self, newstate): + assert newstate in Slot.State + + if newstate != Slot.State.NONE: + self.used = True + self._state = newstate + + @property + def is_active(self): + return self.state in (Slot.State.BEGIN, Slot.State.UPDATE) + + def __str__(self): + return "+" if self.state in (Slot.State.BEGIN, Slot.State.UPDATE) else " " + + +def main(argv): + parser = argparse.ArgumentParser(description="Print the state of touches over time") + parser.add_argument( + "--use-st", action="store_true", help="Ignore slots, use the BTN_TOOL bits" + ) + parser.add_argument( + "path", metavar="recording", nargs=1, help="Path to libinput-record YAML file" + ) + args = parser.parse_args() + + yml = yaml.safe_load(open(args.path[0])) + device = yml["devices"][0] + absinfo = device["evdev"]["absinfo"] + try: + nslots = absinfo[libevdev.EV_ABS.ABS_MT_SLOT.value][1] + 1 + except KeyError: + args.use_st = True + + tool_slot_map = { + libevdev.EV_KEY.BTN_TOOL_FINGER: 0, + libevdev.EV_KEY.BTN_TOOL_PEN: 0, + libevdev.EV_KEY.BTN_TOOL_DOUBLETAP: 1, + libevdev.EV_KEY.BTN_TOOL_TRIPLETAP: 2, + libevdev.EV_KEY.BTN_TOOL_QUADTAP: 3, + libevdev.EV_KEY.BTN_TOOL_QUINTTAP: 4, + } + if args.use_st: + for bit in tool_slot_map: + if bit.value in device["evdev"]["codes"][libevdev.EV_KEY.value]: + nslots = max(nslots, tool_slot_map[bit]) + + slots = [Slot(i) for i in range(0, nslots)] + # We claim the first slots are used just to make the formatting + # more consistent + for i in range(min(5, len(slots))): + slots[i].used = True + + slot = 0 + last_time = None + last_slot_state = None + header = "Timestamp | Rel time | Slots |" + print(header) + print("-" * len(header)) + + def events(): + for event in device["events"]: + for evdev in event["evdev"]: + yield evdev + + for evdev in events(): + e = libevdev.InputEvent( + code=libevdev.evbit(evdev[2], evdev[3]), + value=evdev[4], + sec=evdev[0], + usec=evdev[1], + ) + + # single-touch formatting is simpler than multitouch, it'll just + # show the highest finger down rather than the correct output. + if args.use_st: + if e.code in tool_slot_map: + slot = tool_slot_map[e.code] + s = slots[slot] + if e.value: + s.begin() + else: + s.end() + else: + if e.code == libevdev.EV_ABS.ABS_MT_SLOT: + slot = e.value + s = slots[slot] + # bcm5974 cycles through slot numbers, so let's say all below + # our current slot number was used + for sl in slots[: slot + 1]: + sl.used = True + else: + s = slots[slot] + if e.code == libevdev.EV_ABS.ABS_MT_TRACKING_ID: + if e.value == -1: + s.end() + else: + s.begin() + elif e.code in ( + libevdev.EV_ABS.ABS_MT_POSITION_X, + libevdev.EV_ABS.ABS_MT_POSITION_Y, + libevdev.EV_ABS.ABS_MT_PRESSURE, + libevdev.EV_ABS.ABS_MT_TOUCH_MAJOR, + libevdev.EV_ABS.ABS_MT_TOUCH_MINOR, + ): + # If recording started after touch down + if s.state == Slot.State.NONE: + s.begin() + + if e.code == libevdev.EV_SYN.SYN_REPORT: + current_slot_state = tuple(s.is_active for s in slots) + + if current_slot_state != last_slot_state: + if last_time is None: + last_time = e.sec * 1000000 + e.usec + tdelta = 0 + else: + t = e.sec * 1000000 + e.usec + tdelta = int((t - last_time) / 1000) / 1000 + last_time = t + + fmt = " | ".join([str(s) for s in slots if s.used]) + print( + "{:2d}.{:06d} | {:+7.3f}s | {}".format(e.sec, e.usec, tdelta, fmt) + ) + + last_slot_state = current_slot_state + + for s in slots: + s.sync() + + +if __name__ == "__main__": + main(sys.argv) diff -Nru libinput-1.16.4/tools/libinput-debug-events.c libinput-1.17.2/tools/libinput-debug-events.c --- libinput-1.16.4/tools/libinput-debug-events.c 2020-11-27 01:38:59.399086000 +0000 +++ libinput-1.17.2/tools/libinput-debug-events.c 2021-04-30 04:25:41.545076400 +0000 @@ -289,7 +289,7 @@ } static void -print_key_event(struct libinput *li, struct libinput_event *ev) +print_key_event(struct libinput_event *ev) { struct libinput_event_keyboard *k = libinput_event_get_keyboard_event(ev); enum libinput_key_state state; @@ -521,15 +521,6 @@ } static void -print_touch_event_without_coords(struct libinput_event *ev) -{ - struct libinput_event_touch *t = libinput_event_get_touch_event(ev); - - print_event_time(libinput_event_touch_get_time(t)); - printq("\n"); -} - -static void print_proximity_event(struct libinput_event *ev) { struct libinput_event_tablet_tool *t = libinput_event_get_tablet_tool_event(ev); @@ -629,21 +620,30 @@ } static void -print_touch_event_with_coords(struct libinput_event *ev) +print_touch_event(struct libinput_event *ev) { struct libinput_event_touch *t = libinput_event_get_touch_event(ev); - double x = libinput_event_touch_get_x_transformed(t, screen_width); - double y = libinput_event_touch_get_y_transformed(t, screen_height); - double xmm = libinput_event_touch_get_x(t); - double ymm = libinput_event_touch_get_y(t); + enum libinput_event_type type = libinput_event_get_type(ev); print_event_time(libinput_event_touch_get_time(t)); - printq("%d (%d) %5.2f/%5.2f (%5.2f/%5.2fmm)\n", - libinput_event_touch_get_slot(t), - libinput_event_touch_get_seat_slot(t), - x, y, - xmm, ymm); + if (type != LIBINPUT_EVENT_TOUCH_FRAME) { + printq("%d (%d)", + libinput_event_touch_get_slot(t), + libinput_event_touch_get_seat_slot(t)); + } + + if (type == LIBINPUT_EVENT_TOUCH_DOWN || + type == LIBINPUT_EVENT_TOUCH_MOTION) { + double x = libinput_event_touch_get_x_transformed(t, screen_width); + double y = libinput_event_touch_get_y_transformed(t, screen_height); + double xmm = libinput_event_touch_get_x(t); + double ymm = libinput_event_touch_get_y(t); + + printq(" %5.2f/%5.2f (%5.2f/%5.2fmm)", x, y, xmm, ymm); + } + + printq("\n"); } static void @@ -824,7 +824,7 @@ int rc = -1; struct libinput_event *ev; - libinput_dispatch(li); + tools_dispatch(li); while ((ev = libinput_get_event(li))) { print_event_header(ev); @@ -840,7 +840,7 @@ print_device_notify(ev); break; case LIBINPUT_EVENT_KEYBOARD_KEY: - print_key_event(li, ev); + print_key_event(ev); break; case LIBINPUT_EVENT_POINTER_MOTION: print_motion_event(ev); @@ -855,19 +855,11 @@ print_pointer_axis_event(ev); break; case LIBINPUT_EVENT_TOUCH_DOWN: - print_touch_event_with_coords(ev); - break; case LIBINPUT_EVENT_TOUCH_MOTION: - print_touch_event_with_coords(ev); - break; case LIBINPUT_EVENT_TOUCH_UP: - print_touch_event_without_coords(ev); - break; case LIBINPUT_EVENT_TOUCH_CANCEL: - print_touch_event_without_coords(ev); - break; case LIBINPUT_EVENT_TOUCH_FRAME: - print_touch_event_without_coords(ev); + print_touch_event(ev); break; case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: print_gesture_event_without_coords(ev); @@ -917,7 +909,6 @@ } libinput_event_destroy(ev); - libinput_dispatch(li); rc = 0; } return rc; diff -Nru libinput-1.16.4/tools/libinput-debug-gui.c libinput-1.17.2/tools/libinput-debug-gui.c --- libinput-1.16.4/tools/libinput-debug-gui.c 2020-11-27 01:38:59.400086200 +0000 +++ libinput-1.17.2/tools/libinput-debug-gui.c 2021-04-30 04:25:41.545076400 +0000 @@ -1422,7 +1422,7 @@ struct window *w = libinput_get_user_data(li); struct libinput_event *ev; - libinput_dispatch(li); + tools_dispatch(li); while ((ev = libinput_get_event(li))) { switch (libinput_event_get_type(ev)) { @@ -1487,7 +1487,6 @@ } libinput_event_destroy(ev); - libinput_dispatch(li); } gtk_widget_queue_draw(w->area); diff -Nru libinput-1.16.4/tools/libinput-debug-tablet.c libinput-1.17.2/tools/libinput-debug-tablet.c --- libinput-1.16.4/tools/libinput-debug-tablet.c 2020-11-27 01:38:59.400086200 +0000 +++ libinput-1.17.2/tools/libinput-debug-tablet.c 2021-04-30 04:25:41.545076400 +0000 @@ -390,7 +390,6 @@ } libinput_event_destroy(ev); - libinput_dispatch(li); } } diff -Nru libinput-1.16.4/tools/libinput-list-devices.c libinput-1.17.2/tools/libinput-list-devices.c --- libinput-1.16.4/tools/libinput-list-devices.c 2020-11-27 01:38:59.400086200 +0000 +++ libinput-1.17.2/tools/libinput-list-devices.c 2021-04-30 04:25:41.545076400 +0000 @@ -44,8 +44,8 @@ if (libinput_device_config_tap_get_default_enabled(device)) return "enabled"; - else - return "disabled"; + + return "disabled"; } static const char * @@ -56,8 +56,8 @@ if (libinput_device_config_tap_get_default_drag_enabled(device)) return "enabled"; - else - return "disabled"; + + return "disabled"; } static const char * @@ -68,8 +68,8 @@ if (libinput_device_config_tap_get_default_drag_lock_enabled(device)) return "enabled"; - else - return "disabled"; + + return "disabled"; } static const char* @@ -80,8 +80,8 @@ if (libinput_device_config_left_handed_get_default(device)) return "enabled"; - else - return "disabled"; + + return "disabled"; } static const char * @@ -92,8 +92,8 @@ if (libinput_device_config_scroll_get_default_natural_scroll_enabled(device)) return "enabled"; - else - return "disabled"; + + return "disabled"; } static const char * @@ -104,8 +104,8 @@ if (libinput_device_config_middle_emulation_get_default_enabled(device)) return "enabled"; - else - return "disabled"; + + return "disabled"; } static char * @@ -222,8 +222,8 @@ if (libinput_device_config_dwt_get_default_enabled(device)) return "enabled"; - else - return "disabled"; + + return "disabled"; } static char * @@ -384,13 +384,15 @@ if (streq(argv[1], "--help")) { usage(); return 0; - } else if (streq(argv[1], "--version")) { + } + + if (streq(argv[1], "--version")) { printf("%s\n", LIBINPUT_VERSION); return 0; - } else { - usage(); - return EXIT_INVALID_USAGE; } + + usage(); + return EXIT_INVALID_USAGE; } li = tools_open_backend(BACKEND_UDEV, seat, false, &grab); diff -Nru libinput-1.16.4/tools/libinput-measure-fuzz.py libinput-1.17.2/tools/libinput-measure-fuzz.py --- libinput-1.16.4/tools/libinput-measure-fuzz.py 2020-11-27 01:38:59.400086200 +0000 +++ libinput-1.17.2/tools/libinput-measure-fuzz.py 2021-04-30 04:25:41.545076400 +0000 @@ -28,26 +28,29 @@ import sys import argparse import subprocess + try: import libevdev import pyudev except ModuleNotFoundError as e: - print('Error: {}'.format(str(e)), file=sys.stderr) - print('One or more python modules are missing. Please install those ' - 'modules and re-run this tool.') + print("Error: {}".format(str(e)), file=sys.stderr) + print( + "One or more python modules are missing. Please install those " + "modules and re-run this tool." + ) sys.exit(1) -DEFAULT_HWDB_FILE = '/usr/lib/udev/hwdb.d/60-evdev.hwdb' -OVERRIDE_HWDB_FILE = '/etc/udev/hwdb.d/99-touchpad-fuzz-override.hwdb' +DEFAULT_HWDB_FILE = "/usr/lib/udev/hwdb.d/60-evdev.hwdb" +OVERRIDE_HWDB_FILE = "/etc/udev/hwdb.d/99-touchpad-fuzz-override.hwdb" class tcolors: - GREEN = '\033[92m' - RED = '\033[91m' - YELLOW = '\033[93m' - BOLD = '\033[1m' - NORMAL = '\033[0m' + GREEN = "\033[92m" + RED = "\033[91m" + YELLOW = "\033[93m" + BOLD = "\033[1m" + NORMAL = "\033[0m" def print_bold(msg, **kwargs): @@ -81,44 +84,53 @@ else: self.path = path - fd = open(self.path, 'rb') + fd = open(self.path, "rb") super().__init__(fd) context = pyudev.Context() self.udev_device = pyudev.Devices.from_device_file(context, self.path) def find_touch_device(self): context = pyudev.Context() - for device in context.list_devices(subsystem='input'): - if not device.get('ID_INPUT_TOUCHPAD', 0): + for device in context.list_devices(subsystem="input"): + if not device.get("ID_INPUT_TOUCHPAD", 0): continue - if not device.device_node or \ - not device.device_node.startswith('/dev/input/event'): + if not device.device_node or not device.device_node.startswith( + "/dev/input/event" + ): continue return device.device_node - print('Unable to find a touch device.', file=sys.stderr) + print("Unable to find a touch device.", file=sys.stderr) sys.exit(1) def check_property(self): - '''Return a tuple of (xfuzz, yfuzz) with the fuzz as set in the libinput - property. Returns None if the property doesn't exist''' + """Return a tuple of (xfuzz, yfuzz) with the fuzz as set in the libinput + property. Returns None if the property doesn't exist""" axes = { - 0x00: self.udev_device.get('LIBINPUT_FUZZ_00'), - 0x01: self.udev_device.get('LIBINPUT_FUZZ_01'), - 0x35: self.udev_device.get('LIBINPUT_FUZZ_35'), - 0x36: self.udev_device.get('LIBINPUT_FUZZ_36'), + 0x00: self.udev_device.get("LIBINPUT_FUZZ_00"), + 0x01: self.udev_device.get("LIBINPUT_FUZZ_01"), + 0x35: self.udev_device.get("LIBINPUT_FUZZ_35"), + 0x36: self.udev_device.get("LIBINPUT_FUZZ_36"), } if axes[0x35] is not None: if axes[0x35] != axes[0x00]: - print_bold('WARNING: fuzz mismatch ABS_X: {}, ABS_MT_POSITION_X: {}'.format(axes[0x00], axes[0x35])) + print_bold( + "WARNING: fuzz mismatch ABS_X: {}, ABS_MT_POSITION_X: {}".format( + axes[0x00], axes[0x35] + ) + ) if axes[0x36] is not None: if axes[0x36] != axes[0x01]: - print_bold('WARNING: fuzz mismatch ABS_Y: {}, ABS_MT_POSITION_Y: {}'.format(axes[0x01], axes[0x36])) + print_bold( + "WARNING: fuzz mismatch ABS_Y: {}, ABS_MT_POSITION_Y: {}".format( + axes[0x01], axes[0x36] + ) + ) xfuzz = axes[0x35] or axes[0x00] yfuzz = axes[0x36] or axes[0x01] @@ -126,27 +138,34 @@ if xfuzz is None and yfuzz is None: return None - if ((xfuzz is not None and yfuzz is None) or - (xfuzz is None and yfuzz is not None)): - raise InvalidConfigurationError('fuzz should be set for both axes') + if (xfuzz is not None and yfuzz is None) or ( + xfuzz is None and yfuzz is not None + ): + raise InvalidConfigurationError("fuzz should be set for both axes") return (int(xfuzz), int(yfuzz)) def check_axes(self): - ''' + """ Returns a tuple of (xfuzz, yfuzz) with the fuzz as set on the device axis. Returns None if no fuzz is set. - ''' + """ if not self.has(libevdev.EV_ABS.ABS_X) or not self.has(libevdev.EV_ABS.ABS_Y): - raise InvalidDeviceError('device does not have x/y axes') + raise InvalidDeviceError("device does not have x/y axes") - if self.has(libevdev.EV_ABS.ABS_MT_POSITION_X) != self.has(libevdev.EV_ABS.ABS_MT_POSITION_Y): - raise InvalidDeviceError('device does not have both multitouch axes') - - xfuzz = (self.absinfo[libevdev.EV_ABS.ABS_X].fuzz or - self.absinfo[libevdev.EV_ABS.ABS_MT_POSITION_X].fuzz) - yfuzz = (self.absinfo[libevdev.EV_ABS.ABS_Y].fuzz or - self.absinfo[libevdev.EV_ABS.ABS_MT_POSITION_Y].fuzz) + if self.has(libevdev.EV_ABS.ABS_MT_POSITION_X) != self.has( + libevdev.EV_ABS.ABS_MT_POSITION_Y + ): + raise InvalidDeviceError("device does not have both multitouch axes") + + xfuzz = ( + self.absinfo[libevdev.EV_ABS.ABS_X].fuzz + or self.absinfo[libevdev.EV_ABS.ABS_MT_POSITION_X].fuzz + ) + yfuzz = ( + self.absinfo[libevdev.EV_ABS.ABS_Y].fuzz + or self.absinfo[libevdev.EV_ABS.ABS_MT_POSITION_Y].fuzz + ) if xfuzz == 0 and yfuzz == 0: return None @@ -155,13 +174,13 @@ def print_fuzz(what, fuzz): - print(' Checking {}... '.format(what), end='') + print(" Checking {}... ".format(what), end="") if fuzz is None: - print('not set') + print("not set") elif fuzz == (0, 0): - print('is zero') + print("is zero") else: - print('x={} y={}'.format(*fuzz)) + print("x={} y={}".format(*fuzz)) def handle_existing_entry(device, fuzz): @@ -174,10 +193,10 @@ # If the lines aren't in the same order in the file, it'll be a false # negative. overrides = { - 0x00: device.udev_device.get('EVDEV_ABS_00'), - 0x01: device.udev_device.get('EVDEV_ABS_01'), - 0x35: device.udev_device.get('EVDEV_ABS_35'), - 0x36: device.udev_device.get('EVDEV_ABS_36'), + 0x00: device.udev_device.get("EVDEV_ABS_00"), + 0x01: device.udev_device.get("EVDEV_ABS_01"), + 0x35: device.udev_device.get("EVDEV_ABS_35"), + 0x36: device.udev_device.get("EVDEV_ABS_36"), } has_existing_rules = False @@ -188,85 +207,98 @@ if not has_existing_rules: return False - print_red('Error! ', end='') - print('This device already has axis overrides defined') - print('') - print_bold('Searching for existing override...') + print_red("Error! ", end="") + print("This device already has axis overrides defined") + print("") + print_bold("Searching for existing override...") # Construct a template that looks like a hwdb entry (values only) from # the udev property values - template = [' EVDEV_ABS_00={}'.format(overrides[0x00]), - ' EVDEV_ABS_01={}'.format(overrides[0x01])] + template = [ + " EVDEV_ABS_00={}".format(overrides[0x00]), + " EVDEV_ABS_01={}".format(overrides[0x01]), + ] if overrides[0x35] is not None: - template += [' EVDEV_ABS_35={}'.format(overrides[0x35]), - ' EVDEV_ABS_36={}'.format(overrides[0x36])] + template += [ + " EVDEV_ABS_35={}".format(overrides[0x35]), + " EVDEV_ABS_36={}".format(overrides[0x36]), + ] - print('Checking in {}... '.format(OVERRIDE_HWDB_FILE), end='') + print("Checking in {}... ".format(OVERRIDE_HWDB_FILE), end="") entry, prefix, lineno = check_file_for_lines(OVERRIDE_HWDB_FILE, template) if entry is not None: - print_green('found') - print('The existing hwdb entry can be overwritten') + print_green("found") + print("The existing hwdb entry can be overwritten") return False else: - print_red('not found') - print('Checking in {}... '.format(DEFAULT_HWDB_FILE, template), end='') + print_red("not found") + print("Checking in {}... ".format(DEFAULT_HWDB_FILE), end="") entry, prefix, lineno = check_file_for_lines(DEFAULT_HWDB_FILE, template) if entry is not None: - print_green('found') + print_green("found") else: - print_red('not found') - print('The device has a hwdb override defined but it\'s not where I expected it to be.') - print('Please look at the libinput documentation for more details.') - print('Exiting now.') + print_red("not found") + print( + "The device has a hwdb override defined but it's not where I expected it to be." + ) + print("Please look at the libinput documentation for more details.") + print("Exiting now.") return True - print_bold('Probable entry for this device found in line {}:'.format(lineno)) - print('\n'.join(prefix + entry)) - print('') + print_bold("Probable entry for this device found in line {}:".format(lineno)) + print("\n".join(prefix + entry)) + print("") - print_bold('Suggested new entry for this device:') + print_bold("Suggested new entry for this device:") new_entry = [] for i in range(0, len(template)): - parts = entry[i].split(':') + parts = entry[i].split(":") while len(parts) < 4: - parts.append('') + parts.append("") parts[3] = str(fuzz) - new_entry.append(':'.join(parts)) - print('\n'.join(prefix + new_entry)) - print('') + new_entry.append(":".join(parts)) + print("\n".join(prefix + new_entry)) + print("") # Not going to overwrite the 60-evdev.hwdb entry with this program, too # risky. And it may not be our device match anyway. - print_bold('You must now:') - print('\n'.join(( - '1. Check the above suggestion for sanity. Does it match your device?', - '2. Open {} and amend the existing entry'.format(DEFAULT_HWDB_FILE), - ' as recommended above', - '', - ' The property format is:', - ' EVDEV_ABS_00=min:max:resolution:fuzz', - '', - ' Leave the entry as-is and only add or amend the fuzz value.', - ' A non-existent value can be skipped, e.g. this entry sets the ', - ' resolution to 32 and the fuzz to 8', - ' EVDEV_ABS_00=::32:8', - '', - '3. Save the edited file', - '4. Say Y to the next prompt'))) + print_bold("You must now:") + print( + "\n".join( + ( + "1. Check the above suggestion for sanity. Does it match your device?", + "2. Open {} and amend the existing entry".format(DEFAULT_HWDB_FILE), + " as recommended above", + "", + " The property format is:", + " EVDEV_ABS_00=min:max:resolution:fuzz", + "", + " Leave the entry as-is and only add or amend the fuzz value.", + " A non-existent value can be skipped, e.g. this entry sets the ", + " resolution to 32 and the fuzz to 8", + " EVDEV_ABS_00=::32:8", + "", + "3. Save the edited file", + "4. Say Y to the next prompt", + ) + ) + ) - cont = input('Continue? [Y/n] ') - if cont == 'n': + cont = input("Continue? [Y/n] ") + if cont == "n": raise KeyboardInterrupt if test_hwdb_entry(device, fuzz): - print_bold('Please test the new fuzz setting by restarting libinput') - print_bold('Then submit a pull request for this hwdb entry change to ' - 'to systemd at http://github.com/systemd/systemd') + print_bold("Please test the new fuzz setting by restarting libinput") + print_bold( + "Then submit a pull request for this hwdb entry change to " + "to systemd at http://github.com/systemd/systemd" + ) else: - print_bold('The new fuzz setting did not take effect.') - print_bold('Did you edit the correct file?') - print('Please look at the libinput documentation for more details.') - print('Exiting now.') + print_bold("The new fuzz setting did not take effect.") + print_bold("Did you edit the correct file?") + print("Please look at the libinput documentation for more details.") + print("Exiting now.") return True @@ -274,47 +306,49 @@ def reload_and_trigger_udev(device): import time - print('Running systemd-hwdb update') - subprocess.run(['systemd-hwdb', 'update'], check=True) - syspath = device.path.replace('/dev/input/', '/sys/class/input/') + print("Running systemd-hwdb update") + subprocess.run(["systemd-hwdb", "update"], check=True) + syspath = device.path.replace("/dev/input/", "/sys/class/input/") time.sleep(2) - print('Running udevadm trigger {}'.format(syspath)) - subprocess.run(['udevadm', 'trigger', syspath], check=True) + print("Running udevadm trigger {}".format(syspath)) + subprocess.run(["udevadm", "trigger", syspath], check=True) time.sleep(2) def test_hwdb_entry(device, fuzz): reload_and_trigger_udev(device) - print_bold('Testing... ', end='') + print_bold("Testing... ", end="") d = Device(device.path) f = d.check_axes() if f is not None: if f == (fuzz, fuzz): - print_yellow('Warning') - print_bold('The hwdb applied to the device but libinput\'s udev ' - 'rules have not picked it up. This should only happen' - 'if libinput is not installed') + print_yellow("Warning") + print_bold( + "The hwdb applied to the device but libinput's udev " + "rules have not picked it up. This should only happen" + "if libinput is not installed" + ) return True else: - print_red('Error') + print_red("Error") return False else: f = d.check_property() if f is not None and f == (fuzz, fuzz): - print_green('Success') + print_green("Success") return True else: - print_red('Error') + print_red("Error") return False def check_file_for_lines(path, template): - ''' + """ Checks file at path for the lines given in template. If found, the return value is a tuple of the matching lines and the prefix (i.e. the two lines before the matching lines) - ''' + """ try: lines = [l[:-1] for l in open(path).readlines()] idx = -1 @@ -322,12 +356,12 @@ while idx < len(lines) - 1: idx += 1 line = lines[idx] - if not line.startswith(' EVDEV_ABS_00'): + if not line.startswith(" EVDEV_ABS_00"): continue - if lines[idx:idx + len(template)] != template: + if lines[idx : idx + len(template)] != template: continue - return (lines[idx:idx + len(template)], lines[idx - 2:idx], idx) + return (lines[idx : idx + len(template)], lines[idx - 2 : idx], idx) except IndexError: pass @@ -338,43 +372,51 @@ def write_udev_rule(device, fuzz): - '''Write out a udev rule that may match the device, run udevadm trigger and + """Write out a udev rule that may match the device, run udevadm trigger and check if the udev rule worked. Of course, there's plenty to go wrong... - ''' - print('') - print_bold('Guessing a udev rule to overwrite the fuzz') + """ + print("") + print_bold("Guessing a udev rule to overwrite the fuzz") # Some devices match better on pvr, others on pn, so we get to try both. yay - modalias = open('/sys/class/dmi/id/modalias').readlines()[0] - ms = modalias.split(':') + modalias = open("/sys/class/dmi/id/modalias").readlines()[0] + ms = modalias.split(":") svn, pn, pvr = None, None, None for m in ms: - if m.startswith('svn'): + if m.startswith("svn"): svn = m - elif m.startswith('pn'): + elif m.startswith("pn"): pn = m - elif m.startswith('pvr'): + elif m.startswith("pvr"): pvr = m # Let's print out both to inform and/or confuse the user - template = '\n'.join(('# {} {}', - 'evdev:name:{}:dmi:*:{}*:{}*:', - ' EVDEV_ABS_00=:::{}', - ' EVDEV_ABS_01=:::{}', - ' EVDEV_ABS_35=:::{}', - ' EVDEV_ABS_36=:::{}', - '')) - rule1 = template.format(svn[3:], device.name, device.name, svn, pvr, fuzz, fuzz, fuzz, fuzz) - rule2 = template.format(svn[3:], device.name, device.name, svn, pn, fuzz, fuzz, fuzz, fuzz) + template = "\n".join( + ( + "# {} {}", + "evdev:name:{}:dmi:*:{}*:{}*:", + " EVDEV_ABS_00=:::{}", + " EVDEV_ABS_01=:::{}", + " EVDEV_ABS_35=:::{}", + " EVDEV_ABS_36=:::{}", + "", + ) + ) + rule1 = template.format( + svn[3:], device.name, device.name, svn, pvr, fuzz, fuzz, fuzz, fuzz + ) + rule2 = template.format( + svn[3:], device.name, device.name, svn, pn, fuzz, fuzz, fuzz, fuzz + ) - print('Full modalias is: {}'.format(modalias)) + print("Full modalias is: {}".format(modalias)) print() - print_bold('Suggested udev rule, option 1:') + print_bold("Suggested udev rule, option 1:") print(rule1) print() - print_bold('Suggested udev rule, option 2:') + print_bold("Suggested udev rule, option 2:") print(rule2) - print('') + print("") # The weird hwdb matching behavior means we match on the least specific # rule (i.e. most wildcards) first although that was supposed to be fixed in @@ -386,77 +428,88 @@ return while True: - print_bold('Wich rule do you want to to test? 1 or 2? ', end='') - yesno = input('Ctrl+C to exit ') + print_bold("Wich rule do you want to to test? 1 or 2? ", end="") + yesno = input("Ctrl+C to exit ") - if yesno == '1': + if yesno == "1": rule = rule1 break - elif yesno == '2': + elif yesno == "2": rule = rule2 break fname = OVERRIDE_HWDB_FILE try: - fd = open(fname, 'x') + fd = open(fname, "x") except FileExistsError: - yesno = input('File {} exists, overwrite? [Y/n] '.format(fname)) - if yesno.lower == 'n': + yesno = input("File {} exists, overwrite? [Y/n] ".format(fname)) + if yesno.lower == "n": return - fd = open(fname, 'w') + fd = open(fname, "w") - fd.write('# File generated by libinput measure fuzz\n\n') + fd.write("# File generated by libinput measure fuzz\n\n") fd.write(rule) fd.close() if test_hwdb_entry(device, fuzz): - print('Your hwdb override file is in {}'.format(fname)) - print_bold('Please test the new fuzz setting by restarting libinput') - print_bold('Then submit a pull request for this hwdb entry to ' - 'systemd at http://github.com/systemd/systemd') + print("Your hwdb override file is in {}".format(fname)) + print_bold("Please test the new fuzz setting by restarting libinput") + print_bold( + "Then submit a pull request for this hwdb entry to " + "systemd at http://github.com/systemd/systemd" + ) else: - print('The hwdb entry failed to apply to the device.') - print('Removing hwdb file again.') + print("The hwdb entry failed to apply to the device.") + print("Removing hwdb file again.") os.remove(fname) reload_and_trigger_udev(device) - print_bold('What now?') - print('1. Re-run this program and try the other suggested udev rule. If that fails,') - print('2. File a bug with the suggested udev rule at http://github.com/systemd/systemd') + print_bold("What now?") + print( + "1. Re-run this program and try the other suggested udev rule. If that fails," + ) + print( + "2. File a bug with the suggested udev rule at http://github.com/systemd/systemd" + ) def main(args): parser = argparse.ArgumentParser( - description='Print fuzz settings and/or suggest udev rules for the fuzz to be adjusted.' + description="Print fuzz settings and/or suggest udev rules for the fuzz to be adjusted." + ) + parser.add_argument( + "path", + metavar="/dev/input/event0", + nargs="?", + type=str, + help="Path to device (optional)", ) - parser.add_argument('path', metavar='/dev/input/event0', - nargs='?', type=str, help='Path to device (optional)') - parser.add_argument('--fuzz', type=int, help='Suggested fuzz') + parser.add_argument("--fuzz", type=int, help="Suggested fuzz") args = parser.parse_args() try: device = Device(args.path) - print_bold('Using {}: {}'.format(device.name, device.path)) + print_bold("Using {}: {}".format(device.name, device.path)) fuzz = device.check_property() - print_fuzz('udev property', fuzz) + print_fuzz("udev property", fuzz) fuzz = device.check_axes() - print_fuzz('axes', fuzz) + print_fuzz("axes", fuzz) userfuzz = args.fuzz if userfuzz is not None: write_udev_rule(device, userfuzz) except PermissionError: - print('Permission denied, please re-run as root') + print("Permission denied, please re-run as root") except InvalidConfigurationError as e: - print('Error: {}'.format(e)) + print("Error: {}".format(e)) except InvalidDeviceError as e: - print('Error: {}'.format(e)) + print("Error: {}".format(e)) except KeyboardInterrupt: - print('Exited on user request') + print("Exited on user request") -if __name__ == '__main__': +if __name__ == "__main__": main(sys.argv) diff -Nru libinput-1.16.4/tools/libinput-measure-touchpad-pressure.py libinput-1.17.2/tools/libinput-measure-touchpad-pressure.py --- libinput-1.16.4/tools/libinput-measure-touchpad-pressure.py 2020-11-27 01:38:59.400086200 +0000 +++ libinput-1.17.2/tools/libinput-measure-touchpad-pressure.py 2021-04-30 04:25:41.545076400 +0000 @@ -27,13 +27,16 @@ import sys import subprocess import argparse + try: import libevdev import pyudev except ModuleNotFoundError as e: - print('Error: {}'.format(str(e)), file=sys.stderr) - print('One or more python modules are missing. Please install those ' - 'modules and re-run this tool.') + print("Error: {}".format(str(e)), file=sys.stderr) + print( + "One or more python modules are missing. Please install those " + "modules and re-run this tool." + ) sys.exit(1) @@ -48,35 +51,35 @@ return sum(self.colwidths) + 1 def headers(self, args): - s = '|' + s = "|" align = self.ALIGNMENT - 1 # account for | for arg in args: # +2 because we want space left/right of text w = ((len(arg) + 2 + align) // align) * align self.colwidths.append(w + 1) - s += ' {:^{width}s} |'.format(arg, width=w - 2) + s += " {:^{width}s} |".format(arg, width=w - 2) return s def values(self, args): - s = '|' + s = "|" for w, arg in zip(self.colwidths, args): w -= 1 # width includes | separator if type(arg) == str: # We want space margins for strings - s += ' {:{width}s} |'.format(arg, width=w - 2) + s += " {:{width}s} |".format(arg, width=w - 2) elif type(arg) == bool: - s += '{:^{width}s}|'.format('x' if arg else ' ', width=w) + s += "{:^{width}s}|".format("x" if arg else " ", width=w) else: - s += '{:^{width}d}|'.format(arg, width=w) + s += "{:^{width}d}|".format(arg, width=w) if len(args) < len(self.colwidths): - s += '|'.rjust(self.width - len(s), ' ') + s += "|".rjust(self.width - len(s), " ") return s def separator(self): - return '+' + '-' * (self.width - 2) + '+' + return "+" + "-" * (self.width - 2) + "+" fmt = TableFormatter() @@ -84,9 +87,10 @@ class Range(object): """Class to keep a min/max of a value around""" + def __init__(self): - self.min = float('inf') - self.max = float('-inf') + self.min = float("inf") + self.max = float("-inf") def update(self, value): self.min = min(self.min, value) @@ -157,19 +161,47 @@ def _str_summary(self): if not self.points: - return fmt.values([self.tracking_id, False, False, False, False, - 'No pressure values recorded']) - - s = fmt.values([self.tracking_id, self.was_down, True, self.was_palm, - self.was_thumb, self.prange.min, self.prange.max, 0, - self.avg(), self.median()]) + return fmt.values( + [ + self.tracking_id, + False, + False, + False, + False, + "No pressure values recorded", + ] + ) + + s = fmt.values( + [ + self.tracking_id, + self.was_down, + True, + self.was_palm, + self.was_thumb, + self.prange.min, + self.prange.max, + 0, + self.avg(), + self.median(), + ] + ) return s def _str_state(self): - s = fmt.values([self.tracking_id, self.is_down, not self.is_down, - self.is_palm, self.is_thumb, self.prange.min, - self.prange.max, self.points[-1].pressure]) + s = fmt.values( + [ + self.tracking_id, + self.is_down, + not self.is_down, + self.is_palm, + self.is_thumb, + self.prange.min, + self.prange.max, + self.points[-1].pressure, + ] + ) return s @@ -184,7 +216,7 @@ else: self.path = path - fd = open(self.path, 'rb') + fd = open(self.path, "rb") super().__init__(fd) print("Using {}: {}\n".format(self.name, self.path)) @@ -195,7 +227,9 @@ absinfo = self.absinfo[libevdev.EV_ABS.ABS_PRESSURE] self.has_mt_pressure = False if absinfo is None: - raise InvalidDeviceError("Device does not have ABS_PRESSURE or ABS_MT_PRESSURE") + raise InvalidDeviceError( + "Device does not have ABS_PRESSURE or ABS_MT_PRESSURE" + ) prange = absinfo.maximum - absinfo.minimum @@ -210,12 +244,13 @@ def find_touchpad_device(self): context = pyudev.Context() - for device in context.list_devices(subsystem='input'): - if not device.get('ID_INPUT_TOUCHPAD', 0): + for device in context.list_devices(subsystem="input"): + if not device.get("ID_INPUT_TOUCHPAD", 0): continue - if not device.device_node or \ - not device.device_node.startswith('/dev/input/event'): + if not device.device_node or not device.device_node.startswith( + "/dev/input/event" + ): continue return device.device_node @@ -223,21 +258,24 @@ sys.exit(1) def _init_thresholds_from_quirks(self): - command = ['libinput', 'quirks', 'list', self.path] + command = ["libinput", "quirks", "list", self.path] cmd = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if cmd.returncode != 0: - print("Error querying quirks: {}".format(cmd.stderr.decode('utf-8')), file=sys.stderr) + print( + "Error querying quirks: {}".format(cmd.stderr.decode("utf-8")), + file=sys.stderr, + ) return - stdout = cmd.stdout.decode('utf-8') - quirks = [q.split('=') for q in stdout.split('\n')] + stdout = cmd.stdout.decode("utf-8") + quirks = [q.split("=") for q in stdout.split("\n")] for q in quirks: - if q[0] == 'AttrPalmPressureThreshold': + if q[0] == "AttrPalmPressureThreshold": self.palm = int(q[1]) - elif q[0] == 'AttrPressureRange': + elif q[0] == "AttrPressureRange": self.down, self.up = colon_tuple(q[1]) - elif q[0] == 'AttrThumbPressureThreshold': + elif q[0] == "AttrThumbPressureThreshold": self.thumb = int(q[1]) def start_new_sequence(self, tracking_id): @@ -252,11 +290,13 @@ libevdev.EV_KEY.BTN_TOOL_DOUBLETAP, libevdev.EV_KEY.BTN_TOOL_TRIPLETAP, libevdev.EV_KEY.BTN_TOOL_QUADTAP, - libevdev.EV_KEY.BTN_TOOL_QUINTTAP + libevdev.EV_KEY.BTN_TOOL_QUINTTAP, ] if event.code in tapcodes and event.value > 0: - print('\r\033[2KThis tool cannot handle multiple fingers, ' - 'output will be invalid') + print( + "\r\033[2KThis tool cannot handle multiple fingers, " + "output will be invalid" + ) def handle_abs(device, event): @@ -271,8 +311,9 @@ except IndexError: # If the finger was down at startup pass - elif (event.matches(libevdev.EV_ABS.ABS_MT_PRESSURE) or - (event.matches(libevdev.EV_ABS.ABS_PRESSURE) and not device.has_mt_pressure)): + elif event.matches(libevdev.EV_ABS.ABS_MT_PRESSURE) or ( + event.matches(libevdev.EV_ABS.ABS_PRESSURE) and not device.has_mt_pressure + ): try: s = device.current_sequence() s.append(Touch(pressure=event.value)) @@ -290,24 +331,26 @@ def loop(device): - print('This is an interactive tool') + print("This is an interactive tool") print() print("Place a single finger on the touchpad to measure pressure values.") - print('Check that:') - print('- touches subjectively perceived as down are tagged as down') - print('- touches with a thumb are tagged as thumb') - print('- touches with a palm are tagged as palm') + print("Check that:") + print("- touches subjectively perceived as down are tagged as down") + print("- touches with a thumb are tagged as thumb") + print("- touches with a palm are tagged as palm") print() - print('If the touch states do not match the interaction, re-run') - print('with --touch-thresholds=down:up using observed pressure values.') - print('See --help for more options.') + print("If the touch states do not match the interaction, re-run") + print("with --touch-thresholds=down:up using observed pressure values.") + print("See --help for more options.") print() print("Press Ctrl+C to exit") print() - headers = fmt.headers(['Touch', 'down', 'up', 'palm', 'thumb', 'min', 'max', 'p', 'avg', 'median']) + headers = fmt.headers( + ["Touch", "down", "up", "palm", "thumb", "min", "max", "p", "avg", "median"] + ) print(fmt.separator()) - print(fmt.values(['Thresh', device.down, device.up, device.palm, device.thumb])) + print(fmt.values(["Thresh", device.down, device.up, device.palm, device.thumb])) print(fmt.separator()) print(headers) print(fmt.separator()) @@ -319,11 +362,11 @@ def colon_tuple(string): try: - ts = string.split(':') + ts = string.split(":") t = tuple([int(x) for x in ts]) if len(t) == 2 and t[0] >= t[1]: return t - except: # noqa + except: # noqa pass msg = "{} is not in format N:M (N >= M)".format(string) @@ -331,24 +374,31 @@ def main(args): - parser = argparse.ArgumentParser( - description="Measure touchpad pressure values" - ) + parser = argparse.ArgumentParser(description="Measure touchpad pressure values") parser.add_argument( - 'path', metavar='/dev/input/event0', nargs='?', type=str, - help='Path to device (optional)' + "path", + metavar="/dev/input/event0", + nargs="?", + type=str, + help="Path to device (optional)", ) parser.add_argument( - '--touch-thresholds', metavar='down:up', type=colon_tuple, - help='Thresholds when a touch is logically down or up' + "--touch-thresholds", + metavar="down:up", + type=colon_tuple, + help="Thresholds when a touch is logically down or up", ) parser.add_argument( - '--palm-threshold', metavar='t', type=int, - help='Threshold when a touch is a palm' + "--palm-threshold", + metavar="t", + type=int, + help="Threshold when a touch is a palm", ) parser.add_argument( - '--thumb-threshold', metavar='t', type=int, - help='Threshold when a touch is a thumb' + "--thumb-threshold", + metavar="t", + type=int, + help="Threshold when a touch is a thumb", ) args = parser.parse_args() @@ -366,13 +416,15 @@ loop(device) except KeyboardInterrupt: - print('\r\033[2K{}'.format(fmt.separator())) + print("\r\033[2K{}".format(fmt.separator())) print() except (PermissionError, OSError): print("Error: failed to open device") except InvalidDeviceError as e: - print("This device does not have the capabilities for pressure-based touch detection.") + print( + "This device does not have the capabilities for pressure-based touch detection." + ) print("Details: {}".format(e)) diff -Nru libinput-1.16.4/tools/libinput-measure-touchpad-size.man libinput-1.17.2/tools/libinput-measure-touchpad-size.man --- libinput-1.16.4/tools/libinput-measure-touchpad-size.man 2020-11-27 01:38:59.400086200 +0000 +++ libinput-1.17.2/tools/libinput-measure-touchpad-size.man 2021-04-30 04:25:41.545076400 +0000 @@ -24,7 +24,7 @@ /dev/input/eventX nodes. .SH OPTIONS This tool must be provided the physical dimensions of the device in mm. -For example, if your touchpad is 100mm wide and 55mm heigh, run this tool as +For example, if your touchpad is 100mm wide and 55mm high, run this tool as .B libinput measure touchpad-size 100x55 .PP If a device node is given, this tool opens that device node. Otherwise, this diff -Nru libinput-1.16.4/tools/libinput-measure-touchpad-size.py libinput-1.17.2/tools/libinput-measure-touchpad-size.py --- libinput-1.16.4/tools/libinput-measure-touchpad-size.py 2020-11-27 01:38:59.400086200 +0000 +++ libinput-1.17.2/tools/libinput-measure-touchpad-size.py 2021-04-30 04:25:41.546076300 +0000 @@ -26,13 +26,16 @@ import sys import argparse + try: import libevdev import pyudev except ModuleNotFoundError as e: - print('Error: {}'.format(str(e)), file=sys.stderr) - print('One or more python modules are missing. Please install those ' - 'modules and re-run this tool.') + print("Error: {}".format(str(e)), file=sys.stderr) + print( + "One or more python modules are missing. Please install those " + "modules and re-run this tool." + ) sys.exit(1) @@ -51,15 +54,15 @@ x = evdev.absinfo[libevdev.EV_ABS.ABS_X] y = evdev.absinfo[libevdev.EV_ABS.ABS_Y] if not x or not y: - raise DeviceError('Device does not have an x or axis') + raise DeviceError("Device does not have an x or axis") if not x.resolution or not y.resolution: - print('Device does not have resolutions.', file=sys.stderr) + print("Device does not have resolutions.", file=sys.stderr) x.resolution = 1 y.resolution = 1 - self.xrange = (x.maximum - x.minimum) - self.yrange = (y.maximum - y.minimum) + self.xrange = x.maximum - x.minimum + self.yrange = y.maximum - y.minimum self.width = self.xrange / x.resolution self.height = self.yrange / y.resolution @@ -70,7 +73,12 @@ # terminal character space is (guesswork) ca 2.3 times as high as # wide. self.columns = 30 - self.rows = int(self.columns * (self.yrange // y.resolution) // (self.xrange // x.resolution) / 2.3) + self.rows = int( + self.columns + * (self.yrange // y.resolution) + // (self.xrange // x.resolution) + / 2.3 + ) self.pos = Point(0, 0) self.min = Point() self.max = Point() @@ -87,8 +95,8 @@ def x(self, x): self._x.minimum = min(self.x.minimum, x) self._x.maximum = max(self.x.maximum, x) - self.min.x = min(x, self.min.x or 0xffffffff) - self.max.x = max(x, self.max.x or -0xffffffff) + self.min.x = min(x, self.min.x or 0xFFFFFFFF) + self.max.x = max(x, self.max.x or -0xFFFFFFFF) # we calculate the position based on the original range. # this means on devices with a narrower range than advertised, not # all corners may be reachable in the touchpad drawing. @@ -98,8 +106,8 @@ def y(self, y): self._y.minimum = min(self.y.minimum, y) self._y.maximum = max(self.y.maximum, y) - self.min.y = min(y, self.min.y or 0xffffffff) - self.max.y = max(y, self.max.y or -0xffffffff) + self.min.y = min(y, self.min.y or 0xFFFFFFFF) + self.max.y = max(y, self.max.y or -0xFFFFFFFF) # we calculate the position based on the original range. # this means on devices with a narrower range than advertised, not # all corners may be reachable in the touchpad drawing. @@ -107,61 +115,61 @@ def update_from_data(self): if None in [self.min.x, self.min.y, self.max.x, self.max.y]: - raise DeviceError('Insufficient data to continue') + raise DeviceError("Insufficient data to continue") self._x.minimum = self.min.x self._x.maximum = self.max.x self._y.minimum = self.min.y self._y.maximum = self.max.y def draw(self): - print('Detected axis range: x [{:4d}..{:4d}], y [{:4d}..{:4d}]'.format( - self.min.x if self.min.x is not None else 0, - self.max.x if self.max.x is not None else 0, - self.min.y if self.min.y is not None else 0, - self.max.y if self.max.y is not None else 0)) + print( + "Detected axis range: x [{:4d}..{:4d}], y [{:4d}..{:4d}]".format( + self.min.x if self.min.x is not None else 0, + self.max.x if self.max.x is not None else 0, + self.min.y if self.min.y is not None else 0, + self.max.y if self.max.y is not None else 0, + ) + ) print() - print('Move one finger along all edges of the touchpad'.center(self.columns)) - print('until the detected axis range stops changing.'.center(self.columns)) + print("Move one finger along all edges of the touchpad".center(self.columns)) + print("until the detected axis range stops changing.".center(self.columns)) top = int(self.pos.y * self.rows) - print('+{}+'.format(''.ljust(self.columns, '-'))) + print("+{}+".format("".ljust(self.columns, "-"))) for row in range(0, top): - print('|{}|'.format(''.ljust(self.columns))) + print("|{}|".format("".ljust(self.columns))) left = int(self.pos.x * self.columns) right = max(0, self.columns - 1 - left) - print('|{}{}{}|'.format( - ''.ljust(left), - 'O', - ''.ljust(right))) + print("|{}{}{}|".format("".ljust(left), "O", "".ljust(right))) for row in range(top + 1, self.rows): - print('|{}|'.format(''.ljust(self.columns))) + print("|{}|".format("".ljust(self.columns))) - print('+{}+'.format(''.ljust(self.columns, '-'))) + print("+{}+".format("".ljust(self.columns, "-"))) - print('Press Ctrl+C to stop'.center(self.columns)) + print("Press Ctrl+C to stop".center(self.columns)) - print('\033[{}A'.format(self.rows + 8), flush=True) + print("\033[{}A".format(self.rows + 8), flush=True) self.rows_printed = self.rows + 8 def erase(self): # Erase all previous lines so we're not left with rubbish for row in range(self.rows_printed): - print('\033[K') - print('\033[{}A'.format(self.rows_printed)) + print("\033[K") + print("\033[{}A".format(self.rows_printed)) def dimension(string): try: - ts = string.split('x') + ts = string.split("x") t = tuple([int(x) for x in ts]) if len(t) == 2: return t - except: # noqa + except: # noqa pass msg = "{} is not in format WxH".format(string) @@ -173,82 +181,95 @@ def dmi_modalias_match(modalias): - modalias = modalias.split(':') - dmi = {'svn': None, 'pvr': None, 'pn': None} + modalias = modalias.split(":") + dmi = {"svn": None, "pvr": None, "pn": None} for m in modalias: for key in dmi: if m.startswith(key): - dmi[key] = m[len(key):] + dmi[key] = m[len(key) :] # Based on the current 60-evdev.hwdb, Lenovo uses pvr and everyone else # uses pn to provide a human-identifiable match - if dmi['svn'] == 'LENOVO': - return 'dmi:*svn{}:*pvr{}*'.format(dmi['svn'], dmi['pvr']) + if dmi["svn"] == "LENOVO": + return "dmi:*svn{}:*pvr{}*".format(dmi["svn"], dmi["pvr"]) else: - return 'dmi:*svn{}:*pn{}*'.format(dmi['svn'], dmi['pn']) + return "dmi:*svn{}:*pn{}*".format(dmi["svn"], dmi["pn"]) def main(args): - parser = argparse.ArgumentParser( - description="Measure the touchpad size" - ) + parser = argparse.ArgumentParser(description="Measure the touchpad size") parser.add_argument( - 'size', metavar='WxH', type=dimension, - help='Touchpad size (width by height) in mm', + "size", + metavar="WxH", + type=dimension, + help="Touchpad size (width by height) in mm", ) parser.add_argument( - 'path', metavar='/dev/input/event0', nargs='?', type=str, - help='Path to device (optional)' + "path", + metavar="/dev/input/event0", + nargs="?", + type=str, + help="Path to device (optional)", ) context = pyudev.Context() args = parser.parse_args() if not args.path: - for device in context.list_devices(subsystem='input'): - if (device.get('ID_INPUT_TOUCHPAD', 0) and - (device.device_node or '').startswith('/dev/input/event')): + for device in context.list_devices(subsystem="input"): + if device.get("ID_INPUT_TOUCHPAD", 0) and ( + device.device_node or "" + ).startswith("/dev/input/event"): args.path = device.device_node - name = 'unknown' + name = "unknown" parent = device while parent is not None: - n = parent.get('NAME', None) + n = parent.get("NAME", None) if n: name = n break parent = parent.parent - print('Using {}: {}'.format(name, device.device_node)) + print("Using {}: {}".format(name, device.device_node)) break else: - print('Unable to find a touchpad device.', file=sys.stderr) + print("Unable to find a touchpad device.", file=sys.stderr) return 1 dev = pyudev.Devices.from_device_file(context, args.path) - overrides = [p for p in dev.properties if p.startswith('EVDEV_ABS')] + overrides = [p for p in dev.properties if p.startswith("EVDEV_ABS")] if overrides: print() - print('********************************************************************') - print('WARNING: axis overrides already in place for this device:') + print("********************************************************************") + print("WARNING: axis overrides already in place for this device:") for prop in overrides: - print(' {}={}'.format(prop, dev.properties[prop])) - print('The systemd hwdb already overrides the axis ranges and/or resolution.') - print('This tool is not needed unless you want to verify the axis overrides.') - print('********************************************************************') + print(" {}={}".format(prop, dev.properties[prop])) + print("The systemd hwdb already overrides the axis ranges and/or resolution.") + print("This tool is not needed unless you want to verify the axis overrides.") + print("********************************************************************") print() try: - fd = open(args.path, 'rb') + fd = open(args.path, "rb") evdev = libevdev.Device(fd) touchpad = Touchpad(evdev) - print('Kernel specified touchpad size: {:.1f}x{:.1f}mm'.format(touchpad.width, touchpad.height)) - print('User specified touchpad size: {:.1f}x{:.1f}mm'.format(*args.size)) + print( + "Kernel specified touchpad size: {:.1f}x{:.1f}mm".format( + touchpad.width, touchpad.height + ) + ) + print("User specified touchpad size: {:.1f}x{:.1f}mm".format(*args.size)) print() - print('Kernel axis range: x [{:4d}..{:4d}], y [{:4d}..{:4d}]'.format( - touchpad.x.minimum, touchpad.x.maximum, - touchpad.y.minimum, touchpad.y.maximum)) + print( + "Kernel axis range: x [{:4d}..{:4d}], y [{:4d}..{:4d}]".format( + touchpad.x.minimum, + touchpad.x.maximum, + touchpad.y.minimum, + touchpad.y.maximum, + ) + ) - print('Put your finger on the touchpad to start\033[1A') + print("Put your finger on the touchpad to start\033[1A") try: touchpad.draw() @@ -264,15 +285,27 @@ touchpad.erase() touchpad.update_from_data() - print('Detected axis range: x [{:4d}..{:4d}], y [{:4d}..{:4d}]'.format( - touchpad.x.minimum, touchpad.x.maximum, - touchpad.y.minimum, touchpad.y.maximum)) - - touchpad.x.resolution = round((touchpad.x.maximum - touchpad.x.minimum) / args.size[0]) - touchpad.y.resolution = round((touchpad.y.maximum - touchpad.y.minimum) / args.size[1]) - - print('Resolutions calculated based on user-specified size: x {}, y {} units/mm'.format( - touchpad.x.resolution, touchpad.y.resolution)) + print( + "Detected axis range: x [{:4d}..{:4d}], y [{:4d}..{:4d}]".format( + touchpad.x.minimum, + touchpad.x.maximum, + touchpad.y.minimum, + touchpad.y.maximum, + ) + ) + + touchpad.x.resolution = round( + (touchpad.x.maximum - touchpad.x.minimum) / args.size[0] + ) + touchpad.y.resolution = round( + (touchpad.y.maximum - touchpad.y.minimum) / args.size[1] + ) + + print( + "Resolutions calculated based on user-specified size: x {}, y {} units/mm".format( + touchpad.x.resolution, touchpad.y.resolution + ) + ) # If both x/y are within some acceptable deviation, we skip the axis # overrides and only override the resolution @@ -287,50 +320,73 @@ if skip: print() - print('Note: Axis ranges within acceptable deviation, skipping min/max override') + print( + "Note: Axis ranges within acceptable deviation, skipping min/max override" + ) print() print() - print('Suggested hwdb entry:') + print("Suggested hwdb entry:") - use_dmi = evdev.id['bustype'] not in [0x03, 0x05] # USB, Bluetooth + use_dmi = evdev.id["bustype"] not in [0x03, 0x05] # USB, Bluetooth if use_dmi: - modalias = open('/sys/class/dmi/id/modalias').read().strip() - print('Note: the dmi modalias match is a guess based on your machine\'s modalias:') - print(' ', modalias) - print('Please verify that this is the most sensible match and adjust if necessary.') + modalias = open("/sys/class/dmi/id/modalias").read().strip() + print( + "Note: the dmi modalias match is a guess based on your machine's modalias:" + ) + print(" ", modalias) + print( + "Please verify that this is the most sensible match and adjust if necessary." + ) - print('-8<--------------------------') - print('# Laptop model description (e.g. Lenovo X1 Carbon 5th)') + print("-8<--------------------------") + print("# Laptop model description (e.g. Lenovo X1 Carbon 5th)") if use_dmi: - print('evdev:name:{}:{}*'.format(evdev.name, dmi_modalias_match(modalias))) + print("evdev:name:{}:{}*".format(evdev.name, dmi_modalias_match(modalias))) else: - print('evdev:input:b{:04X}v{:04X}p{:04X}*'.format( - evdev.id['bustype'], evdev.id['vendor'], evdev.id['product'])) - print(' EVDEV_ABS_00={}:{}:{}'.format( - touchpad.x.minimum if not skip else '', - touchpad.x.maximum if not skip else '', - touchpad.x.resolution)) - print(' EVDEV_ABS_01={}:{}:{}'.format( - touchpad.y.minimum if not skip else '', - touchpad.y.maximum if not skip else '', - touchpad.y.resolution)) + print( + "evdev:input:b{:04X}v{:04X}p{:04X}*".format( + evdev.id["bustype"], evdev.id["vendor"], evdev.id["product"] + ) + ) + print( + " EVDEV_ABS_00={}:{}:{}".format( + touchpad.x.minimum if not skip else "", + touchpad.x.maximum if not skip else "", + touchpad.x.resolution, + ) + ) + print( + " EVDEV_ABS_01={}:{}:{}".format( + touchpad.y.minimum if not skip else "", + touchpad.y.maximum if not skip else "", + touchpad.y.resolution, + ) + ) if evdev.absinfo[libevdev.EV_ABS.ABS_MT_POSITION_X]: - print(' EVDEV_ABS_35={}:{}:{}'.format( - touchpad.x.minimum if not skip else '', - touchpad.x.maximum if not skip else '', - touchpad.x.resolution)) - print(' EVDEV_ABS_36={}:{}:{}'.format( - touchpad.y.minimum if not skip else '', - touchpad.y.maximum if not skip else '', - touchpad.y.resolution)) - print('-8<--------------------------') - print('Instructions on what to do with this snippet are in /usr/lib/udev/hwdb.d/60-evdev.hwdb') + print( + " EVDEV_ABS_35={}:{}:{}".format( + touchpad.x.minimum if not skip else "", + touchpad.x.maximum if not skip else "", + touchpad.x.resolution, + ) + ) + print( + " EVDEV_ABS_36={}:{}:{}".format( + touchpad.y.minimum if not skip else "", + touchpad.y.maximum if not skip else "", + touchpad.y.resolution, + ) + ) + print("-8<--------------------------") + print( + "Instructions on what to do with this snippet are in /usr/lib/udev/hwdb.d/60-evdev.hwdb" + ) except DeviceError as e: - print('Error: {}'.format(e), file=sys.stderr) + print("Error: {}".format(e), file=sys.stderr) return 1 except PermissionError: - print('Unable to open device. Please run me as root', file=sys.stderr) + print("Unable to open device. Please run me as root", file=sys.stderr) return 1 return 0 diff -Nru libinput-1.16.4/tools/libinput-measure-touchpad-tap.man libinput-1.17.2/tools/libinput-measure-touchpad-tap.man --- libinput-1.16.4/tools/libinput-measure-touchpad-tap.man 2020-11-27 01:38:59.400086200 +0000 +++ libinput-1.17.2/tools/libinput-measure-touchpad-tap.man 2021-04-30 04:25:41.546076300 +0000 @@ -66,7 +66,7 @@ .B WARNING: The data contained in the output is grouped by different sort orders. For example, the first few columns may list tap information in the 'natural' -sort order (i.e. as they occured), the data in the next few columns may list +sort order (i.e. as they occurred), the data in the next few columns may list tap information sorted by the delta time between touch down and touch up. Comparing columns across these group boundaries will compare data of two different touch points and result in invalid analysis. diff -Nru libinput-1.16.4/tools/libinput-measure-touchpad-tap.py libinput-1.17.2/tools/libinput-measure-touchpad-tap.py --- libinput-1.16.4/tools/libinput-measure-touchpad-tap.py 2020-11-27 01:38:59.400086200 +0000 +++ libinput-1.17.2/tools/libinput-measure-touchpad-tap.py 2021-04-30 04:25:41.546076300 +0000 @@ -26,14 +26,17 @@ import sys import argparse + try: import libevdev import textwrap import pyudev except ModuleNotFoundError as e: - print('Error: {}'.format(e), file=sys.stderr) - print('One or more python modules are missing. Please install those ' - 'modules and re-run this tool.') + print("Error: {}".format(e), file=sys.stderr) + print( + "One or more python modules are missing. Please install those " + "modules and re-run this tool." + ) sys.exit(1) print_dest = sys.stdout @@ -66,7 +69,7 @@ @up.setter def up(self, up): - assert(up > self.down) + assert up > self.down self._up = up @property @@ -88,7 +91,7 @@ self.path = self._find_touch_device() else: self.path = path - fd = open(self.path, 'rb') + fd = open(self.path, "rb") super().__init__(fd) print("Using {}: {}\n".format(self.name, self.path)) @@ -101,18 +104,19 @@ def _find_touch_device(self): context = pyudev.Context() device_node = None - for device in context.list_devices(subsystem='input'): - if (not device.device_node or - not device.device_node.startswith('/dev/input/event')): + for device in context.list_devices(subsystem="input"): + if not device.device_node or not device.device_node.startswith( + "/dev/input/event" + ): continue # pick the touchpad by default, fallback to the first # touchscreen only when there is no touchpad - if device.get('ID_INPUT_TOUCHPAD', 0): + if device.get("ID_INPUT_TOUCHPAD", 0): device_node = device.device_node break - if device.get('ID_INPUT_TOUCHSCREEN', 0) and device_node is None: + if device.get("ID_INPUT_TOUCHSCREEN", 0) and device_node is None: device_node = device.device_node if device_node is not None: @@ -127,17 +131,19 @@ self.touches.append(t) else: self.touches[-1].up = tv2us(event.sec, event.usec) - msg("\rTouch sequences detected: {}".format(len(self.touches)), - end='') + msg("\rTouch sequences detected: {}".format(len(self.touches)), end="") def handle_key(self, event): - tapcodes = [libevdev.EV_KEY.BTN_TOOL_DOUBLETAP, - libevdev.EV_KEY.BTN_TOOL_TRIPLETAP, - libevdev.EV_KEY.BTN_TOOL_QUADTAP, - libevdev.EV_KEY.BTN_TOOL_QUINTTAP] + tapcodes = [ + libevdev.EV_KEY.BTN_TOOL_DOUBLETAP, + libevdev.EV_KEY.BTN_TOOL_TRIPLETAP, + libevdev.EV_KEY.BTN_TOOL_QUADTAP, + libevdev.EV_KEY.BTN_TOOL_QUINTTAP, + ] if event.code in tapcodes and event.value > 0: - error("\rThis tool cannot handle multiple fingers, " - "output will be invalid") + error( + "\rThis tool cannot handle multiple fingers, " "output will be invalid" + ) return if event.matches(libevdev.EV_KEY.BTN_TOUCH): @@ -146,9 +152,11 @@ def handle_syn(self, event): if self.touch.dirty: self.current_sequence().append(self.touch) - self.touch = Touch(major=self.touch.major, - minor=self.touch.minor, - orientation=self.touch.orientation) + self.touch = Touch( + major=self.touch.major, + minor=self.touch.minor, + orientation=self.touch.orientation, + ) def handle_event(self, event): if event.matches(libevdev.EV_KEY): @@ -182,14 +190,16 @@ def print_dat(self): print("# libinput-measure-touchpad-tap") - print(textwrap.dedent('''\ + print( + textwrap.dedent( + """\ # File contents: # This file contains multiple prints of the data in # different sort order. Row number is index of touch # point within each group. Comparing data across groups # will result in invalid analysis. # Columns (1-indexed): - # Group 1, sorted by time of occurence + # Group 1, sorted by time of occurrence # 1: touch down time in ms, offset by first event # 2: touch up time in ms, offset by first event # 3: time delta in ms); @@ -197,7 +207,9 @@ # 4: touch down time in ms, offset by first event # 5: touch up time in ms, offset by first event # 6: time delta in ms - ''')) + """ + ) + ) deltas = [t for t in self.touches] deltas_sorted = sorted(deltas, key=lambda t: t.tdelta) @@ -205,28 +217,44 @@ offset = deltas[0].down for t1, t2 in zip(deltas, deltas_sorted): - print(t1.down - offset, t1.up - offset, t1.tdelta, - t2.down - offset, t2.up - offset, t2.tdelta) + print( + t1.down - offset, + t1.up - offset, + t1.tdelta, + t2.down - offset, + t2.up - offset, + t2.tdelta, + ) def print(self, format): if not self.touches: error("No tap data available") return - if format == 'summary': + if format == "summary": self.print_summary() - elif format == 'dat': + elif format == "dat": self.print_dat() def main(args): - parser = argparse.ArgumentParser(description="Measure tap-to-click properties of devices") - parser.add_argument('path', metavar='/dev/input/event0', - nargs='?', type=str, help='Path to device (optional)') - parser.add_argument('--format', metavar='format', - choices=['summary', 'dat'], - default='summary', - help='data format to print ("summary" or "dat")') + parser = argparse.ArgumentParser( + description="Measure tap-to-click properties of devices" + ) + parser.add_argument( + "path", + metavar="/dev/input/event0", + nargs="?", + type=str, + help="Path to device (optional)", + ) + parser.add_argument( + "--format", + metavar="format", + choices=["summary", "dat"], + default="summary", + help='data format to print ("summary" or "dat")', + ) args = parser.parse_args() if not sys.stdout.isatty(): @@ -235,13 +263,15 @@ try: device = Device(args.path) - error("Ready for recording data.\n" - "Tap the touchpad multiple times with a single finger only.\n" - "For useful data we recommend at least 20 taps.\n" - "Ctrl+C to exit") + error( + "Ready for recording data.\n" + "Tap the touchpad multiple times with a single finger only.\n" + "For useful data we recommend at least 20 taps.\n" + "Ctrl+C to exit" + ) device.read_events() except KeyboardInterrupt: - msg('') + msg("") device.print(args.format) except (PermissionError, OSError) as e: error("Error: failed to open device. {}".format(e)) diff -Nru libinput-1.16.4/tools/libinput-measure-touch-size.py libinput-1.17.2/tools/libinput-measure-touch-size.py --- libinput-1.16.4/tools/libinput-measure-touch-size.py 2020-11-27 01:38:59.400086200 +0000 +++ libinput-1.17.2/tools/libinput-measure-touch-size.py 2021-04-30 04:25:41.545076400 +0000 @@ -27,21 +27,25 @@ import sys import subprocess import argparse + try: import libevdev import pyudev except ModuleNotFoundError as e: - print('Error: {}'.format(str(e)), file=sys.stderr) - print('One or more python modules are missing. Please install those ' - 'modules and re-run this tool.') + print("Error: {}".format(str(e)), file=sys.stderr) + print( + "One or more python modules are missing. Please install those " + "modules and re-run this tool." + ) sys.exit(1) class Range(object): """Class to keep a min/max of a value around""" + def __init__(self): - self.min = float('inf') - self.max = float('-inf') + self.min = float("inf") + self.max = float("-inf") def update(self, value): self.min = min(self.min, value) @@ -148,7 +152,9 @@ self.major_range.min, self.major_range.max ) if self.device.has_minor: - s += "minor: [{:3d}..{:3d}] ".format(self.minor_range.min, self.minor_range.max) + s += "minor: [{:3d}..{:3d}] ".format( + self.minor_range.min, self.minor_range.max + ) if self.was_down: s += " down" if self.was_palm: @@ -160,10 +166,12 @@ def _str_state(self): touch = self.points[-1] - s = "{}, tags: {} {} {}".format(touch, - "down" if self.is_down else " ", - "palm" if self.is_palm else " ", - "thumb" if self.is_thumb else " ") + s = "{}, tags: {} {} {}".format( + touch, + "down" if self.is_down else " ", + "palm" if self.is_palm else " ", + "thumb" if self.is_thumb else " ", + ) return s @@ -178,7 +186,7 @@ else: self.path = path - fd = open(self.path, 'rb') + fd = open(self.path, "rb") super().__init__(fd) print("Using {}: {}\n".format(self.name, self.path)) @@ -200,13 +208,15 @@ def find_touch_device(self): context = pyudev.Context() - for device in context.list_devices(subsystem='input'): - if not device.get('ID_INPUT_TOUCHPAD', 0) and \ - not device.get('ID_INPUT_TOUCHSCREEN', 0): + for device in context.list_devices(subsystem="input"): + if not device.get("ID_INPUT_TOUCHPAD", 0) and not device.get( + "ID_INPUT_TOUCHSCREEN", 0 + ): continue - if not device.device_node or \ - not device.device_node.startswith('/dev/input/event'): + if not device.device_node or not device.device_node.startswith( + "/dev/input/event" + ): continue return device.device_node @@ -215,21 +225,24 @@ sys.exit(1) def _init_thresholds_from_quirks(self): - command = ['libinput', 'quirks', 'list', self.path] + command = ["libinput", "quirks", "list", self.path] cmd = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if cmd.returncode != 0: - print("Error querying quirks: {}".format(cmd.stderr.decode('utf-8')), file=sys.stderr) + print( + "Error querying quirks: {}".format(cmd.stderr.decode("utf-8")), + file=sys.stderr, + ) return - stdout = cmd.stdout.decode('utf-8') - quirks = [q.split('=') for q in stdout.split('\n')] + stdout = cmd.stdout.decode("utf-8") + quirks = [q.split("=") for q in stdout.split("\n")] for q in quirks: - if q[0] == 'AttrPalmSizeThreshold': + if q[0] == "AttrPalmSizeThreshold": self.palm = int(q[1]) - elif q[0] == 'AttrTouchSizeRange': + elif q[0] == "AttrTouchSizeRange": self.down, self.up = colon_tuple(q[1]) - elif q[0] == 'AttrThumbSizeThreshold': + elif q[0] == "AttrThumbSizeThreshold": self.thumb = int(q[1]) def start_new_sequence(self, tracking_id): @@ -239,13 +252,17 @@ return self.sequences[-1] def handle_key(self, event): - tapcodes = [libevdev.EV_KEY.BTN_TOOL_DOUBLETAP, - libevdev.EV_KEY.BTN_TOOL_TRIPLETAP, - libevdev.EV_KEY.BTN_TOOL_QUADTAP, - libevdev.EV_KEY.BTN_TOOL_QUINTTAP] + tapcodes = [ + libevdev.EV_KEY.BTN_TOOL_DOUBLETAP, + libevdev.EV_KEY.BTN_TOOL_TRIPLETAP, + libevdev.EV_KEY.BTN_TOOL_QUADTAP, + libevdev.EV_KEY.BTN_TOOL_QUINTTAP, + ] if event.code in tapcodes and event.value > 0: - print("\rThis tool cannot handle multiple fingers, " - "output will be invalid", file=sys.stderr) + print( + "\rThis tool cannot handle multiple fingers, " "output will be invalid", + file=sys.stderr, + ) def handle_abs(self, event): if event.matches(libevdev.EV_ABS.ABS_MT_TRACKING_ID): @@ -271,9 +288,11 @@ try: self.current_sequence().append(self.touch) print("\r{}".format(self.current_sequence()), end="") - self.touch = Touch(major=self.touch.major, - minor=self.touch.minor, - orientation=self.touch.orientation) + self.touch = Touch( + major=self.touch.major, + minor=self.touch.minor, + orientation=self.touch.orientation, + ) except IndexError: pass @@ -290,8 +309,10 @@ print("Touch sizes used: {}:{}".format(self.down, self.up)) print("Palm size used: {}".format(self.palm)) print("Thumb size used: {}".format(self.thumb)) - print("Place a single finger on the device to measure touch size.\n" - "Ctrl+C to exit\n") + print( + "Place a single finger on the device to measure touch size.\n" + "Ctrl+C to exit\n" + ) while True: for event in self.events(): @@ -300,11 +321,11 @@ def colon_tuple(string): try: - ts = string.split(':') + ts = string.split(":") t = tuple([int(x) for x in ts]) if len(t) == 2 and t[0] >= t[1]: return t - except: # noqa + except: # noqa pass msg = "{} is not in format N:M (N >= M)".format(string) @@ -313,13 +334,25 @@ def main(args): parser = argparse.ArgumentParser(description="Measure touch size and orientation") - parser.add_argument('path', metavar='/dev/input/event0', - nargs='?', type=str, help='Path to device (optional)') - parser.add_argument('--touch-thresholds', metavar='down:up', - type=colon_tuple, - help='Thresholds when a touch is logically down or up') - parser.add_argument('--palm-threshold', metavar='t', - type=int, help='Threshold when a touch is a palm') + parser.add_argument( + "path", + metavar="/dev/input/event0", + nargs="?", + type=str, + help="Path to device (optional)", + ) + parser.add_argument( + "--touch-thresholds", + metavar="down:up", + type=colon_tuple, + help="Thresholds when a touch is logically down or up", + ) + parser.add_argument( + "--palm-threshold", + metavar="t", + type=int, + help="Threshold when a touch is a palm", + ) args = parser.parse_args() try: @@ -337,7 +370,9 @@ except (PermissionError, OSError): print("Error: failed to open device") except InvalidDeviceError as e: - print("This device does not have the capabilities for size-based touch detection.") + print( + "This device does not have the capabilities for size-based touch detection." + ) print("Details: {}".format(e)) diff -Nru libinput-1.16.4/tools/libinput-quirks.c libinput-1.17.2/tools/libinput-quirks.c --- libinput-1.16.4/tools/libinput-quirks.c 2020-11-27 01:38:59.400086200 +0000 +++ libinput-1.17.2/tools/libinput-quirks.c 2021-04-30 04:25:41.546076300 +0000 @@ -191,6 +191,9 @@ } udev = udev_new(); + if (!udev) + goto out; + path = argv[optind]; if (strneq(path, "/sys/", 5)) { device = udev_device_new_from_syspath(udev, path); diff -Nru libinput-1.16.4/tools/libinput-record.c libinput-1.17.2/tools/libinput-record.c --- libinput-1.16.4/tools/libinput-record.c 2020-11-27 01:38:59.403086200 +0000 +++ libinput-1.17.2/tools/libinput-record.c 2021-04-30 04:25:41.546076300 +0000 @@ -24,11 +24,13 @@ #include "config.h" #include +#include #include #include #include #include #include +#include #include #include #include @@ -112,9 +114,48 @@ unsigned int indent; struct libinput *libinput; + + int epoll_fd; + struct list sources; + + struct { + bool had_events_since_last_time; + bool skipped_timer_print; + } timestamps; + + bool had_events; + bool stop; }; -static inline bool +#define resize(array_, sz_) \ +{ \ + size_t new_size = (sz_) + 1000; \ + void *tmp = realloc((array_), new_size * sizeof(*(array_))); \ + assert(tmp); \ + (array_) = tmp; \ + (sz_) = new_size; \ +} + +static struct event * +next_event(struct record_device *d) +{ + if (d->nevents == d->events_sz) + resize(d->events, d->events_sz); + return &d->events[d->nevents++]; +} + +typedef void (*source_dispatch_t)(struct record_context *ctx, + int fd, + void *user_data); + +struct source { + source_dispatch_t dispatch; + void *user_data; + int fd; + struct list link; +}; + +static bool obfuscate_keycode(struct input_event *ev) { switch (ev->type) { @@ -135,13 +176,13 @@ return false; } -static inline void +static void indent_push(struct record_context *ctx) { ctx->indent += 2; } -static inline void +static void indent_pop(struct record_context *ctx) { assert(ctx->indent >= 2); @@ -149,9 +190,9 @@ } /** - * Indented dprintf, indentation is given as second parameter. + * Indented dprintf, indentation is in the context */ -static inline void +static void iprintf(const struct record_context *ctx, const char *format, ...) { va_list args; @@ -184,7 +225,7 @@ /** * Normal printf, just wrapped for the context */ -static inline void +static void noiprintf(const struct record_context *ctx, const char *format, ...) { va_list args; @@ -196,13 +237,13 @@ assert(rc != -1 && (unsigned int)rc > 0); } -static inline uint64_t +static uint64_t time_offset(struct record_context *ctx, uint64_t time) { return ctx->offset ? time - ctx->offset : 0; } -static inline void +static void print_evdev_event(struct record_context *ctx, struct record_device *dev, struct input_event *ev) @@ -341,16 +382,7 @@ desc); } -#define resize(array_, sz_) \ -{ \ - size_t new_size = (sz_) + 1000; \ - void *tmp = realloc((array_), new_size * sizeof(*(array_))); \ - assert(tmp); \ - (array_) = tmp; \ - (sz_) = new_size; \ -} - -static inline size_t +static size_t handle_evdev_frame(struct record_context *ctx, struct record_device *d) { struct libevdev *evdev = d->evdev; @@ -369,10 +401,7 @@ else time = time_offset(ctx, time); - if (d->nevents == d->events_sz) - resize(d->events, d->events_sz); - - event = &d->events[d->nevents++]; + event = next_event(d); event->type = EVDEV; event->time = time; event->u.evdev = e; @@ -398,11 +427,8 @@ if (d->touch.slot_state != d->touch.last_slot_state) { d->touch.last_slot_state = d->touch.slot_state; - if (d->nevents == d->events_sz) - resize(d->events, d->events_sz); - if (d->touch.slot_state == 0) { - event = &d->events[d->nevents++]; + event = next_event(d); event->type = COMMENT; event->time = last_time; snprintf(event->u.comment, @@ -1348,7 +1374,7 @@ indent_pop(ctx); } -static inline size_t +static size_t handle_libinput_events(struct record_context *ctx, struct record_device *d) { @@ -1375,10 +1401,7 @@ assert(found); } - if (current->nevents == current->events_sz) - resize(current->events, current->events_sz); - - event = ¤t->events[current->nevents++]; + event = next_event(current); event->type = LIBINPUT; buffer_libinput_event(ctx, e, event); @@ -1389,7 +1412,7 @@ return count; } -static inline void +static void handle_events(struct record_context *ctx, struct record_device *d, bool print) { while(true) { @@ -1412,7 +1435,7 @@ } } -static inline void +static void print_libinput_header(struct record_context *ctx) { iprintf(ctx, "libinput:\n"); @@ -1424,7 +1447,7 @@ indent_pop(ctx); } -static inline void +static void print_system_header(struct record_context *ctx) { struct utsname u; @@ -1480,16 +1503,17 @@ indent_pop(ctx); } -static inline void +static void print_header(struct record_context *ctx) { + iprintf(ctx, "# libinput record\n"); iprintf(ctx, "version: %d\n", FILE_VERSION_NUMBER); iprintf(ctx, "ndevices: %d\n", ctx->ndevices); print_libinput_header(ctx); print_system_header(ctx); } -static inline void +static void print_description_abs(struct record_context *ctx, struct libevdev *dev, unsigned int code) @@ -1507,7 +1531,7 @@ iprintf(ctx, "# Resolution %6d\n", abs->resolution); } -static inline void +static void print_description_state(struct record_context *ctx, struct libevdev *dev, unsigned int type, @@ -1517,7 +1541,7 @@ iprintf(ctx, "# State %d\n", state); } -static inline void +static void print_description_codes(struct record_context *ctx, struct libevdev *dev, unsigned int type) @@ -1558,7 +1582,7 @@ } } -static inline void +static void print_description(struct record_context *ctx, struct libevdev *dev) { const struct input_absinfo *x, *y; @@ -1607,7 +1631,7 @@ } } -static inline void +static void print_bits_info(struct record_context *ctx, struct libevdev *dev) { iprintf(ctx, "name: \"%s\"\n", libevdev_get_name(dev)); @@ -1619,7 +1643,7 @@ libevdev_get_id_version(dev)); } -static inline void +static void print_bits_absinfo(struct record_context *ctx, struct libevdev *dev) { const struct input_absinfo *abs; @@ -1647,13 +1671,13 @@ indent_pop(ctx); } -static inline void +static void print_bits_codes(struct record_context *ctx, struct libevdev *dev, unsigned int type) { int max; - bool first = true; + const char *sep = ""; max = libevdev_event_type_get_max(type); if (max == -1) @@ -1665,14 +1689,14 @@ if (!libevdev_has_event_code(dev, type, code)) continue; - noiprintf(ctx, "%s%d", first ? "" : ", ", code); - first = false; + noiprintf(ctx, "%s%d", sep, code); + sep = ", "; } noiprintf(ctx, "] # %s\n", libevdev_event_type_get_name(type)); } -static inline void +static void print_bits_types(struct record_context *ctx, struct libevdev *dev) { iprintf(ctx, "codes:\n"); @@ -1685,22 +1709,22 @@ indent_pop(ctx); } -static inline void +static void print_bits_props(struct record_context *ctx, struct libevdev *dev) { - bool first = true; + const char *sep = ""; iprintf(ctx, "properties: ["); for (unsigned int prop = 0; prop < INPUT_PROP_CNT; prop++) { if (libevdev_has_property(dev, prop)) { - noiprintf(ctx, "%s%d", first ? "" : ", ", prop); - first = false; + noiprintf(ctx, "%s%d", sep, prop); + sep = ", "; } } noiprintf(ctx, "]\n"); /* last entry, no comma */ } -static inline void +static void print_evdev_description(struct record_context *ctx, struct record_device *dev) { struct libevdev *evdev = dev->evdev; @@ -1717,32 +1741,29 @@ indent_pop(ctx); } -static inline void +static void print_hid_report_descriptor(struct record_context *ctx, struct record_device *dev) { const char *prefix = "/dev/input/event"; - const char *node; char syspath[PATH_MAX]; unsigned char buf[1024]; int len; int fd; - bool first = true; + const char *sep = ""; /* we take the shortcut rather than the proper udev approach, the report_descriptor is available in sysfs and two devices up from - our device. 2 digits for the event number should be enough. + our device. This approach won't work for /dev/input/by-id devices. */ - if (!strstartswith(dev->devnode, prefix) || - strlen(dev->devnode) > strlen(prefix) + 2) + if (!strstartswith(dev->devnode, prefix)) return; - node = &dev->devnode[strlen(prefix)]; len = snprintf(syspath, sizeof(syspath), - "/sys/class/input/event%s/device/device/report_descriptor", - node); - if (len < 55 || len > 56) + "/sys/class/input/%s/device/device/report_descriptor", + safe_basename(dev->devnode)); + if (len <= 0) return; fd = open(syspath, O_RDONLY); @@ -1754,16 +1775,16 @@ while ((len = read(fd, buf, sizeof(buf))) > 0) { for (int i = 0; i < len; i++) { /* YAML requires decimal */ - noiprintf(ctx, "%s%u",first ? "" : ", ", buf[i]); - first = false; + noiprintf(ctx, "%s%u", sep, buf[i]); + sep = ", "; } } - noiprintf(ctx, " ]\n"); + noiprintf(ctx, "]\n"); close(fd); } -static inline void +static void print_udev_properties(struct record_context *ctx, struct record_device *dev) { struct udev *udev = NULL; @@ -1829,7 +1850,7 @@ iprintf(ctx, "- %s\n", val); } -static inline void +static void print_device_quirks(struct record_context *ctx, struct record_device *dev) { struct udev *udev = NULL; @@ -1883,7 +1904,8 @@ udev_unref(udev); quirks_context_unref(quirks); } -static inline void + +static void print_libinput_description(struct record_context *ctx, struct record_device *dev) { @@ -1902,7 +1924,7 @@ {LIBINPUT_DEVICE_CAP_SWITCH, "switch"}, }; struct cap *cap; - bool is_first; + const char *sep = ""; if (!device) return; @@ -1914,12 +1936,11 @@ iprintf(ctx, "size: [%.f, %.f]\n", w, h); iprintf(ctx, "capabilities: ["); - is_first = true; ARRAY_FOR_EACH(caps, cap) { if (!libinput_device_has_capability(device, cap->cap)) continue; - noiprintf(ctx, "%s%s", is_first ? "" : ", ", cap->name); - is_first = false; + noiprintf(ctx, "%s%s", sep, cap->name); + sep = ", "; } noiprintf(ctx, "]\n"); @@ -1931,7 +1952,7 @@ indent_pop(ctx); } -static inline void +static void print_device_description(struct record_context *ctx, struct record_device *dev) { iprintf(ctx, "- node: %s\n", dev->devnode); @@ -1947,7 +1968,7 @@ return strneq(dir->d_name, "event", 5); } -static inline char * +static char * select_device(void) { struct dirent **namelist; @@ -1956,12 +1977,16 @@ char *device_path; bool has_eaccess = false; int available_devices = 0; + const char *prefix = ""; + + if (!isatty(STDERR_FILENO)) + prefix = "# "; ndev = scandir("/dev/input", &namelist, is_event_node, versionsort); if (ndev <= 0) return NULL; - fprintf(stderr, "Available devices:\n"); + fprintf(stderr, "%sAvailable devices:\n", prefix); for (int i = 0; i < ndev; i++) { struct libevdev *device; char path[PATH_MAX]; @@ -1983,7 +2008,7 @@ if (rc != 0) continue; - fprintf(stderr, "%s: %s\n", path, libevdev_get_name(device)); + fprintf(stderr, "%s%s: %s\n", prefix, path, libevdev_get_name(device)); libevdev_free(device); available_devices++; } @@ -1993,14 +2018,13 @@ free(namelist); if (available_devices == 0) { - fprintf(stderr, "No devices available. "); - if (has_eaccess) - fprintf(stderr, "Please re-run as root."); - fprintf(stderr, "\n"); + fprintf(stderr, + "No devices available.%s\n", + has_eaccess ? " Please re-run as root." : ""); return NULL; } - fprintf(stderr, "Select the device event number: "); + fprintf(stderr, "%sSelect the device event number: ", prefix); rc = scanf("%d", &selected_device); if (rc != 1 || selected_device < 0) @@ -2013,7 +2037,7 @@ return device_path; } -static inline char ** +static char ** all_devices(void) { struct dirent **namelist; @@ -2094,7 +2118,7 @@ return true; } -static inline void +static void print_progress_bar(void) { static uint8_t foo = 0; @@ -2107,58 +2131,206 @@ fprintf(stderr, "\rReceiving events: [%*s%*s]", foo, "*", 21 - foo, " "); } +static void +print_wall_time(struct record_context *ctx) +{ + time_t t = time(NULL); + struct tm tm; + + localtime_r(&t, &tm); + iprintf(ctx, "# Current time is %02d:%02d:%02d\n", tm.tm_hour, tm.tm_min, tm.tm_sec); +} + +static void +arm_timer(int timerfd) +{ + time_t t = time(NULL); + struct tm tm; + struct itimerspec interval = { + .it_value = { 0, 0 }, + .it_interval = { 5, 0 }, + }; + + localtime_r(&t, &tm); + interval.it_value.tv_sec = 5 - (tm.tm_sec % 5); + timerfd_settime(timerfd, 0, &interval, NULL); +} + +static struct source * +add_source(struct record_context *ctx, + int fd, + source_dispatch_t dispatch, + void *user_data) +{ + struct source *source; + struct epoll_event ep; + + assert(fd != -1); + + source = zalloc(sizeof *source); + source->dispatch = dispatch; + source->user_data = user_data; + source->fd = fd; + list_append(&ctx->sources, &source->link); + + memset(&ep, 0, sizeof ep); + ep.events = EPOLLIN; + ep.data.ptr = source; + + if (epoll_ctl(ctx->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) { + free(source); + return NULL; + } + + return source; +} + +static void +destroy_source(struct record_context *ctx, struct source *source) +{ + list_remove(&source->link); + epoll_ctl(ctx->epoll_fd, EPOLL_CTL_DEL, source->fd, NULL); + close(source->fd); + free(source); +} + +static void +signalfd_dispatch(struct record_context *ctx, int fd, void *data) +{ + struct signalfd_siginfo fdsi; + + (void)read(fd, &fdsi, sizeof(fdsi)); + + ctx->stop = true; +} + +static void +timefd_dispatch(struct record_context *ctx, int fd, void *data) +{ + char discard[64]; + + (void)read(fd, discard, sizeof(discard)); + + if (ctx->timestamps.had_events_since_last_time) { + print_wall_time(ctx); + ctx->timestamps.had_events_since_last_time = false; + ctx->timestamps.skipped_timer_print = false; + } else { + ctx->timestamps.skipped_timer_print = true; + } +} + +static void +evdev_dispatch(struct record_context *ctx, int fd, void *data) +{ + struct record_device *first_device = NULL; + struct record_device *this_device = data; + + if (ctx->timestamps.skipped_timer_print) { + print_wall_time(ctx); + ctx->timestamps.skipped_timer_print = false; + } + + ctx->had_events = true; + ctx->timestamps.had_events_since_last_time = true; + + first_device = list_first_entry(&ctx->devices, first_device, link); + handle_events(ctx, this_device, this_device == first_device); +} + +static void +libinput_ctx_dispatch(struct record_context *ctx, int fd, void *data) +{ + struct record_device *first_device = NULL; + size_t count, offset; + + /* This function should only handle events caused by internal + * timeouts etc. The real input events caused by the evdev devices + * are already processed in handle_events */ + first_device = list_first_entry(&ctx->devices, first_device, link); + libinput_dispatch(ctx->libinput); + offset = first_device->nevents; + count = handle_libinput_events(ctx, first_device); + if (count) { + print_cached_events(ctx, + first_device, + offset, + count); + } +} + +static int +dispatch_sources(struct record_context *ctx) +{ + struct source *source; + struct epoll_event ep[64]; + int i, count; + + count = epoll_wait(ctx->epoll_fd, ep, ARRAY_LENGTH(ep), ctx->timeout); + if (count < 0) + return -errno; + + for (i = 0; i < count; ++i) { + source = ep[i].data.ptr; + if (source->fd == -1) + continue; + source->dispatch(ctx, source->fd, source->user_data); + } + + return count; +} + static int mainloop(struct record_context *ctx) { bool autorestart = (ctx->timeout > 0); - struct pollfd fds[ctx->ndevices + 2]; - unsigned int nfds = 0; + struct source *source, *tmp; struct record_device *d = NULL; - struct record_device *first_device = NULL; - struct timespec ts; sigset_t mask; + int sigfd, timerfd; assert(ctx->timeout != 0); assert(!list_empty(&ctx->devices)); + ctx->epoll_fd = epoll_create1(0); + assert(ctx->epoll_fd >= 0); + sigemptyset(&mask); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGQUIT); sigprocmask(SIG_BLOCK, &mask, NULL); - fds[0].fd = signalfd(-1, &mask, SFD_NONBLOCK); - fds[0].events = POLLIN; - fds[0].revents = 0; - assert(fds[0].fd != -1); - nfds++; + sigfd = signalfd(-1, &mask, SFD_NONBLOCK); + add_source(ctx, sigfd, signalfd_dispatch, NULL); - if (ctx->libinput) { - fds[1].fd = libinput_get_fd(ctx->libinput); - fds[1].events = POLLIN; - fds[1].revents = 0; - nfds++; - assert(nfds == 2); - } + timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC|TFD_NONBLOCK); + add_source(ctx, timerfd, timefd_dispatch, NULL); + arm_timer(timerfd); list_for_each(d, &ctx->devices, link) { - fds[nfds].fd = libevdev_get_fd(d->evdev); - fds[nfds].events = POLLIN; - fds[nfds].revents = 0; - assert(fds[nfds].fd != -1); - nfds++; + add_source(ctx, libevdev_get_fd(d->evdev), evdev_dispatch, d); + } + + if (ctx->libinput) { + /* See the note in the dispatch function */ + add_source(ctx, + libinput_get_fd(ctx->libinput), + libinput_ctx_dispatch, + NULL); } /* If we have more than one device, the time starts at recording * start time. Otherwise, the first event starts the recording time. */ if (ctx->ndevices > 1) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); ctx->offset = s2us(ts.tv_sec) + ns2us(ts.tv_nsec); } do { - int rc; - bool had_events = false; /* we delete files without events */ + struct record_device *first_device = NULL; if (!open_output_file(ctx, autorestart)) { fprintf(stderr, @@ -2166,7 +2338,11 @@ ctx->output_file); break; } - fprintf(stderr, "Recording to '%s'.\n", ctx->output_file); + fprintf(stderr, "%sRecording to '%s'.\n", + isatty(STDERR_FILENO) ? "" : "# ", + ctx->output_file); + + ctx->had_events = false; print_header(ctx); if (autorestart) @@ -2184,6 +2360,7 @@ link); print_device_description(ctx, first_device); + print_wall_time(ctx); iprintf(ctx, "events:\n"); indent_push(ctx); @@ -2195,47 +2372,23 @@ } while (true) { - rc = poll(fds, nfds, ctx->timeout); - if (rc == -1) { /* error */ - fprintf(stderr, "Error: %m\n"); - autorestart = false; + int rc = dispatch_sources(ctx); + if (rc < 0) { /* error */ + fprintf(stderr, "Error: %s\n", strerror(-rc)); + ctx->stop = true; + break; + } + + /* set by the signalfd handler */ + if (ctx->stop) break; - } else if (rc == 0) { + + if (rc == 0) { fprintf(stderr, " ... timeout%s\n", - had_events ? "" : " (file is empty)"); + ctx->had_events ? "" : " (file is empty)"); break; - } else if (fds[0].revents != 0) { /* signal */ - autorestart = false; - break; - } - /* Pull off the evdev events first since they cause - * libinput events. - * handle_events de-queues libinput events so by the - * time we finish that, we hopefully have all evdev - * events and libinput events roughly in sync. - */ - had_events = true; - list_for_each(d, &ctx->devices, link) - handle_events(ctx, d, d == first_device); - - /* This shouldn't pull any events off unless caused - * by libinput-internal timeouts (e.g. tapping) */ - if (ctx->libinput && fds[1].revents) { - size_t count, offset; - - libinput_dispatch(ctx->libinput); - offset = first_device->nevents; - count = handle_libinput_events(ctx, - first_device); - if (count) { - print_cached_events(ctx, - first_device, - offset, - count); - } - rc--; } if (ctx->out_fd != STDOUT_FILENO) @@ -2270,7 +2423,7 @@ /* If we didn't have events, delete the file. */ if (!isatty(ctx->out_fd)) { - if (!had_events && ctx->output_file) { + if (!ctx->had_events && ctx->output_file) { fprintf(stderr, "No events recorded, deleting '%s'\n", ctx->output_file); unlink(ctx->output_file); } @@ -2280,17 +2433,20 @@ } free(ctx->output_file); ctx->output_file = NULL; - } while (autorestart); - - close(fds[0].fd); + } while (autorestart && !ctx->stop); sigprocmask(SIG_UNBLOCK, &mask, NULL); + list_for_each_safe(source, tmp, &ctx->sources, link) { + destroy_source(ctx, source); + } + close(ctx->epoll_fd); + return 0; } -static inline bool -init_device(struct record_context *ctx, char *path) +static bool +init_device(struct record_context *ctx, char *path, bool grab) { struct record_device *d; int fd, rc; @@ -2320,6 +2476,17 @@ goto error; } + if (grab) { + rc = libevdev_grab(d->evdev, LIBEVDEV_GRAB); + if (rc != 0) { + fprintf(stderr, + "Grab failed on %s: %s\n", + path, + strerror(-rc)); + goto error; + } + } + libevdev_set_clock_id(d->evdev, CLOCK_MONOTONIC); if (libevdev_get_num_slots(d->evdev) > 0) @@ -2352,7 +2519,7 @@ .close_restricted = close_restricted, }; -static inline bool +static bool init_libinput(struct record_context *ctx) { struct record_device *dev; @@ -2386,7 +2553,7 @@ return true; } -static inline void +static void usage(void) { printf("Usage: %s [--help] [--all] [--autorestart] [--output-file filename] [/dev/input/event0] [...]\n" @@ -2417,7 +2584,8 @@ F_NOEXIST, }; -static inline enum ftype is_char_dev(const char *path) +static enum ftype +is_char_dev(const char *path) { struct stat st; @@ -2441,6 +2609,7 @@ OPT_MULTIPLE, OPT_ALL, OPT_LIBINPUT, + OPT_GRAB, }; int @@ -2458,15 +2627,17 @@ { "all", no_argument, 0, OPT_ALL }, { "help", no_argument, 0, OPT_HELP }, { "with-libinput", no_argument, 0, OPT_LIBINPUT }, + { "grab", no_argument, 0, OPT_GRAB }, { 0, 0, 0, 0 }, }; struct record_device *d, *tmp; const char *output_arg = NULL; - bool all = false, with_libinput = false; + bool all = false, with_libinput = false, grab = false; int ndevices; int rc = EXIT_FAILURE; list_init(&ctx.devices); + list_init(&ctx.sources); while (1) { int c; @@ -2506,6 +2677,9 @@ case OPT_LIBINPUT: with_libinput = true; break; + case OPT_GRAB: + grab = true; + break; default: usage(); rc = EXIT_INVALID_USAGE; @@ -2603,7 +2777,7 @@ d = devices; while (*d) { - if (!init_device(&ctx, safe_strdup(*d))) { + if (!init_device(&ctx, safe_strdup(*d), grab)) { strv_free(devices); goto out; } @@ -2622,7 +2796,7 @@ for (int i = ndevices; i > 0; i -= 1) { char *devnode = safe_strdup(argv[optind + i - 1]); - if (!init_device(&ctx, devnode)) + if (!init_device(&ctx, devnode, grab)) goto out; } } else { @@ -2633,7 +2807,7 @@ goto out; } - if (!init_device(&ctx, path)) + if (!init_device(&ctx, path, grab)) goto out; } diff -Nru libinput-1.16.4/tools/libinput-record.man libinput-1.17.2/tools/libinput-record.man --- libinput-1.16.4/tools/libinput-record.man 2020-11-27 01:38:59.403086200 +0000 +++ libinput-1.17.2/tools/libinput-record.man 2021-04-30 04:25:41.546076300 +0000 @@ -58,6 +58,10 @@ not an input device, the first \fBor\fR last argument will be the output file. .TP 8 +.B \-\-grab +Exclusively grab all opened devices. This will prevent events from being +delivered to the host system. +.TP 8 .B \-\-show\-keycodes Show keycodes as-is in the recording. By default, common keys are obfuscated and printed as \fBKEY_A\fR to avoid information leaks. @@ -86,9 +90,9 @@ immediately, all other devices and their events are printed on exit. .SH RECORDING LIBINPUT EVENTS -When the \fB\-\-with-libinput\fR switch is provided, \fBlibinput\-record\fR -initializes a libinput context for the devices being recorded. Events from -these contexts are printed alongside the evdev events. +When the \fB\-\-with-libinput\fR commandline option is given, +\fBlibinput\-record\fR initializes a libinput context for the devices being +recorded. Events from these contexts are printed alongside the evdev events. .B THIS FEATURE IS EXPERIMENTAL. .PP The primary purpose of this feature is debugging and event analysis, no @@ -281,8 +285,8 @@ Information about the events. The content is a list of dictionaries, with the string identifying the type of event sequence. .TP 8 -.B { evdev: [ {"data": [sec, usec, type, code, value]}, ...] } -Each \fBinput_event\fR dictionary contains the contents of a \fBstruct +.B { evdev: [ [sec, usec, type, code, value], ...] } +Each \fBevdev\fR dictionary contains the contents of a \fBstruct input_event\fR in decimal format. The last item in the list is always the \fBSYN_REPORT\fR of this event frame. The next event frame starts a new \fBevdev\fR dictionary entry in the parent \fBevents\fR list. diff -Nru libinput-1.16.4/tools/libinput-record-verify-yaml.py libinput-1.17.2/tools/libinput-record-verify-yaml.py --- libinput-1.16.4/tools/libinput-record-verify-yaml.py 2020-11-27 01:38:59.402086000 +0000 +++ libinput-1.17.2/tools/libinput-record-verify-yaml.py 2021-04-30 04:25:41.546076300 +0000 @@ -34,7 +34,7 @@ class TestYaml(unittest.TestCase): - filename = '' + filename = "" @classmethod def setUpClass(cls): @@ -42,163 +42,166 @@ cls.yaml = yaml.safe_load(f) def dict_key_crosscheck(self, d, keys): - '''Check that each key in d is in keys, and that each key is in d''' + """Check that each key in d is in keys, and that each key is in d""" self.assertEqual(sorted(d.keys()), sorted(keys)) def libinput_events(self, filter=None): - '''Returns all libinput events in the recording, regardless of the - device''' - devices = self.yaml['devices'] + """Returns all libinput events in the recording, regardless of the + device""" + devices = self.yaml["devices"] for d in devices: - events = d['events'] + events = d["events"] if not events: raise unittest.SkipTest() for e in events: try: - libinput = e['libinput'] + libinput = e["libinput"] except KeyError: continue for ev in libinput: - if (filter is None or ev['type'] == filter or - isinstance(filter, list) and ev['type'] in filter): + if ( + filter is None + or ev["type"] == filter + or isinstance(filter, list) + and ev["type"] in filter + ): yield ev def test_sections_exist(self): - sections = ['version', 'ndevices', 'libinput', 'system', 'devices'] + sections = ["version", "ndevices", "libinput", "system", "devices"] for section in sections: self.assertIn(section, self.yaml) def test_version(self): - version = self.yaml['version'] + version = self.yaml["version"] self.assertTrue(isinstance(version, int)) self.assertEqual(version, 1) def test_ndevices(self): - ndevices = self.yaml['ndevices'] + ndevices = self.yaml["ndevices"] self.assertTrue(isinstance(ndevices, int)) self.assertGreaterEqual(ndevices, 1) - self.assertEqual(ndevices, len(self.yaml['devices'])) + self.assertEqual(ndevices, len(self.yaml["devices"])) def test_libinput(self): - libinput = self.yaml['libinput'] - version = libinput['version'] + libinput = self.yaml["libinput"] + version = libinput["version"] self.assertTrue(isinstance(version, str)) - self.assertGreaterEqual(parse_version(version), - parse_version('1.10.0')) - git = libinput['git'] + self.assertGreaterEqual(parse_version(version), parse_version("1.10.0")) + git = libinput["git"] self.assertTrue(isinstance(git, str)) - self.assertNotEqual(git, 'unknown') + self.assertNotEqual(git, "unknown") def test_system(self): - system = self.yaml['system'] - kernel = system['kernel'] + system = self.yaml["system"] + kernel = system["kernel"] self.assertTrue(isinstance(kernel, str)) self.assertEqual(kernel, os.uname().release) - dmi = system['dmi'] + dmi = system["dmi"] self.assertTrue(isinstance(dmi, str)) - with open('/sys/class/dmi/id/modalias') as f: + with open("/sys/class/dmi/id/modalias") as f: sys_dmi = f.read()[:-1] # trailing newline self.assertEqual(dmi, sys_dmi) def test_devices_sections_exist(self): - devices = self.yaml['devices'] + devices = self.yaml["devices"] for d in devices: - self.assertIn('node', d) - self.assertIn('evdev', d) - self.assertIn('udev', d) + self.assertIn("node", d) + self.assertIn("evdev", d) + self.assertIn("udev", d) def test_evdev_sections_exist(self): - sections = ['name', 'id', 'codes', 'properties'] - devices = self.yaml['devices'] + sections = ["name", "id", "codes", "properties"] + devices = self.yaml["devices"] for d in devices: - evdev = d['evdev'] + evdev = d["evdev"] for s in sections: self.assertIn(s, evdev) def test_evdev_name(self): - devices = self.yaml['devices'] + devices = self.yaml["devices"] for d in devices: - evdev = d['evdev'] - name = evdev['name'] + evdev = d["evdev"] + name = evdev["name"] self.assertTrue(isinstance(name, str)) self.assertGreaterEqual(len(name), 5) def test_evdev_id(self): - devices = self.yaml['devices'] + devices = self.yaml["devices"] for d in devices: - evdev = d['evdev'] - id = evdev['id'] + evdev = d["evdev"] + id = evdev["id"] self.assertTrue(isinstance(id, list)) self.assertEqual(len(id), 4) self.assertGreater(id[0], 0) self.assertGreater(id[1], 0) def test_evdev_properties(self): - devices = self.yaml['devices'] + devices = self.yaml["devices"] for d in devices: - evdev = d['evdev'] - properties = evdev['properties'] + evdev = d["evdev"] + properties = evdev["properties"] self.assertTrue(isinstance(properties, list)) def test_hid(self): - devices = self.yaml['devices'] + devices = self.yaml["devices"] for d in devices: - hid = d['hid'] + hid = d["hid"] self.assertTrue(isinstance(hid, list)) for byte in hid: self.assertGreaterEqual(byte, 0) self.assertLessEqual(byte, 255) def test_udev_sections_exist(self): - sections = ['properties'] - devices = self.yaml['devices'] + sections = ["properties"] + devices = self.yaml["devices"] for d in devices: - udev = d['udev'] + udev = d["udev"] for s in sections: self.assertIn(s, udev) def test_udev_properties(self): - devices = self.yaml['devices'] + devices = self.yaml["devices"] for d in devices: - udev = d['udev'] - properties = udev['properties'] + udev = d["udev"] + properties = udev["properties"] self.assertTrue(isinstance(properties, list)) self.assertGreater(len(properties), 0) - self.assertIn('ID_INPUT=1', properties) + self.assertIn("ID_INPUT=1", properties) for p in properties: - self.assertTrue(re.match('[A-Z0-9_]+=.+', p)) + self.assertTrue(re.match("[A-Z0-9_]+=.+", p)) def test_udev_id_inputs(self): - devices = self.yaml['devices'] + devices = self.yaml["devices"] for d in devices: - udev = d['udev'] - properties = udev['properties'] - id_inputs = [p for p in properties if p.startswith('ID_INPUT')] + udev = d["udev"] + properties = udev["properties"] + id_inputs = [p for p in properties if p.startswith("ID_INPUT")] # We expect ID_INPUT and ID_INPUT_something, but might get more # than one of the latter self.assertGreaterEqual(len(id_inputs), 2) def test_events_have_section(self): - devices = self.yaml['devices'] + devices = self.yaml["devices"] for d in devices: - events = d['events'] + events = d["events"] if not events: raise unittest.SkipTest() for e in events: - self.assertTrue('evdev' in e or 'libinput' in e) + self.assertTrue("evdev" in e or "libinput" in e) def test_events_evdev(self): - devices = self.yaml['devices'] + devices = self.yaml["devices"] for d in devices: - events = d['events'] + events = d["events"] if not events: raise unittest.SkipTest() for e in events: try: - evdev = e['evdev'] + evdev = e["evdev"] except KeyError: continue @@ -213,28 +216,28 @@ self.assertLessEqual(ev_syn[4], 1) def test_events_evdev_syn_report(self): - devices = self.yaml['devices'] + devices = self.yaml["devices"] for d in devices: - events = d['events'] + events = d["events"] if not events: raise unittest.SkipTest() for e in events: try: - evdev = e['evdev'] + evdev = e["evdev"] except KeyError: continue for ev in evdev[:-1]: self.assertFalse(ev[2] == 0 and ev[3] == 0) def test_events_libinput(self): - devices = self.yaml['devices'] + devices = self.yaml["devices"] for d in devices: - events = d['events'] + events = d["events"] if not events: raise unittest.SkipTest() for e in events: try: - libinput = e['libinput'] + libinput = e["libinput"] except KeyError: continue @@ -243,20 +246,35 @@ self.assertTrue(isinstance(ev, dict)) def test_events_libinput_type(self): - types = ['POINTER_MOTION', 'POINTER_MOTION_ABSOLUTE', 'POINTER_AXIS', - 'POINTER_BUTTON', 'DEVICE_ADDED', 'KEYBOARD_KEY', - 'TOUCH_DOWN', 'TOUCH_MOTION', 'TOUCH_UP', 'TOUCH_FRAME', - 'GESTURE_SWIPE_BEGIN', 'GESTURE_SWIPE_UPDATE', - 'GESTURE_SWIPE_END', 'GESTURE_PINCH_BEGIN', - 'GESTURE_PINCH_UPDATE', 'GESTURE_PINCH_END', - 'TABLET_TOOL_AXIS', 'TABLET_TOOL_PROXIMITY', - 'TABLET_TOOL_BUTTON', 'TABLET_TOOL_TIP', - 'TABLET_PAD_STRIP', 'TABLET_PAD_RING', - 'TABLET_PAD_BUTTON', 'SWITCH_TOGGLE', - ] + types = [ + "POINTER_MOTION", + "POINTER_MOTION_ABSOLUTE", + "POINTER_AXIS", + "POINTER_BUTTON", + "DEVICE_ADDED", + "KEYBOARD_KEY", + "TOUCH_DOWN", + "TOUCH_MOTION", + "TOUCH_UP", + "TOUCH_FRAME", + "GESTURE_SWIPE_BEGIN", + "GESTURE_SWIPE_UPDATE", + "GESTURE_SWIPE_END", + "GESTURE_PINCH_BEGIN", + "GESTURE_PINCH_UPDATE", + "GESTURE_PINCH_END", + "TABLET_TOOL_AXIS", + "TABLET_TOOL_PROXIMITY", + "TABLET_TOOL_BUTTON", + "TABLET_TOOL_TIP", + "TABLET_PAD_STRIP", + "TABLET_PAD_RING", + "TABLET_PAD_BUTTON", + "SWITCH_TOGGLE", + ] for e in self.libinput_events(): - self.assertIn('type', e) - self.assertIn(e['type'], types) + self.assertIn("type", e) + self.assertIn(e["type"], types) def test_events_libinput_time(self): # DEVICE_ADDED has no time @@ -264,51 +282,51 @@ # libinput event. try: for e in list(self.libinput_events())[2:]: - self.assertIn('time', e) - self.assertGreater(e['time'], 0.0) - self.assertLess(e['time'], 60.0) + self.assertIn("time", e) + self.assertGreater(e["time"], 0.0) + self.assertLess(e["time"], 60.0) except IndexError: pass def test_events_libinput_device_added(self): - keys = ['type', 'seat', 'logical_seat'] - for e in self.libinput_events('DEVICE_ADDED'): + keys = ["type", "seat", "logical_seat"] + for e in self.libinput_events("DEVICE_ADDED"): self.dict_key_crosscheck(e, keys) - self.assertEqual(e['seat'], 'seat0') - self.assertEqual(e['logical_seat'], 'default') + self.assertEqual(e["seat"], "seat0") + self.assertEqual(e["logical_seat"], "default") def test_events_libinput_pointer_motion(self): - keys = ['type', 'time', 'delta', 'unaccel'] - for e in self.libinput_events('POINTER_MOTION'): + keys = ["type", "time", "delta", "unaccel"] + for e in self.libinput_events("POINTER_MOTION"): self.dict_key_crosscheck(e, keys) - delta = e['delta'] + delta = e["delta"] self.assertTrue(isinstance(delta, list)) self.assertEqual(len(delta), 2) for d in delta: self.assertTrue(isinstance(d, float)) - unaccel = e['unaccel'] + unaccel = e["unaccel"] self.assertTrue(isinstance(unaccel, list)) self.assertEqual(len(unaccel), 2) for d in unaccel: self.assertTrue(isinstance(d, float)) def test_events_libinput_pointer_button(self): - keys = ['type', 'time', 'button', 'state', 'seat_count'] - for e in self.libinput_events('POINTER_BUTTON'): + keys = ["type", "time", "button", "state", "seat_count"] + for e in self.libinput_events("POINTER_BUTTON"): self.dict_key_crosscheck(e, keys) - button = e['button'] + button = e["button"] self.assertGreater(button, 0x100) # BTN_0 self.assertLess(button, 0x160) # KEY_OK - state = e['state'] - self.assertIn(state, ['pressed', 'released']) - scount = e['seat_count'] + state = e["state"] + self.assertIn(state, ["pressed", "released"]) + scount = e["seat_count"] self.assertGreaterEqual(scount, 0) def test_events_libinput_pointer_absolute(self): - keys = ['type', 'time', 'point', 'transformed'] - for e in self.libinput_events('POINTER_MOTION_ABSOLUTE'): + keys = ["type", "time", "point", "transformed"] + for e in self.libinput_events("POINTER_MOTION_ABSOLUTE"): self.dict_key_crosscheck(e, keys) - point = e['point'] + point = e["point"] self.assertTrue(isinstance(point, list)) self.assertEqual(len(point), 2) for p in point: @@ -316,7 +334,7 @@ self.assertGreater(p, 0.0) self.assertLess(p, 300.0) - transformed = e['transformed'] + transformed = e["transformed"] self.assertTrue(isinstance(transformed, list)) self.assertEqual(len(transformed), 2) for t in transformed: @@ -325,25 +343,24 @@ self.assertLess(t, 100.0) def test_events_libinput_touch(self): - keys = ['type', 'time', 'slot', 'seat_slot'] + keys = ["type", "time", "slot", "seat_slot"] for e in self.libinput_events(): - if (not e['type'].startswith('TOUCH_') or - e['type'] == 'TOUCH_FRAME'): + if not e["type"].startswith("TOUCH_") or e["type"] == "TOUCH_FRAME": continue for k in keys: self.assertIn(k, e.keys()) - slot = e['slot'] - seat_slot = e['seat_slot'] + slot = e["slot"] + seat_slot = e["seat_slot"] self.assertGreaterEqual(slot, 0) self.assertGreaterEqual(seat_slot, 0) def test_events_libinput_touch_down(self): - keys = ['type', 'time', 'slot', 'seat_slot', 'point', 'transformed'] - for e in self.libinput_events('TOUCH_DOWN'): + keys = ["type", "time", "slot", "seat_slot", "point", "transformed"] + for e in self.libinput_events("TOUCH_DOWN"): self.dict_key_crosscheck(e, keys) - point = e['point'] + point = e["point"] self.assertTrue(isinstance(point, list)) self.assertEqual(len(point), 2) for p in point: @@ -351,7 +368,7 @@ self.assertGreater(p, 0.0) self.assertLess(p, 300.0) - transformed = e['transformed'] + transformed = e["transformed"] self.assertTrue(isinstance(transformed, list)) self.assertEqual(len(transformed), 2) for t in transformed: @@ -360,10 +377,10 @@ self.assertLess(t, 100.0) def test_events_libinput_touch_motion(self): - keys = ['type', 'time', 'slot', 'seat_slot', 'point', 'transformed'] - for e in self.libinput_events('TOUCH_MOTION'): + keys = ["type", "time", "slot", "seat_slot", "point", "transformed"] + for e in self.libinput_events("TOUCH_MOTION"): self.dict_key_crosscheck(e, keys) - point = e['point'] + point = e["point"] self.assertTrue(isinstance(point, list)) self.assertEqual(len(point), 2) for p in point: @@ -371,7 +388,7 @@ self.assertGreater(p, 0.0) self.assertLess(p, 300.0) - transformed = e['transformed'] + transformed = e["transformed"] self.assertTrue(isinstance(transformed, list)) self.assertEqual(len(transformed), 2) for t in transformed: @@ -380,25 +397,25 @@ self.assertLess(t, 100.0) def test_events_libinput_touch_frame(self): - devices = self.yaml['devices'] + devices = self.yaml["devices"] for d in devices: - events = d['events'] + events = d["events"] if not events: raise unittest.SkipTest() for e in events: try: - evdev = e['libinput'] + evdev = e["libinput"] except KeyError: continue need_frame = False for ev in evdev: - t = ev['type'] - if not t.startswith('TOUCH_'): + t = ev["type"] + if not t.startswith("TOUCH_"): self.assertFalse(need_frame) continue - if t == 'TOUCH_FRAME': + if t == "TOUCH_FRAME": self.assertTrue(need_frame) need_frame = False else: @@ -407,177 +424,175 @@ self.assertFalse(need_frame) def test_events_libinput_gesture_pinch(self): - keys = ['type', 'time', 'nfingers', 'delta', - 'unaccel', 'angle_delta', 'scale'] - for e in self.libinput_events(['GESTURE_PINCH_BEGIN', - 'GESTURE_PINCH_UPDATE', - 'GESTURE_PINCH_END']): + keys = ["type", "time", "nfingers", "delta", "unaccel", "angle_delta", "scale"] + for e in self.libinput_events( + ["GESTURE_PINCH_BEGIN", "GESTURE_PINCH_UPDATE", "GESTURE_PINCH_END"] + ): self.dict_key_crosscheck(e, keys) - delta = e['delta'] + delta = e["delta"] self.assertTrue(isinstance(delta, list)) self.assertEqual(len(delta), 2) for d in delta: self.assertTrue(isinstance(d, float)) - unaccel = e['unaccel'] + unaccel = e["unaccel"] self.assertTrue(isinstance(unaccel, list)) self.assertEqual(len(unaccel), 2) for d in unaccel: self.assertTrue(isinstance(d, float)) - adelta = e['angle_delta'] + adelta = e["angle_delta"] self.assertTrue(isinstance(adelta, list)) self.assertEqual(len(adelta), 2) for d in adelta: self.assertTrue(isinstance(d, float)) - scale = e['scale'] + scale = e["scale"] self.assertTrue(isinstance(scale, list)) self.assertEqual(len(scale), 2) for d in scale: self.assertTrue(isinstance(d, float)) def test_events_libinput_gesture_swipe(self): - keys = ['type', 'time', 'nfingers', 'delta', - 'unaccel'] - for e in self.libinput_events(['GESTURE_SWIPE_BEGIN', - 'GESTURE_SWIPE_UPDATE', - 'GESTURE_SWIPE_END']): + keys = ["type", "time", "nfingers", "delta", "unaccel"] + for e in self.libinput_events( + ["GESTURE_SWIPE_BEGIN", "GESTURE_SWIPE_UPDATE", "GESTURE_SWIPE_END"] + ): self.dict_key_crosscheck(e, keys) - delta = e['delta'] + delta = e["delta"] self.assertTrue(isinstance(delta, list)) self.assertEqual(len(delta), 2) for d in delta: self.assertTrue(isinstance(d, float)) - unaccel = e['unaccel'] + unaccel = e["unaccel"] self.assertTrue(isinstance(unaccel, list)) self.assertEqual(len(unaccel), 2) for d in unaccel: self.assertTrue(isinstance(d, float)) def test_events_libinput_tablet_pad_button(self): - keys = ['type', 'time', 'button', 'state', 'mode', 'is-toggle'] + keys = ["type", "time", "button", "state", "mode", "is-toggle"] - for e in self.libinput_events('TABLET_PAD_BUTTON'): + for e in self.libinput_events("TABLET_PAD_BUTTON"): self.dict_key_crosscheck(e, keys) - b = e['button'] + b = e["button"] self.assertTrue(isinstance(b, int)) self.assertGreaterEqual(b, 0) self.assertLessEqual(b, 16) - state = e['state'] - self.assertIn(state, ['pressed', 'released']) + state = e["state"] + self.assertIn(state, ["pressed", "released"]) - m = e['mode'] + m = e["mode"] self.assertTrue(isinstance(m, int)) self.assertGreaterEqual(m, 0) self.assertLessEqual(m, 3) - t = e['is-toggle'] + t = e["is-toggle"] self.assertTrue(isinstance(t, bool)) def test_events_libinput_tablet_pad_ring(self): - keys = ['type', 'time', 'number', 'position', 'source', 'mode'] + keys = ["type", "time", "number", "position", "source", "mode"] - for e in self.libinput_events('TABLET_PAD_RING'): + for e in self.libinput_events("TABLET_PAD_RING"): self.dict_key_crosscheck(e, keys) - n = e['number'] + n = e["number"] self.assertTrue(isinstance(n, int)) self.assertGreaterEqual(n, 0) self.assertLessEqual(n, 4) - p = e['position'] + p = e["position"] self.assertTrue(isinstance(p, float)) if p != -1.0: # special 'end' case self.assertGreaterEqual(p, 0.0) self.assertLess(p, 360.0) - m = e['mode'] + m = e["mode"] self.assertTrue(isinstance(m, int)) self.assertGreaterEqual(m, 0) self.assertLessEqual(m, 3) - s = e['source'] - self.assertIn(s, ['finger', 'unknown']) + s = e["source"] + self.assertIn(s, ["finger", "unknown"]) def test_events_libinput_tablet_pad_strip(self): - keys = ['type', 'time', 'number', 'position', 'source', 'mode'] + keys = ["type", "time", "number", "position", "source", "mode"] - for e in self.libinput_events('TABLET_PAD_STRIP'): + for e in self.libinput_events("TABLET_PAD_STRIP"): self.dict_key_crosscheck(e, keys) - n = e['number'] + n = e["number"] self.assertTrue(isinstance(n, int)) self.assertGreaterEqual(n, 0) self.assertLessEqual(n, 4) - p = e['position'] + p = e["position"] self.assertTrue(isinstance(p, float)) if p != -1.0: # special 'end' case self.assertGreaterEqual(p, 0.0) self.assertLessEqual(p, 1.0) - m = e['mode'] + m = e["mode"] self.assertTrue(isinstance(m, int)) self.assertGreaterEqual(m, 0) self.assertLessEqual(m, 3) - s = e['source'] - self.assertIn(s, ['finger', 'unknown']) + s = e["source"] + self.assertIn(s, ["finger", "unknown"]) def test_events_libinput_tablet_tool_proximity(self): - keys = ['type', 'time', 'proximity', 'tool-type', 'serial', 'axes'] + keys = ["type", "time", "proximity", "tool-type", "serial", "axes"] - for e in self.libinput_events('TABLET_TOOL_PROXIMITY'): + for e in self.libinput_events("TABLET_TOOL_PROXIMITY"): for k in keys: self.assertIn(k, e) - p = e['proximity'] - self.assertIn(p, ['in', 'out']) + p = e["proximity"] + self.assertIn(p, ["in", "out"]) - p = e['tool-type'] - self.assertIn(p, ['pen', 'eraser', 'brush', 'airbrush', 'mouse', - 'lens', 'unknown']) + p = e["tool-type"] + self.assertIn( + p, ["pen", "eraser", "brush", "airbrush", "mouse", "lens", "unknown"] + ) - s = e['serial'] + s = e["serial"] self.assertTrue(isinstance(s, int)) self.assertGreaterEqual(s, 0) - a = e['axes'] - for ax in e['axes']: - self.assertIn(a, 'pdtrsw') + a = e["axes"] + for ax in e["axes"]: + self.assertIn(a, "pdtrsw") def test_events_libinput_tablet_tool(self): - keys = ['type', 'time', 'tip'] + keys = ["type", "time", "tip"] - for e in self.libinput_events(['TABLET_TOOL_AXIS', - 'TABLET_TOOL_TIP']): + for e in self.libinput_events(["TABLET_TOOL_AXIS", "TABLET_TOOL_TIP"]): for k in keys: self.assertIn(k, e) - t = e['tip'] - self.assertIn(t, ['down', 'up']) + t = e["tip"] + self.assertIn(t, ["down", "up"]) def test_events_libinput_tablet_tool_button(self): - keys = ['type', 'time', 'button', 'state'] + keys = ["type", "time", "button", "state"] - for e in self.libinput_events('TABLET_TOOL_BUTTON'): + for e in self.libinput_events("TABLET_TOOL_BUTTON"): self.dict_key_crosscheck(e, keys) - b = e['button'] + b = e["button"] # STYLUS, STYLUS2, STYLUS3 - self.assertIn(b, [0x14b, 0x14c, 0x139]) + self.assertIn(b, [0x14B, 0x14C, 0x139]) - s = e['state'] - self.assertIn(s, ['pressed', 'released']) + s = e["state"] + self.assertIn(s, ["pressed", "released"]) def test_events_libinput_tablet_tool_axes(self): - for e in self.libinput_events(['TABLET_TOOL_PROXIMITY', - 'TABLET_TOOL_AXIS', - 'TABLET_TOOL_TIP']): + for e in self.libinput_events( + ["TABLET_TOOL_PROXIMITY", "TABLET_TOOL_AXIS", "TABLET_TOOL_TIP"] + ): - point = e['point'] + point = e["point"] self.assertTrue(isinstance(point, list)) self.assertEqual(len(point), 2) for p in point: @@ -585,7 +600,7 @@ self.assertGreater(p, 0.0) try: - tilt = e['tilt'] + tilt = e["tilt"] self.assertTrue(isinstance(tilt, list)) self.assertEqual(len(tilt), 2) for t in tilt: @@ -594,70 +609,75 @@ pass try: - d = e['distance'] + d = e["distance"] self.assertTrue(isinstance(d, float)) self.assertGreaterEqual(d, 0.0) - self.assertNotIn('pressure', e) + self.assertNotIn("pressure", e) except KeyError: pass try: - p = e['pressure'] + p = e["pressure"] self.assertTrue(isinstance(p, float)) self.assertGreaterEqual(p, 0.0) - self.assertNotIn('distance', e) + self.assertNotIn("distance", e) except KeyError: pass try: - r = e['rotation'] + r = e["rotation"] self.assertTrue(isinstance(r, float)) self.assertGreaterEqual(r, 0.0) except KeyError: pass try: - s = e['slider'] + s = e["slider"] self.assertTrue(isinstance(s, float)) self.assertGreaterEqual(s, 0.0) except KeyError: pass try: - w = e['wheel'] + w = e["wheel"] self.assertTrue(isinstance(w, float)) self.assertGreaterEqual(w, 0.0) - self.assertIn('wheel-discrete', e) - wd = e['wheel-discrete'] + self.assertIn("wheel-discrete", e) + wd = e["wheel-discrete"] self.assertTrue(isinstance(wd, 1)) self.assertGreaterEqual(wd, 0.0) def sign(x): (1, -1)[x < 0] + self.assertTrue(sign(w), sign(wd)) except KeyError: pass def test_events_libinput_switch(self): - keys = ['type', 'time', 'switch', 'state'] + keys = ["type", "time", "switch", "state"] - for e in self.libinput_events('SWITCH_TOGGLE'): + for e in self.libinput_events("SWITCH_TOGGLE"): self.dict_key_crosscheck(e, keys) - s = e['switch'] + s = e["switch"] self.assertTrue(isinstance(s, int)) self.assertIn(s, [0x00, 0x01]) # yaml converts on/off to true/false - state = e['state'] + state = e["state"] self.assertTrue(isinstance(state, bool)) -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Verify a YAML recording') - parser.add_argument('recording', metavar='recorded-file.yaml', - type=str, help='Path to device recording') - parser.add_argument('--verbose', action='store_true') +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Verify a YAML recording") + parser.add_argument( + "recording", + metavar="recorded-file.yaml", + type=str, + help="Path to device recording", + ) + parser.add_argument("--verbose", action="store_true") args, remainder = parser.parse_known_args() TestYaml.filename = args.recording verbosity = 1 diff -Nru libinput-1.16.4/tools/libinput-replay libinput-1.17.2/tools/libinput-replay --- libinput-1.16.4/tools/libinput-replay 2020-11-27 01:38:59.403086200 +0000 +++ libinput-1.17.2/tools/libinput-replay 1970-01-01 00:00:00.000000000 +0000 @@ -1,282 +0,0 @@ -#!/usr/bin/env python3 -# vim: set expandtab shiftwidth=4: -# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ -# -# Copyright © 2018 Red Hat, Inc. -# -# 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. - -import os -import sys -import time -import multiprocessing -import argparse -from pathlib import Path - -try: - import libevdev - import yaml -except ModuleNotFoundError as e: - print('Error: {}'.format(e), file=sys.stderr) - print('One or more python modules are missing. Please install those ' - 'modules and re-run this tool.') - sys.exit(1) - - -SUPPORTED_FILE_VERSION = 1 - - -def error(msg, **kwargs): - print(msg, **kwargs, file=sys.stderr) - - -class YamlException(Exception): - pass - - -def fetch(yaml, key): - '''Helper function to avoid confusing a YAML error with a - normal KeyError bug''' - try: - return yaml[key] - except KeyError: - raise YamlException('Failed to get \'{}\' from recording.'.format(key)) - - -def create(device): - evdev = fetch(device, 'evdev') - - d = libevdev.Device() - d.name = fetch(evdev, 'name') - - ids = fetch(evdev, 'id') - if len(ids) != 4: - raise YamlException('Invalid ID format: {}'.format(ids)) - d.id = dict(zip(['bustype', 'vendor', 'product', 'version'], ids)) - - codes = fetch(evdev, 'codes') - for evtype, evcodes in codes.items(): - for code in evcodes: - data = None - if evtype == libevdev.EV_ABS.value: - values = fetch(evdev, 'absinfo')[code] - absinfo = libevdev.InputAbsInfo(minimum=values[0], - maximum=values[1], - fuzz=values[2], - flat=values[3], - resolution=values[4]) - data = absinfo - elif evtype == libevdev.EV_REP.value: - if code == libevdev.EV_REP.REP_DELAY.value: - data = 500 - elif code == libevdev.EV_REP.REP_PERIOD.value: - data = 20 - d.enable(libevdev.evbit(evtype, code), data=data) - - properties = fetch(evdev, 'properties') - for prop in properties: - d.enable(libevdev.propbit(prop)) - - uinput = d.create_uinput_device() - return uinput - - -def print_events(devnode, indent, evs): - devnode = os.path.basename(devnode) - for e in evs: - print("{}: {}{:06d}.{:06d} {} / {:<20s} {:4d}".format( - devnode, ' ' * (indent * 8), e.sec, e.usec, e.type.name, e.code.name, e.value)) - - -def replay(device, verbose): - events = fetch(device, 'events') - if events is None: - return - uinput = device['__uinput'] - - # The first event may have a nonzero offset but we want to replay - # immediately regardless. When replaying multiple devices, the first - # offset is the offset from the first event on any device. - offset = time.time() - device['__first_event_offset'] - - if offset < 0: - error('WARNING: event time offset is in the future, refusing to replay') - return - - # each 'evdev' set contains one SYN_REPORT so we only need to check for - # the time offset once per event - for event in events: - try: - evdev = fetch(event, 'evdev') - except YamlException: - continue - - (sec, usec, evtype, evcode, value) = evdev[0] - evtime = sec + usec / 1e6 + offset - now = time.time() - - if evtime - now > 150 / 1e6: # 150 µs error margin - time.sleep(evtime - now - 150 / 1e6) - - evs = [libevdev.InputEvent(libevdev.evbit(e[2], e[3]), value=e[4], sec=e[0], usec=e[1]) for e in evdev] - uinput.send_events(evs) - if verbose: - print_events(uinput.devnode, device['__index'], evs) - - -def first_timestamp(device): - try: - events = fetch(device, 'events') - if events is None: - raise YamlException('No events from this device') - - evdev = fetch(events[0], 'evdev') - (sec, usec, *_) = evdev[0] - - return sec + usec / 1.e6 - - except YamlException: - import math - return math.inf - - -def wrap(func, *args): - try: - func(*args) - except KeyboardInterrupt: - pass - - -def loop(args, recording): - devices = fetch(recording, 'devices') - - # All devices need to start replaying at the same time, so let's find - # the very first event and offset everything by that timestamp. - toffset = min([first_timestamp(d) for d in devices]) - - for idx, d in enumerate(devices): - uinput = create(d) - print('{}: {}'.format(uinput.devnode, uinput.name)) - d['__uinput'] = uinput # cheaper to hide it in the dict then work around it - d['__index'] = idx - d['__first_event_offset'] = toffset - - while True: - input('Hit enter to start replaying') - - processes = [] - for d in devices: - p = multiprocessing.Process(target=wrap, args=(replay, d, args.verbose)) - processes.append(p) - - for p in processes: - p.start() - - for p in processes: - p.join() - - del processes - - -def create_device_quirk(device): - try: - quirks = fetch(device, 'quirks') - if not quirks: - return None - except YamlException: - return None - # Where the device has a quirk, we match on name, vendor and product. - # That's the best match we can assemble here from the info we have. - evdev = fetch(device, 'evdev') - name = fetch(evdev, 'name') - id = fetch(evdev, 'id') - quirk = ('[libinput-replay {name}]\n' - 'MatchName={name}\n' - 'MatchVendor=0x{id[1]:04X}\n' - 'MatchProduct=0x{id[2]:04X}\n').format(name=name, id=id) - quirk += '\n'.join(quirks) - return quirk - - -def setup_quirks(recording): - devices = fetch(recording, 'devices') - overrides = None - quirks = [] - for d in devices: - if 'quirks' in d: - quirk = create_device_quirk(d) - if quirk: - quirks.append(quirk) - if not quirks: - return None - - overrides = Path('/etc/libinput/local-overrides.quirks') - if overrides.exists(): - print('{} exists, please move it out of the way first'.format(overrides), file=sys.stderr) - sys.exit(1) - - overrides.parent.mkdir(exist_ok=True) - with overrides.open('w+') as fd: - fd.write('# This file was generated by libinput replay\n') - fd.write('# Unless libinput replay is running right now, remove this file.\n') - fd.write('\n\n'.join(quirks)) - - return overrides - - -def check_file(recording): - version = fetch(recording, 'version') - if version != SUPPORTED_FILE_VERSION: - raise YamlException('Invalid file format: {}, expected {}'.format(version, SUPPORTED_FILE_VERSION)) - - ndevices = fetch(recording, 'ndevices') - devices = fetch(recording, 'devices') - if ndevices != len(devices): - error('WARNING: truncated file, expected {} devices, got {}'.format(ndevices, len(devices))) - - -def main(): - parser = argparse.ArgumentParser(description='Replay a device recording') - parser.add_argument('recording', metavar='recorded-file.yaml', - type=str, help='Path to device recording') - parser.add_argument('--verbose', action='store_true') - args = parser.parse_args() - - quirks_file = None - - try: - with open(args.recording) as f: - y = yaml.safe_load(f) - check_file(y) - quirks_file = setup_quirks(y) - loop(args, y) - except KeyboardInterrupt: - pass - except (PermissionError, OSError) as e: - error('Error: failed to open device: {}'.format(e)) - except YamlException as e: - error('Error: failed to parse recording: {}'.format(e)) - finally: - if quirks_file: - quirks_file.unlink() - - -if __name__ == '__main__': - main() diff -Nru libinput-1.16.4/tools/libinput-replay.py libinput-1.17.2/tools/libinput-replay.py --- libinput-1.16.4/tools/libinput-replay.py 1970-01-01 00:00:00.000000000 +0000 +++ libinput-1.17.2/tools/libinput-replay.py 2021-04-30 04:25:41.546076300 +0000 @@ -0,0 +1,371 @@ +#!/usr/bin/env python3 +# vim: set expandtab shiftwidth=4: +# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ +# +# Copyright © 2018 Red Hat, Inc. +# +# 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. + +import os +import sys +import time +import math +import multiprocessing +import argparse +from pathlib import Path + +try: + import libevdev + import yaml + import pyudev +except ModuleNotFoundError as e: + print("Error: {}".format(e), file=sys.stderr) + print( + "One or more python modules are missing. Please install those " + "modules and re-run this tool." + ) + sys.exit(1) + + +SUPPORTED_FILE_VERSION = 1 + + +def error(msg, **kwargs): + print(msg, **kwargs, file=sys.stderr) + + +class YamlException(Exception): + pass + + +def fetch(yaml, key): + """Helper function to avoid confusing a YAML error with a + normal KeyError bug""" + try: + return yaml[key] + except KeyError: + raise YamlException("Failed to get '{}' from recording.".format(key)) + + +def check_udev_properties(yaml_data, uinput): + """ + Compare the properties our new uinput device has with the ones from the + recording and ring the alarm bell if one of them is off. + """ + yaml_udev_section = fetch(yaml_data, "udev") + yaml_udev_props = fetch(yaml_udev_section, "properties") + yaml_props = { + k: v for (k, v) in [prop.split("=", maxsplit=1) for prop in yaml_udev_props] + } + try: + # We don't assign this one to virtual devices + del yaml_props["LIBINPUT_DEVICE_GROUP"] + except KeyError: + pass + + # give udev some time to catch up + time.sleep(0.2) + context = pyudev.Context() + udev_device = pyudev.Devices.from_device_file(context, uinput.devnode) + for name, value in udev_device.properties.items(): + if name in yaml_props: + if yaml_props[name] != value: + error( + f"Warning: udev property mismatch: recording has {name}={yaml_props[name]}, device has {name}={value}" + ) + del yaml_props[name] + else: + # The list of properties we add to the recording, see libinput-record.c + prefixes = ( + "ID_INPUT", + "LIBINPUT", + "EVDEV_ABS", + "MOUSE_DPI", + "POINTINGSTICK_", + ) + for prefix in prefixes: + if name.startswith(prefix): + error(f"Warning: unexpected property: {name}={value}") + + # the ones we found above were removed from the dict + for name, value in yaml_props.items(): + error(f"Warning: device is missing recorded udev property: {name}={value}") + + +def create(device): + evdev = fetch(device, "evdev") + + d = libevdev.Device() + d.name = fetch(evdev, "name") + + ids = fetch(evdev, "id") + if len(ids) != 4: + raise YamlException("Invalid ID format: {}".format(ids)) + d.id = dict(zip(["bustype", "vendor", "product", "version"], ids)) + + codes = fetch(evdev, "codes") + for evtype, evcodes in codes.items(): + for code in evcodes: + data = None + if evtype == libevdev.EV_ABS.value: + values = fetch(evdev, "absinfo")[code] + absinfo = libevdev.InputAbsInfo( + minimum=values[0], + maximum=values[1], + fuzz=values[2], + flat=values[3], + resolution=values[4], + ) + data = absinfo + elif evtype == libevdev.EV_REP.value: + if code == libevdev.EV_REP.REP_DELAY.value: + data = 500 + elif code == libevdev.EV_REP.REP_PERIOD.value: + data = 20 + d.enable(libevdev.evbit(evtype, code), data=data) + + properties = fetch(evdev, "properties") + for prop in properties: + d.enable(libevdev.propbit(prop)) + + uinput = d.create_uinput_device() + + check_udev_properties(device, uinput) + + return uinput + + +def print_events(devnode, indent, evs): + devnode = os.path.basename(devnode) + for e in evs: + print( + "{}: {}{:06d}.{:06d} {} / {:<20s} {:4d}".format( + devnode, + " " * (indent * 8), + e.sec, + e.usec, + e.type.name, + e.code.name, + e.value, + ) + ) + + +def replay(device, verbose): + events = fetch(device, "events") + if events is None: + return + uinput = device["__uinput"] + + # The first event may have a nonzero offset but we want to replay + # immediately regardless. When replaying multiple devices, the first + # offset is the offset from the first event on any device. + offset = time.time() - device["__first_event_offset"] + + if offset < 0: + error("WARNING: event time offset is in the future, refusing to replay") + return + + # each 'evdev' set contains one SYN_REPORT so we only need to check for + # the time offset once per event + for event in events: + try: + evdev = fetch(event, "evdev") + except YamlException: + continue + + (sec, usec, evtype, evcode, value) = evdev[0] + evtime = sec + usec / 1e6 + offset + now = time.time() + + if evtime - now > 150 / 1e6: # 150 µs error margin + time.sleep(evtime - now - 150 / 1e6) + + evs = [ + libevdev.InputEvent( + libevdev.evbit(e[2], e[3]), value=e[4], sec=e[0], usec=e[1] + ) + for e in evdev + ] + uinput.send_events(evs) + if verbose: + print_events(uinput.devnode, device["__index"], evs) + + +def first_timestamp(device): + events = fetch(device, "events") + for e in events or []: + try: + evdev = fetch(e, "evdev") + (sec, usec, *_) = evdev[0] + return sec + usec / 1.0e6 + except YamlException: + pass + + return None + + +def wrap(func, *args): + try: + func(*args) + except KeyboardInterrupt: + pass + + +def loop(args, recording): + devices = fetch(recording, "devices") + + first_timestamps = tuple( + filter(lambda x: x is not None, [first_timestamp(d) for d in devices]) + ) + # All devices need to start replaying at the same time, so let's find + # the very first event and offset everything by that timestamp. + toffset = min(first_timestamps or [math.inf]) + + for idx, d in enumerate(devices): + uinput = create(d) + print("{}: {}".format(uinput.devnode, uinput.name)) + d["__uinput"] = uinput # cheaper to hide it in the dict then work around it + d["__index"] = idx + d["__first_event_offset"] = toffset + + if not first_timestamps: + input("No events in recording. Hit enter to quit") + return + + while True: + input("Hit enter to start replaying") + + processes = [] + for d in devices: + p = multiprocessing.Process(target=wrap, args=(replay, d, args.verbose)) + processes.append(p) + + for p in processes: + p.start() + + for p in processes: + p.join() + + del processes + + +def create_device_quirk(device): + try: + quirks = fetch(device, "quirks") + if not quirks: + return None + except YamlException: + return None + # Where the device has a quirk, we match on name, vendor and product. + # That's the best match we can assemble here from the info we have. + evdev = fetch(device, "evdev") + name = fetch(evdev, "name") + id = fetch(evdev, "id") + quirk = ( + "[libinput-replay {name}]\n" + "MatchName={name}\n" + "MatchVendor=0x{id[1]:04X}\n" + "MatchProduct=0x{id[2]:04X}\n" + ).format(name=name, id=id) + quirk += "\n".join(quirks) + return quirk + + +def setup_quirks(recording): + devices = fetch(recording, "devices") + overrides = None + quirks = [] + for d in devices: + if "quirks" in d: + quirk = create_device_quirk(d) + if quirk: + quirks.append(quirk) + if not quirks: + return None + + overrides = Path("/etc/libinput/local-overrides.quirks") + if overrides.exists(): + print( + "{} exists, please move it out of the way first".format(overrides), + file=sys.stderr, + ) + sys.exit(1) + + overrides.parent.mkdir(exist_ok=True) + with overrides.open("w+") as fd: + fd.write("# This file was generated by libinput replay\n") + fd.write("# Unless libinput replay is running right now, remove this file.\n") + fd.write("\n\n".join(quirks)) + + return overrides + + +def check_file(recording): + version = fetch(recording, "version") + if version != SUPPORTED_FILE_VERSION: + raise YamlException( + "Invalid file format: {}, expected {}".format( + version, SUPPORTED_FILE_VERSION + ) + ) + + ndevices = fetch(recording, "ndevices") + devices = fetch(recording, "devices") + if ndevices != len(devices): + error( + "WARNING: truncated file, expected {} devices, got {}".format( + ndevices, len(devices) + ) + ) + + +def main(): + parser = argparse.ArgumentParser(description="Replay a device recording") + parser.add_argument( + "recording", + metavar="recorded-file.yaml", + type=str, + help="Path to device recording", + ) + parser.add_argument("--verbose", action="store_true") + args = parser.parse_args() + + quirks_file = None + + try: + with open(args.recording) as f: + y = yaml.safe_load(f) + check_file(y) + quirks_file = setup_quirks(y) + loop(args, y) + except KeyboardInterrupt: + pass + except (PermissionError, OSError) as e: + error("Error: failed to open device: {}".format(e)) + except YamlException as e: + error("Error: failed to parse recording: {}".format(e)) + finally: + if quirks_file: + quirks_file.unlink() + + +if __name__ == "__main__": + main() diff -Nru libinput-1.16.4/tools/shared.c libinput-1.17.2/tools/shared.c --- libinput-1.16.4/tools/shared.c 2020-11-27 01:38:59.404086000 +0000 +++ libinput-1.17.2/tools/shared.c 2021-04-30 04:25:41.547076200 +0000 @@ -43,6 +43,15 @@ #include "util-macros.h" #include "util-strings.h" +static uint32_t dispatch_counter = 0; + +void +tools_dispatch(struct libinput *libinput) +{ + dispatch_counter++; + libinput_dispatch(libinput); +} + LIBINPUT_ATTRIBUTE_PRINTF(3, 0) static void log_handler(struct libinput *li, @@ -51,20 +60,38 @@ va_list args) { static int is_tty = -1; + static uint32_t last_dispatch_no = 0; + static bool color_toggle = false; if (is_tty == -1) is_tty = isatty(STDOUT_FILENO); if (is_tty) { - if (priority >= LIBINPUT_LOG_PRIORITY_ERROR) + if (priority >= LIBINPUT_LOG_PRIORITY_ERROR) { printf(ANSI_RED); - else if (priority >= LIBINPUT_LOG_PRIORITY_INFO) + } else if (priority >= LIBINPUT_LOG_PRIORITY_INFO) { printf(ANSI_HIGHLIGHT); + } else if (priority == LIBINPUT_LOG_PRIORITY_DEBUG) { + if (dispatch_counter != last_dispatch_no) + color_toggle = !color_toggle; + uint8_t r = 0, + g = 135, + b = 95 + (color_toggle ? 80 :0); + printf("\x1B[38;2;%u;%u;%um", r, g, b); + } } + if (priority < LIBINPUT_LOG_PRIORITY_INFO) { + if (dispatch_counter != last_dispatch_no) { + last_dispatch_no = dispatch_counter; + printf("%4u: ", dispatch_counter); + } else { + printf(" %4s ", "..."); + } + } vprintf(format, args); - if (is_tty && priority >= LIBINPUT_LOG_PRIORITY_INFO) + if (is_tty) printf(ANSI_NORMAL); } @@ -437,13 +464,16 @@ find_device(const char *udev_tag) { struct udev *udev; - struct udev_enumerate *e; + struct udev_enumerate *e = NULL; struct udev_list_entry *entry = NULL; struct udev_device *device; const char *path, *sysname; char *device_node = NULL; udev = udev_new(); + if (!udev) + goto out; + e = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(e, "input"); udev_enumerate_scan_devices(e); @@ -468,6 +498,7 @@ if (device_node) break; } +out: udev_enumerate_unref(e); udev_unref(udev); @@ -499,6 +530,9 @@ return false; udev = udev_new(); + if (!udev) + goto out; + dev = udev_device_new_from_devnum(udev, 'c', st.st_rdev); if (!dev) goto out; @@ -564,27 +598,26 @@ "libinput: %s is not installed\n", command); return EXIT_INVALID_USAGE; - } else { - fprintf(stderr, - "Failed to execute '%s' (%s)\n", - command, - strerror(errno)); } + fprintf(stderr, + "Failed to execute '%s' (%s)\n", + command, + strerror(errno)); } return EXIT_FAILURE; } static void -sprintf_event_codes(char *buf, size_t sz, struct quirks *quirks) +sprintf_event_codes(char *buf, size_t sz, struct quirks *quirks, enum quirk q) { const struct quirk_tuples *t; size_t off = 0; int printed; const char *name; - quirks_get_tuples(quirks, QUIRK_ATTR_EVENT_CODE_DISABLE, &t); - name = quirk_get_name(QUIRK_ATTR_EVENT_CODE_DISABLE); + quirks_get_tuples(quirks, q, &t); + name = quirk_get_name(q); printed = snprintf(buf, sz, "%s=", name); assert(printed != -1); off += printed; @@ -600,6 +633,29 @@ } } +static void +sprintf_input_props(char *buf, size_t sz, struct quirks *quirks, enum quirk q) +{ + const uint32_t *properties; + size_t nprops = 0; + size_t off = 0; + int printed; + const char *name; + + quirks_get_uint32_array(quirks, q, &properties, &nprops); + name = quirk_get_name(q); + printed = snprintf(buf, sz, "%s=", name); + assert(printed != -1); + off += printed; + + for (size_t i = 0; off < sz && i < nprops; i++) { + const char *name = libevdev_property_get_name(properties[i]); + printed = snprintf(buf + off, sz - off, "%s;", name); + assert(printed != -1); + off += printed; + } +} + void tools_list_device_quirks(struct quirks_context *ctx, struct udev_device *device, @@ -680,7 +736,13 @@ callback(userdata, buf); break; case QUIRK_ATTR_EVENT_CODE_DISABLE: - sprintf_event_codes(buf, sizeof(buf), quirks); + case QUIRK_ATTR_EVENT_CODE_ENABLE: + sprintf_event_codes(buf, sizeof(buf), quirks, q); + callback(userdata, buf); + break; + case QUIRK_ATTR_INPUT_PROP_DISABLE: + case QUIRK_ATTR_INPUT_PROP_ENABLE: + sprintf_input_props(buf, sizeof(buf), quirks, q); callback(userdata, buf); break; default: diff -Nru libinput-1.16.4/tools/shared.h libinput-1.17.2/tools/shared.h --- libinput-1.16.4/tools/shared.h 2020-11-27 01:38:59.404086000 +0000 +++ libinput-1.17.2/tools/shared.h 2021-04-30 04:25:41.547076200 +0000 @@ -132,4 +132,6 @@ void (*callback)(void *userdata, const char *str), void *userdata); +void +tools_dispatch(struct libinput *libinput); #endif diff -Nru libinput-1.16.4/tools/test_tool_option_parsing.py libinput-1.17.2/tools/test_tool_option_parsing.py --- libinput-1.16.4/tools/test_tool_option_parsing.py 2020-11-27 01:38:59.404086000 +0000 +++ libinput-1.17.2/tools/test_tool_option_parsing.py 2021-04-30 04:25:41.547076200 +0000 @@ -32,15 +32,15 @@ try: import pytest except ImportError: - print('Failed to import pytest. Skipping.', file=sys.stderr) + print("Failed to import pytest. Skipping.", file=sys.stderr) sys.exit(77) -logger = logging.getLogger('test') +logger = logging.getLogger("test") logger.setLevel(logging.DEBUG) -if '@DISABLE_WARNING@' != 'yes': - print('This is the source file, run the one in the meson builddir instead') +if "@DISABLE_WARNING@" != "yes": + print("This is the source file, run the one in the meson builddir instead") sys.exit(1) @@ -49,9 +49,13 @@ def run_command(args): - logger.debug('run command: {}'.format(' '.join(args))) - with subprocess.Popen(args, preexec_fn=_disable_coredump, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) as p: + logger.debug("run command: {}".format(" ".join(args))) + with subprocess.Popen( + args, + preexec_fn=_disable_coredump, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) as p: try: p.wait(0.7) except subprocess.TimeoutExpired: @@ -59,11 +63,11 @@ stdout, stderr = p.communicate(timeout=5) if p.returncode == -3: p.returncode = 0 - return p.returncode, stdout.decode('UTF-8'), stderr.decode('UTF-8') + return p.returncode, stdout.decode("UTF-8"), stderr.decode("UTF-8") class LibinputTool(object): - libinput_tool = 'libinput' + libinput_tool = "libinput" subtool = None def __init__(self, subtool=None): @@ -92,43 +96,43 @@ def run_command_unrecognized_option(self, args): rc, stdout, stderr = self.run_command(args) assert rc == 2, (rc, stdout, stderr) - assert stdout.startswith('Usage') or stdout == '' - assert 'unrecognized option' in stderr + assert stdout.startswith("Usage") or stdout == "" + assert "unrecognized option" in stderr def run_command_missing_arg(self, args): rc, stdout, stderr = self.run_command(args) assert rc == 2, (rc, stdout, stderr) - assert stdout.startswith('Usage') or stdout == '' - assert 'requires an argument' in stderr + assert stdout.startswith("Usage") or stdout == "" + assert "requires an argument" in stderr def run_command_unrecognized_tool(self, args): rc, stdout, stderr = self.run_command(args) assert rc == 2, (rc, stdout, stderr) - assert stdout.startswith('Usage') or stdout == '' - assert 'is not installed' in stderr + assert stdout.startswith("Usage") or stdout == "" + assert "is not installed" in stderr class LibinputDebugGui(LibinputTool): - def __init__(self, subtool='debug-gui'): - assert subtool == 'debug-gui' + def __init__(self, subtool="debug-gui"): + assert subtool == "debug-gui" super().__init__(subtool) - debug_gui_enabled = '@MESON_ENABLED_DEBUG_GUI@' == 'True' + debug_gui_enabled = "@MESON_ENABLED_DEBUG_GUI@" == "True" if not debug_gui_enabled: pytest.skip() - if not os.getenv('DISPLAY') and not os.getenv('WAYLAND_DISPLAY'): + if not os.getenv("DISPLAY") and not os.getenv("WAYLAND_DISPLAY"): pytest.skip() # 77 means gtk_init() failed, which is probably because you can't # connect to the display server. - rc, _, _ = self.run_command(['--help']) + rc, _, _ = self.run_command(["--help"]) if rc == 77: pytest.skip() def get_tool(subtool=None): - if subtool == 'debug-gui': + if subtool == "debug-gui": return LibinputDebugGui() else: return LibinputTool(subtool) @@ -139,110 +143,110 @@ return get_tool() -@pytest.fixture(params=['debug-events', 'debug-gui']) +@pytest.fixture(params=["debug-events", "debug-gui"]) def libinput_debug_tool(request): yield get_tool(request.param) @pytest.fixture def libinput_debug_events(): - return get_tool('debug-events') + return get_tool("debug-events") @pytest.fixture def libinput_debug_gui(): - return get_tool('debug-gui') + return get_tool("debug-gui") @pytest.fixture def libinput_record(): - return get_tool('record') + return get_tool("record") def test_help(libinput): - stdout, stderr = libinput.run_command_success(['--help']) - assert stdout.startswith('Usage:') - assert stderr == '' + stdout, stderr = libinput.run_command_success(["--help"]) + assert stdout.startswith("Usage:") + assert stderr == "" def test_version(libinput): - stdout, stderr = libinput.run_command_success(['--version']) - assert stdout.startswith('1') - assert stderr == '' + stdout, stderr = libinput.run_command_success(["--version"]) + assert stdout.startswith("1") + assert stderr == "" -@pytest.mark.parametrize('argument', ['--banana', '--foo', '--quiet', '--verbose']) +@pytest.mark.parametrize("argument", ["--banana", "--foo", "--quiet", "--verbose"]) def test_invalid_arguments(libinput, argument): libinput.run_command_unrecognized_option([argument]) -@pytest.mark.parametrize('tool', [['foo'], ['debug'], ['foo', '--quiet']]) +@pytest.mark.parametrize("tool", [["foo"], ["debug"], ["foo", "--quiet"]]) def test_invalid_tool(libinput, tool): libinput.run_command_unrecognized_tool(tool) def test_udev_seat(libinput_debug_tool): - libinput_debug_tool.run_command_missing_arg(['--udev']) - libinput_debug_tool.run_command_success(['--udev', 'seat0']) - libinput_debug_tool.run_command_success(['--udev', 'seat1']) + libinput_debug_tool.run_command_missing_arg(["--udev"]) + libinput_debug_tool.run_command_success(["--udev", "seat0"]) + libinput_debug_tool.run_command_success(["--udev", "seat1"]) -@pytest.mark.skipif(os.environ.get('UDEV_NOT_AVAILABLE'), reason='udev required') +@pytest.mark.skipif(os.environ.get("UDEV_NOT_AVAILABLE"), reason="udev required") def test_device_arg(libinput_debug_tool): - libinput_debug_tool.run_command_missing_arg(['--device']) - libinput_debug_tool.run_command_success(['--device', '/dev/input/event0']) - libinput_debug_tool.run_command_success(['--device', '/dev/input/event1']) - libinput_debug_tool.run_command_success(['/dev/input/event0']) + libinput_debug_tool.run_command_missing_arg(["--device"]) + libinput_debug_tool.run_command_success(["--device", "/dev/input/event0"]) + libinput_debug_tool.run_command_success(["--device", "/dev/input/event1"]) + libinput_debug_tool.run_command_success(["/dev/input/event0"]) options = { - 'pattern': ['sendevents'], + "pattern": ["sendevents"], # enable/disable options - 'enable-disable': [ - 'tap', - 'drag', - 'drag-lock', - 'middlebutton', - 'natural-scrolling', - 'left-handed', - 'dwt' + "enable-disable": [ + "tap", + "drag", + "drag-lock", + "middlebutton", + "natural-scrolling", + "left-handed", + "dwt", ], # options with distinct values - 'enums': { - 'set-click-method': ['none', 'clickfinger', 'buttonareas'], - 'set-scroll-method': ['none', 'twofinger', 'edge', 'button'], - 'set-profile': ['adaptive', 'flat'], - 'set-tap-map': ['lrm', 'lmr'], + "enums": { + "set-click-method": ["none", "clickfinger", "buttonareas"], + "set-scroll-method": ["none", "twofinger", "edge", "button"], + "set-profile": ["adaptive", "flat"], + "set-tap-map": ["lrm", "lmr"], }, # options with a range - 'ranges': { - 'set-speed': (float, -1.0, +1.0), - } + "ranges": { + "set-speed": (float, -1.0, +1.0), + }, } # Options that allow for glob patterns -@pytest.mark.parametrize('option', options['pattern']) +@pytest.mark.parametrize("option", options["pattern"]) def test_options_pattern(libinput_debug_tool, option): - libinput_debug_tool.run_command_success(['--disable-{}'.format(option), '*']) - libinput_debug_tool.run_command_success(['--disable-{}'.format(option), 'abc*']) + libinput_debug_tool.run_command_success(["--disable-{}".format(option), "*"]) + libinput_debug_tool.run_command_success(["--disable-{}".format(option), "abc*"]) -@pytest.mark.parametrize('option', options['enable-disable']) +@pytest.mark.parametrize("option", options["enable-disable"]) def test_options_enable_disable(libinput_debug_tool, option): - libinput_debug_tool.run_command_success(['--enable-{}'.format(option)]) - libinput_debug_tool.run_command_success(['--disable-{}'.format(option)]) + libinput_debug_tool.run_command_success(["--enable-{}".format(option)]) + libinput_debug_tool.run_command_success(["--disable-{}".format(option)]) -@pytest.mark.parametrize('option', options['enums'].items()) +@pytest.mark.parametrize("option", options["enums"].items()) def test_options_enums(libinput_debug_tool, option): name, values = option for v in values: - libinput_debug_tool.run_command_success(['--{}'.format(name), v]) - libinput_debug_tool.run_command_success(['--{}={}'.format(name, v)]) + libinput_debug_tool.run_command_success(["--{}".format(name), v]) + libinput_debug_tool.run_command_success(["--{}={}".format(name, v)]) -@pytest.mark.parametrize('option', options['ranges'].items()) +@pytest.mark.parametrize("option", options["ranges"].items()) def test_options_ranges(libinput_debug_tool, option): name, values = option range_type, minimum, maximum = values @@ -250,114 +254,128 @@ step = (maximum - minimum) / 10.0 value = minimum while value < maximum: - libinput_debug_tool.run_command_success(['--{}'.format(name), str(value)]) - libinput_debug_tool.run_command_success(['--{}={}'.format(name, value)]) + libinput_debug_tool.run_command_success(["--{}".format(name), str(value)]) + libinput_debug_tool.run_command_success(["--{}={}".format(name, value)]) value += step - libinput_debug_tool.run_command_success(['--{}'.format(name), str(maximum)]) - libinput_debug_tool.run_command_success(['--{}={}'.format(name, maximum)]) + libinput_debug_tool.run_command_success(["--{}".format(name), str(maximum)]) + libinput_debug_tool.run_command_success(["--{}={}".format(name, maximum)]) def test_apply_to(libinput_debug_tool): - libinput_debug_tool.run_command_missing_arg(['--apply-to']) - libinput_debug_tool.run_command_success(['--apply-to', '*foo*']) - libinput_debug_tool.run_command_success(['--apply-to', 'foobar']) - libinput_debug_tool.run_command_success(['--apply-to', 'any']) + libinput_debug_tool.run_command_missing_arg(["--apply-to"]) + libinput_debug_tool.run_command_success(["--apply-to", "*foo*"]) + libinput_debug_tool.run_command_success(["--apply-to", "foobar"]) + libinput_debug_tool.run_command_success(["--apply-to", "any"]) -@pytest.mark.parametrize('args', [['--verbose'], ['--quiet'], - ['--verbose', '--quiet'], - ['--quiet', '--verbose']]) +@pytest.mark.parametrize( + "args", + [["--verbose"], ["--quiet"], ["--verbose", "--quiet"], ["--quiet", "--verbose"]], +) def test_debug_events_verbose_quiet(libinput_debug_events, args): libinput_debug_events.run_command_success(args) -@pytest.mark.parametrize('arg', ['--banana', '--foo', '--version']) +@pytest.mark.parametrize("arg", ["--banana", "--foo", "--version"]) def test_invalid_args(libinput_debug_tool, arg): libinput_debug_tool.run_command_unrecognized_option([arg]) def test_libinput_debug_events_multiple_devices(libinput_debug_events): - libinput_debug_events.run_command_success(['--device', '/dev/input/event0', '/dev/input/event1']) + libinput_debug_events.run_command_success( + ["--device", "/dev/input/event0", "/dev/input/event1"] + ) # same event path multiple times? meh, your problem - libinput_debug_events.run_command_success(['--device', '/dev/input/event0', '/dev/input/event0']) - libinput_debug_events.run_command_success(['/dev/input/event0', '/dev/input/event1']) + libinput_debug_events.run_command_success( + ["--device", "/dev/input/event0", "/dev/input/event0"] + ) + libinput_debug_events.run_command_success( + ["/dev/input/event0", "/dev/input/event1"] + ) def test_libinput_debug_events_too_many_devices(libinput_debug_events): # Too many arguments just bails with the usage message - rc, stdout, stderr = libinput_debug_events.run_command(['/dev/input/event0'] * 61) + rc, stdout, stderr = libinput_debug_events.run_command(["/dev/input/event0"] * 61) assert rc == 2, (stdout, stderr) -@pytest.mark.parametrize('arg', ['--quiet']) +@pytest.mark.parametrize("arg", ["--quiet"]) def test_libinput_debug_gui_invalid_arg(libinput_debug_gui, arg): libinput_debug_gui.run_command_unrecognized_option([arg]) def test_libinput_debug_gui_verbose(libinput_debug_gui): - libinput_debug_gui.run_command_success(['--verbose']) + libinput_debug_gui.run_command_success(["--verbose"]) -@pytest.mark.parametrize('arg', ['--help', '--show-keycodes', '--with-libinput']) +@pytest.mark.parametrize("arg", ["--help", "--show-keycodes", "--with-libinput"]) def test_libinput_record_args(libinput_record, arg): libinput_record.run_command_success([arg]) def test_libinput_record_multiple_arg(libinput_record): # this arg is deprecated and a noop - libinput_record.run_command_success(['--multiple']) + libinput_record.run_command_success(["--multiple"]) @pytest.fixture def recording(tmp_path): - return str((tmp_path / 'record.out').resolve()) + return str((tmp_path / "record.out").resolve()) def test_libinput_record_all(libinput_record, recording): - libinput_record.run_command_success(['--all', '-o', recording]) - libinput_record.run_command_success(['--all', recording]) + libinput_record.run_command_success(["--all", "-o", recording]) + libinput_record.run_command_success(["--all", recording]) def test_libinput_record_outfile(libinput_record, recording): - libinput_record.run_command_success(['-o', recording]) - libinput_record.run_command_success(['--output-file', recording]) - libinput_record.run_command_success(['--output-file={}'.format(recording)]) + libinput_record.run_command_success(["-o", recording]) + libinput_record.run_command_success(["--output-file", recording]) + libinput_record.run_command_success(["--output-file={}".format(recording)]) def test_libinput_record_single(libinput_record, recording): - libinput_record.run_command_success(['/dev/input/event0']) - libinput_record.run_command_success(['-o', recording, '/dev/input/event0']) - libinput_record.run_command_success(['/dev/input/event0', recording]) - libinput_record.run_command_success([recording, '/dev/input/event0']) + libinput_record.run_command_success(["/dev/input/event0"]) + libinput_record.run_command_success(["-o", recording, "/dev/input/event0"]) + libinput_record.run_command_success(["/dev/input/event0", recording]) + libinput_record.run_command_success([recording, "/dev/input/event0"]) def test_libinput_record_multiple(libinput_record, recording): - libinput_record.run_command_success(['-o', recording, '/dev/input/event0', '/dev/input/event1']) - libinput_record.run_command_success([recording, '/dev/input/event0', '/dev/input/event1']) - libinput_record.run_command_success(['/dev/input/event0', '/dev/input/event1', recording]) + libinput_record.run_command_success( + ["-o", recording, "/dev/input/event0", "/dev/input/event1"] + ) + libinput_record.run_command_success( + [recording, "/dev/input/event0", "/dev/input/event1"] + ) + libinput_record.run_command_success( + ["/dev/input/event0", "/dev/input/event1", recording] + ) def test_libinput_record_autorestart(libinput_record, recording): - libinput_record.run_command_invalid(['--autorestart']) - libinput_record.run_command_invalid(['--autorestart=2']) - libinput_record.run_command_success(['-o', recording, '--autorestart=2']) + libinput_record.run_command_invalid(["--autorestart"]) + libinput_record.run_command_invalid(["--autorestart=2"]) + libinput_record.run_command_success(["-o", recording, "--autorestart=2"]) def main(): - args = ['-m', 'pytest'] + args = ["-m", "pytest"] try: import xdist # noqa - args += ['-n', 'auto'] + + args += ["-n", "auto"] except ImportError: - logger.info('python-xdist missing, this test will be slow') + logger.info("python-xdist missing, this test will be slow") pass - args += ['@MESON_BUILD_ROOT@'] + args += ["@MESON_BUILD_ROOT@"] - os.environ['LIBINPUT_RUNNING_TEST_SUITE'] = '1' + os.environ["LIBINPUT_RUNNING_TEST_SUITE"] = "1" return subprocess.run([sys.executable] + args).returncode -if __name__ == '__main__': +if __name__ == "__main__": raise SystemExit(main()) diff -Nru libinput-1.16.4/udev/libinput-device-group.c libinput-1.17.2/udev/libinput-device-group.c --- libinput-1.16.4/udev/libinput-device-group.c 2020-11-27 01:38:59.404086000 +0000 +++ libinput-1.17.2/udev/libinput-device-group.c 2021-04-30 04:25:41.547076200 +0000 @@ -30,7 +30,7 @@ #include "libinput-util.h" -#if HAVE_LIBWACOM_GET_PAIRED_DEVICE +#if HAVE_LIBWACOM #include static void @@ -209,7 +209,7 @@ } else { char *physmatch = NULL; -#if HAVE_LIBWACOM_GET_PAIRED_DEVICE +#if HAVE_LIBWACOM if (vendor_id == VENDOR_ID_WACOM) { if (product_id == PRODUCT_ID_WACOM_EKR) wacom_handle_ekr(device,