Skip to content
Commits on Source (219)
......@@ -27,15 +27,15 @@
include:
# Arch container builder template
- project: 'wayland/ci-templates'
ref: c73dae8b84697ef18e2dbbf4fed7386d9652b0cd # see https://docs.gitlab.com/ee/ci/yaml/#includefile
ref: 955e61e67cf29327cf907432f668df9eec4ca6a2 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
file: '/templates/arch.yml'
# Fedora container builder template
- project: 'wayland/ci-templates'
ref: c73dae8b84697ef18e2dbbf4fed7386d9652b0cd # see https://docs.gitlab.com/ee/ci/yaml/#includefile
ref: 955e61e67cf29327cf907432f668df9eec4ca6a2 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
file: '/templates/fedora.yml'
# Ubuntu container builder template
- project: 'wayland/ci-templates'
ref: c73dae8b84697ef18e2dbbf4fed7386d9652b0cd # see https://docs.gitlab.com/ee/ci/yaml/#includefile
ref: 955e61e67cf29327cf907432f668df9eec4ca6a2 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
file: '/templates/ubuntu.yml'
stages:
......@@ -66,10 +66,10 @@ variables:
# changing these will force rebuilding the associated image
# Note: these tags have no meaning and are not tied to a particular
# libinput version
FEDORA_TAG: '2019-03-15.0'
UBUNTU_TAG: '2019-03-15.0'
ARCH_TAG: '2019-04-14.0'
FREEBSD_TAG: '2019-03-15.0'
FEDORA_TAG: '2019-08-07.0'
UBUNTU_TAG: '2019-08-07.0'
ARCH_TAG: '2019-08-07.0'
FREEBSD_TAG: '2019-08-07.0'
UBUNTU_EXEC: "bash .gitlab-ci/ubuntu_install.sh $UBUNTU_CUSTOM_DEBS"
......@@ -81,11 +81,10 @@ variables:
FREEBSD_CONTAINER_IMAGE: $CI_REGISTRY_IMAGE/freebsd/11.2:$FREEBSD_TAG
MESON_BUILDDIR: "build dir"
NINJA_ARGS: 'test'
NINJA_ARGS: ''
MESON_ARGS: ''
MESON_TEST_ARGS: '--no-suite=hardware'
# Until we have a VM with full access, we cannot run the test suite runner
SKIP_LIBINPUT_TEST_SUITE_RUNNER: 1
# udev isn't available/working properly in the containers
UDEV_NOT_AVAILABLE: 1
GIT_DEPTH: 1
......@@ -105,6 +104,7 @@ variables:
- meson "$MESON_BUILDDIR" $MESON_ARGS
- meson configure "$MESON_BUILDDIR"
- ninja -C "$MESON_BUILDDIR" $NINJA_ARGS
- if test x"$MESON_TEST_ARGS" != "x"; then echo "Running meson test -C \"$MESON_BUILDDIR\" $MESON_TEST_ARGS"; meson test -C "$MESON_BUILDDIR" $MESON_TEST_ARGS; fi
#################################################################
# #
......@@ -137,12 +137,12 @@ variables:
skopeo inspect docker://$CI_REGISTRY_IMAGE/$IMAGE > /dev/null && exit 0 || true ;
fi
fedora:28@container-prep:
fedora:30@container-prep:
extends: .fedora@container-build
stage: container_prep
variables:
GIT_STRATEGY: none
FEDORA_VERSION: 28
FEDORA_VERSION: 30
DISTRIB_FLAVOR: fedora
DISTRIB_VERSION: $FEDORA_VERSION
TAG: $FEDORA_TAG
......@@ -171,12 +171,12 @@ ubuntu:18.10@container-prep:
TAG: $UBUNTU_TAG
<<: *pull_upstream_or_rebuild
ubuntu:18.04@container-prep:
ubuntu:19.04@container-prep:
extends: .ubuntu@container-build
stage: container_prep
variables:
GIT_STRATEGY: none
UBUNTU_VERSION: "18.04"
UBUNTU_VERSION: "19.04"
DISTRIB_FLAVOR: ubuntu
DISTRIB_VERSION: $UBUNTU_VERSION
TAG: $UBUNTU_TAG
......@@ -199,13 +199,15 @@ arch:rolling@container-prep:
image: $BUILDAH_IMAGE
<<: *pull_upstream_or_rebuild
script:
- export BUILDAH_RUN="buildah run --isolation chroot"
- export BUILDAH_COMMIT="buildah commit --format docker"
- buildcntr=$(buildah from --quiet myfreeweb/freebsd-cross:latest)
- buildah run $buildcntr apk add --no-cache $FREEBSD_BUILD_PKGS
- buildah run $buildcntr pkg -r /freebsd update -f
- buildah run $buildcntr pkg -r /freebsd install -y $FREEBSD_PKGS
- $BUILDAH_RUN $buildcntr apk add --no-cache $FREEBSD_BUILD_PKGS
- $BUILDAH_RUN $buildcntr pkg -r /freebsd update -f
- $BUILDAH_RUN $buildcntr pkg -r /freebsd install -y $FREEBSD_PKGS
- buildah config --workingdir /app $buildcntr
# tag the current container
- buildah commit --quiet $buildcntr $FREEBSD_CONTAINER_IMAGE
- $BUILDAH_COMMIT $buildcntr $FREEBSD_CONTAINER_IMAGE
# clean up the working container
- buildah rm $buildcntr
......@@ -252,10 +254,17 @@ freebsd:11.2@container-prep:
# get the r/w token from the settings to access the registry
#
# each developer needs to register a secret variable that contains
# a personal token with api access in the form of:
# PERSONAL_TOKEN_$USER (for example PERSONAL_TOKEN_bentiss)
# a personal token with api access. The token
# - must be named PERSONAL_TOKEN_$USER (for example PERSONAL_TOKEN_bentiss)
# - must be registered in the CI/CD Variables section as type file
# - value must be a netrc file as a single-line string:
# default login <user> password <token value>
# e.g. "default login bentiss password 1235abcde"
- tokenname="PERSONAL_TOKEN_$GITLAB_USER_LOGIN"
- token=$(eval echo "\$$tokenname")
- netrcfile=$(eval echo "\$$tokenname")
- if [[ ! -f "$netrcfile" ]]; then
echo "No netrc file found or token is missing, skipping job" && false;
fi
# request a token for the registry API
- REGISTRY_TOKEN=$(curl https://$GITLAB/jwt/auth --get
......@@ -265,7 +274,7 @@ freebsd:11.2@container-prep:
-d service=container_registry
-d "scope=repository:$REPOSITORY:pull,*"
--fail
--user $GITLAB_USER_LOGIN:$token
--netrc-file "$netrcfile"
| sed -r 's/(\{"token":"|"\})//g')
# get the digest of the latest image
......@@ -296,11 +305,11 @@ freebsd:11.2@container-prep:
only:
- schedules
fedora:28@container-clean:
fedora:30@container-clean:
extends: .container-clean
variables:
GIT_STRATEGY: none
FEDORA_VERSION: 28
FEDORA_VERSION: 30
CURRENT_CONTAINER_IMAGE: $FEDORA_CONTAINER_IMAGE
fedora:29@container-clean:
......@@ -317,11 +326,11 @@ ubuntu:18.10@container-clean:
UBUNTU_VERSION: "18.10"
CURRENT_CONTAINER_IMAGE: $UBUNTU_CONTAINER_IMAGE
ubuntu:18.04@container-clean:
ubuntu:19.04@container-clean:
extends: .container-clean
variables:
GIT_STRATEGY: none
UBUNTU_VERSION: "18.04"
UBUNTU_VERSION: "19.04"
CURRENT_CONTAINER_IMAGE: $UBUNTU_CONTAINER_IMAGE
arch:rolling@container-clean:
......@@ -356,27 +365,27 @@ freebsd:11.2@container-clean:
extends: .build@template
image: $FEDORA_CONTAINER_IMAGE
fedora:28@default-build:
fedora:29@default-build:
extends: .fedora-build@template
variables:
FEDORA_VERSION: 28
FEDORA_VERSION: 29
fedora:29@default-build:
fedora:30@default-build:
extends: .fedora-build@template
variables:
FEDORA_VERSION: 29
FEDORA_VERSION: 30
fedora:29@default-build-release:
fedora:30@default-build-release:
extends: .fedora-build@template
variables:
FEDORA_VERSION: 29
FEDORA_VERSION: 30
MESON_ARGS: "-Dbuildtype=release"
CFLAGS: "-Werror"
fedora:29@scan-build:
fedora:30@scan-build:
extends: .fedora-build@template
variables:
FEDORA_VERSION: 29
FEDORA_VERSION: 30
NINJA_ARGS: scan-build
before_script:
- dnf install -y clang-analyzer findutils
......@@ -390,75 +399,69 @@ fedora:29@scan-build:
# run them on one image, they shouldn't fail on one distro
# when they succeed on another.
fedora:29@build-no-libwacom:
fedora:30@build-no-libwacom:
extends: .fedora-build@template
variables:
FEDORA_VERSION: 29
FEDORA_VERSION: 30
MESON_ARGS: "-Dlibwacom=false"
fedora:29@build-no-libwacom-nodeps:
fedora:30@build-no-libwacom-nodeps:
extends: .fedora-build@template
variables:
FEDORA_VERSION: 29
FEDORA_VERSION: 30
MESON_ARGS: "-Dlibwacom=false"
before_script:
- dnf remove -y libwacom libwacom-devel
fedora:29@build-no-docs:
fedora:30@build-no-docs:
extends: .fedora-build@template
variables:
FEDORA_VERSION: 29
FEDORA_VERSION: 30
MESON_ARGS: "-Ddocumentation=false"
fedora:29@build-no-docs-nodeps:
fedora:30@build-no-docs-nodeps:
extends: .fedora-build@template
variables:
FEDORA_VERSION: 29
FEDORA_VERSION: 30
MESON_ARGS: "-Ddocumentation=false"
before_script:
- dnf remove -y doxygen graphviz
fedora:29@build-no-debuggui:
fedora:30@build-no-debuggui:
extends: .fedora-build@template
variables:
FEDORA_VERSION: 29
FEDORA_VERSION: 30
MESON_ARGS: "-Ddebug-gui=false"
fedora:29@build-no-debuggui-nodeps:
fedora:30@build-no-debuggui-nodeps:
extends: .fedora-build@template
variables:
FEDORA_VERSION: 29
FEDORA_VERSION: 30
MESON_ARGS: "-Ddebug-gui=false"
before_script:
- dnf remove -y gtk3-devel
fedora:29@build-no-tests:
fedora:30@build-no-tests:
extends: .fedora-build@template
variables:
FEDORA_VERSION: 29
FEDORA_VERSION: 30
MESON_ARGS: "-Dtests=false"
fedora:29@build-no-tests-nodeps:
fedora:30@build-no-tests-nodeps:
extends: .fedora-build@template
variables:
FEDORA_VERSION: 29
FEDORA_VERSION: 30
MESON_ARGS: "-Dtests=false"
before_script:
- dnf remove -y check-devel
fedora:29@valgrind:
fedora:30@valgrind:
extends: .fedora-build@template
variables:
FEDORA_VERSION: 29
FEDORA_VERSION: 30
MESON_TEST_ARGS: '--suite=valgrind --no-suite=hardware --setup=valgrind'
before_script:
- dnf install -y valgrind
# note: we override the default_build here by providing a new script
script:
- rm -rf "$MESON_BUILDDIR"
- meson "$MESON_BUILDDIR" $MESON_ARGS
- meson configure "$MESON_BUILDDIR"
- meson test -C "$MESON_BUILDDIR" --setup=valgrind
#
# Ubuntu
#
......@@ -472,10 +475,10 @@ ubuntu:18.10@default-build:
variables:
UBUNTU_VERSION: "18.10"
ubuntu:18.04@default-build:
ubuntu:19.04@default-build:
extends: .ubuntu@template
variables:
UBUNTU_VERSION: "18.04"
UBUNTU_VERSION: "19.04"
#
# Arch
......@@ -495,8 +498,8 @@ arch:rolling@default-build:
image: $FREEBSD_CONTAINER_IMAGE
variables:
MESON_ARGS: '--cross-file freebsd -Ddocumentation=false -Dtests=false -Depoll-dir=/freebsd/usr/local/'
# Can't run FreeBSD tests on Linux machine, so NINJA_ARGS shouldn't be "test"
NINJA_ARGS: ''
# Can't run FreeBSD tests on Linux machine, so MESON_TEST_ARGS shouldn't be "test"
MESON_TEST_ARGS: ''
freebsd:11.2@default-build:
extends: .freebsd@template
......@@ -509,8 +512,12 @@ wayland-web:
image: $BUILDAH_IMAGE
stage: deploy
script:
# Requirements:
# - variable WAYLAND_WEB_TOKEN defined as type File in libinput's CI/CD settings
# - content of that file is the token value, as generated by the Pipeline Triggers
# of the wayland.freedesktop.org project.
- curl --request POST
--form "token=$WAYLAND_WEB_TOKEN"
--form "token=<$WAYLAND_WEB_TOKEN"
--form ref=master
https://gitlab.freedesktop.org/api/v4/projects/wayland${SLASH}wayland${DOT}freedesktop${DOT}org/trigger/pipeline
only:
......
libinput (1.14.0-1) unstable; urgency=medium
* New upstream release.
* symbols: Updated.
-- Timo Aaltonen <tjaalton@debian.org> Thu, 08 Aug 2019 13:37:23 +0300
libinput (1.13.4-1) unstable; urgency=medium
* New upstream release.
......
......@@ -7,6 +7,7 @@ libinput.so.10 libinput10 #MINVER#
LIBINPUT_0.20.0@LIBINPUT_0.20.0 0.21.0
LIBINPUT_0.21.0@LIBINPUT_0.21.0 0.21.0
LIBINPUT_1.11@LIBINPUT_1.11 1.11.1
LIBINPUT_1.14@LIBINPUT_1.14 1.14.0
LIBINPUT_1.1@LIBINPUT_1.1 1.1.0
LIBINPUT_1.2@LIBINPUT_1.2 1.2.0
LIBINPUT_1.3@LIBINPUT_1.3 1.3.0
......@@ -183,6 +184,8 @@ libinput.so.10 libinput10 #MINVER#
libinput_event_tablet_tool_get_proximity_state@LIBINPUT_1.2 1.2.0
libinput_event_tablet_tool_get_rotation@LIBINPUT_1.2 1.2.0
libinput_event_tablet_tool_get_seat_button_count@LIBINPUT_1.2 1.2.0
libinput_event_tablet_tool_get_size_major@LIBINPUT_1.14 1.14.0
libinput_event_tablet_tool_get_size_minor@LIBINPUT_1.14 1.14.0
libinput_event_tablet_tool_get_slider_position@LIBINPUT_1.2 1.2.0
libinput_event_tablet_tool_get_tilt_x@LIBINPUT_1.2 1.2.0
libinput_event_tablet_tool_get_tilt_y@LIBINPUT_1.2 1.2.0
......@@ -198,6 +201,8 @@ libinput.so.10 libinput10 #MINVER#
libinput_event_tablet_tool_get_y_transformed@LIBINPUT_1.2 1.2.0
libinput_event_tablet_tool_pressure_has_changed@LIBINPUT_1.2 1.2.0
libinput_event_tablet_tool_rotation_has_changed@LIBINPUT_1.2 1.2.0
libinput_event_tablet_tool_size_major_has_changed@LIBINPUT_1.14 1.14.0
libinput_event_tablet_tool_size_minor_has_changed@LIBINPUT_1.14 1.14.0
libinput_event_tablet_tool_slider_has_changed@LIBINPUT_1.2 1.2.0
libinput_event_tablet_tool_tilt_x_has_changed@LIBINPUT_1.2 1.2.0
libinput_event_tablet_tool_tilt_y_has_changed@LIBINPUT_1.2 1.2.0
......@@ -253,6 +258,7 @@ libinput.so.10 libinput10 #MINVER#
libinput_tablet_tool_has_distance@LIBINPUT_1.2 1.2.0
libinput_tablet_tool_has_pressure@LIBINPUT_1.2 1.2.0
libinput_tablet_tool_has_rotation@LIBINPUT_1.2 1.2.0
libinput_tablet_tool_has_size@LIBINPUT_1.14 1.14.0
libinput_tablet_tool_has_slider@LIBINPUT_1.2 1.2.0
libinput_tablet_tool_has_tilt@LIBINPUT_1.2 1.2.0
libinput_tablet_tool_has_wheel@LIBINPUT_1.2 1.2.0
......
......@@ -58,8 +58,7 @@ doxyfiles = []
foreach f : src_doxygen
df = configure_file(input: f,
output: '@PLAINNAME@',
configuration : config_noop,
install : false)
configuration : config_noop)
doxyfiles += [ df ]
endforeach
......@@ -70,8 +69,7 @@ doc_config.set('builddir', meson.current_build_dir())
doxyfile = configure_file(input : 'libinput.doxygen.in',
output : 'libinput.doxygen',
configuration : doc_config,
install : false)
configuration : doc_config)
custom_target('doxygen',
input : [ doxyfiles, doxyfile, mainpage ] + src_doxygen,
......
......@@ -132,12 +132,6 @@ general-purpose **Model*** flags are listed here.
ModelALPSTouchpad, ModelAppleTouchpad, ModelWacomTouchpad, ModelChromebook
Reserved for touchpads made by the respective vendors
ModelTabletNoTilt
Indicates that the tablet stylus does not provide tilt axis
information, even if the kernel exposes that axis.
ModelTabletNoProximityOut
Indicates that the tablet stylus does not send correct proximity out
events.
ModelTouchpadVisibleMarker
Indicates the touchpad has a drawn-on visible marker between the software
buttons.
......
......@@ -18,6 +18,7 @@ to be useful.
gestures.rst
middle-button-emulation.rst
palm-detection.rst
touchpad-thumb-detection.rst
scrolling.rst
t440-support.rst
tapping.rst
......
......@@ -17,8 +17,7 @@ git_version_page = vcs_tag(command : ['git', 'log', '-1', '--format=%H'],
sphinx_conf_py = configure_file(input : 'conf.py.in',
output : 'conf.py',
configuration : sphinx_config,
install : false)
configuration : sphinx_config)
# 404 replacements for old URLs
# The switch to sphinx caused a few pages to be renamed, sphinx uses
......@@ -80,8 +79,7 @@ foreach s404 : src_404s
config_404.set('TARGET', '@0@.html'.format(tname))
c = configure_file(input : '404.rst',
output : '@0@.rst'.format(oname),
configuration : config_404,
install : false)
configuration : config_404)
dst_404s += [c]
endif
endforeach
......@@ -159,6 +157,7 @@ src_rst = files(
'touchpad-pressure.rst',
'touchpad-pressure-debugging.rst',
'touchpad-jitter.rst',
'touchpad-thumb-detection.rst',
'touchpads.rst',
'trackpoints.rst',
'trackpoint-configuration.rst',
......@@ -180,8 +179,7 @@ src_sphinx = []
foreach f : src_rst
sf = configure_file(input: f,
output: '@PLAINNAME@',
configuration : config_noop,
install : false)
configuration : config_noop)
src_sphinx += [ sf ]
endforeach
......
......@@ -65,7 +65,7 @@ pressure ranges, see :ref:`touchpad_pressure`.
Palm detection based on touch size
------------------------------------------------------------------------------
On touchads that support the ``ABS_MT_TOUCH_MAJOR`` axes, libinput can perform
On touchpads that support the ``ABS_MT_TOUCH_MAJOR`` axes, libinput can perform
palm detection based on the size of the touch ellipse. This works similar to
the pressure-based palm detection in that a touch is labelled as palm when
it exceeds the (device-specific) touch size threshold.
......
......@@ -4,18 +4,37 @@
libinput test suite
==============================================================================
libinput ships with a number of tests all run automatically on ``ninja test``.
The primary test suite is the ``libinput-test-suite``. When testing,
the ``libinput-test-suite`` should always be invoked to check for
behavior changes. The test suite relies on the kernel and udev to function
correctly. It is not suitable for running inside containers.
libinput's primary test suite can be invoked with
.. note:: ``ninja test`` runs more than just the test suite, you **must**
run all tests for full coverage.
::
$ sudo ./builddir/libinput-test-suite
When developing libinput, the ``libinput-test-suite`` should always be
run to check for behavior changes and/or regressions. For quick iteration,
the number of tests to run can be filtered, see :ref:`test-filtering`.
This allows for developers to verify a subset of tests (e.g.
touchpad tap-to-click) while hacking on that specific feature and only run
the full suite when development is done finished.
.. note:: The test suite relies on udev and the kernel, specifically uinput.
It creates virtual input devices and replays the events. This may
interfere with your running session. The test suite is not suitable
for running inside containers.
In addition, libinput ships with a set of (primarily janitorial) tests that
must pass for any merge request. These tests are invoked by calling
``meson test -C builddir`` (or ``ninja test``). The ``libinput-test-suite`` is
part of that test set by default.
The upstream CI runs all these tests but not the ``libinput-test-suite``.
This CI is run for every merge request.
The test suite runner uses
`Check <http://check.sourceforge.net/doc/check_html/>`_ underneath the hood
but most of the functionality is abstracted into *litest* wrappers.
.. _test-job-control:
------------------------------------------------------------------------------
Job control in the test suite
------------------------------------------------------------------------------
The test suite runner has a make-like job control enabled by the ``-j`` or
``--jobs`` flag and will fork off as many parallel processes as given by this
......@@ -47,8 +66,8 @@ Permissions required to run tests
Most tests require the creation of uinput devices and access to the
resulting ``/dev/input/eventX`` nodes. Some tests require temporary udev rules.
**This usually requires the tests to be run as root**. If not run as
root, the test suite runner will exit with status 77, interpreted as
"skipped" by ninja.
root, the test suite runner will exit with status 77, an exit status
interpreted as "skipped".
.. _test-filtering:
......@@ -161,7 +180,7 @@ environment variable, if set, also enables verbose mode.
::
$ ./builddir/libinput-test-suite --verbose
$ LITEST_VERBOSE=1 ninja test
$ LITEST_VERBOSE=1 meson test -C builddir
.. _test-installed:
......@@ -190,3 +209,35 @@ To configure libinput to install the tests, use the ``-Dinstall-tests=true``
meson option::
$ meson builddir -Dtests=true -Dinstall-tests=true <other options>
.. _test-meson-suites:
------------------------------------------------------------------------------
Meson test suites
------------------------------------------------------------------------------
This section is primarily of interest to distributors that want to run test
or developers working on libinput's CI.
Tests invoked by ``meson test`` are grouped into test suites, the test suite
names identify when the respective test can be run:
- ``valgrind``: tests that can be run under valgrind (in addition to a
normal run)
- ``root``: tests that must be run as root
- ``hardware``: tests that require a VM or physical machine
- ``all``: all tests, only needed because of
`meson bug 5340 <https://github.com/mesonbuild/meson/issues/5340>`_
The suite names can be provided as filters to ``meson test
--suite=<suitename>`` or ``meson test --no-suite=<suitename>``.
For example, if running a container-based CI, you may specify the test
suites as:
::
$ meson test --no-suite=machine # only run container-friendly tests
$ meson test --suite=valgrind --setup=valgrind # run all valgrind-compatible tests
$ meson test --no-suite=root # run all tests not requiring root
These suites are subject to change at any time.
.. _thumb_detection:
==============================================================================
Thumb detection
==============================================================================
Thumb detection tries to identify touches triggered by a thumb rather than a
pointer-moving finger. This is necessary on :ref:`touchpads_buttons_clickpads`
as a finger pressing a button always creates a new touch, causing
misinterpretation of gestures. Click-and-drag with two fingers (one holding
the button, one moving) would be interpreted as two-finger scrolling without
working thumb detection.
libinput has built-in thumb detection, partially dependent on
hardware-specific capabilities.
- :ref:`thumb_pressure`
- :ref:`thumb_areas`
- :ref:`thumb_speed`
Thumb detection uses multiple approaches and the final decision on whether
to ignore a thumb depends on the interaction at the time.
.. _thumb_pressure:
------------------------------------------------------------------------------
Thumb detection based on pressure or size
------------------------------------------------------------------------------
The simplest form of thumb detection identifies a touch as thumb when the
pressure value goes above a certain threshold. This threshold is usually
high enough that it cannot be triggered by a finger movement.
On touchpads that support the ``ABS_MT_TOUCH_MAJOR`` axes, libinput can perform
thumb detection based on the size of the touch ellipse. This works similar to
the pressure-based palm detection in that a touch is labelled as palm when
it exceeds the (device-specific) touch size threshold.
Pressure- and size-based thumb detection depends on the location of the
thumb and usually only applies within the :ref:`thumb_areas`.
For some information on how to detect pressure on a touch and debug the
pressure ranges, see :ref:`touchpad_pressure`. Pressure- and size-based
thumb detection require thresholds set in the :ref:`device-quirks`.
.. _thumb_areas:
------------------------------------------------------------------------------
Thumb detection areas
------------------------------------------------------------------------------
Pressure and size readings are unreliable at the far bottom of the touchpad.
A thumb hanging mostly off the touchpad will have a small surface area.
libinput has a definitive thumb zone where any touch is considered a
thumb. Immediately above that area is the area where libinput will label a
thumb as such if the pressure or size thresholds are exceeded.
.. figure:: thumb-detection.svg
:align: center
The picture above shows the two detection areas. In the larger (light red)
area, a touch is labelled as thumb when it exceeds a device-specific
pressure threshold. In the lower (dark red) area, a touch is always labelled
as thumb.
Moving outside the areas generally releases the thumb from being a thumb.
.. _thumb_speed:
------------------------------------------------------------------------------
Thumb movement based on speed
------------------------------------------------------------------------------
Regular interactions with thumbs do not usually move the thumb. When fingers
are moving across the touchpad and a thumb is dropped, this can cause
erroneous scroll motion or similar issues. libinput observes the finger
motion speed for all touches - where a finger has been moving a newly
dropped finger is more likely to be labeled as thumb.
------------------------------------------------------------------------------
Thumb detection based on finger positions
------------------------------------------------------------------------------
The shape of the human hand and the interactions that usually involve a
thumb imply that a thumb is situated in a specific position relative to
other fingers (usually to the side and below). This is used by libinput to
detect thumbs during some interactions that do not implicitly require a
thumb (e.g. pinch-and-rotate).
This diff is collapsed.
project('libinput', 'c',
version : '1.13.4',
version : '1.14.0',
license : 'MIT/Expat',
default_options : [ 'c_std=gnu99', 'warning_level=2' ],
meson_version : '>= 0.41.0')
......@@ -149,8 +149,8 @@ executable('libinput-device-group',
include_directories : [includes_src, includes_include],
install : true,
install_dir : dir_udev_callouts)
executable('libinput-model-quirks',
'udev/libinput-model-quirks.c',
executable('libinput-fuzz-override',
'udev/libinput-fuzz-override.c',
dependencies : [dep_udev, dep_libevdev],
include_directories : [includes_src, includes_include],
install : true,
......@@ -160,12 +160,10 @@ udev_rules_config = configuration_data()
udev_rules_config.set('UDEV_TEST_PATH', '')
configure_file(input : 'udev/80-libinput-device-groups.rules.in',
output : '80-libinput-device-groups.rules',
install : true,
install_dir : dir_udev_rules,
configuration : udev_rules_config)
configure_file(input : 'udev/90-libinput-model-quirks.rules.in',
output : '90-libinput-model-quirks.rules',
install : true,
configure_file(input : 'udev/90-libinput-fuzz-override.rules.in',
output : '90-libinput-fuzz-override.rules',
install_dir : dir_udev_rules,
configuration : udev_rules_config)
......@@ -173,13 +171,24 @@ litest_udev_rules_config = configuration_data()
litest_udev_rules_config.set('UDEV_TEST_PATH', meson.build_root() + '/')
litest_groups_rules_file = configure_file(input : 'udev/80-libinput-device-groups.rules.in',
output : '80-libinput-device-groups-litest.rules',
install : false,
configuration : litest_udev_rules_config)
litest_model_quirks_file = configure_file(input : 'udev/90-libinput-model-quirks.rules.in',
output : '90-libinput-model-quirks-litest.rules',
install : false,
litest_fuzz_override_file = configure_file(input : 'udev/90-libinput-fuzz-override.rules.in',
output : '90-libinput-fuzz-override-litest.rules',
configuration : litest_udev_rules_config)
############ Check for leftover udev rules ########
# This test should be defined first so we don't waste time testing anything
# else if we're about to fail anyway. ninja test will execute tests in the
# order of them defined in meson.build
if get_option('tests')
test('leftover-rules',
find_program('test/check-leftover-udev-rules.sh'),
is_parallel : false,
suite : ['all'])
endif
############ libepoll-shim (BSD) ############
if cc.has_header_symbol('sys/epoll.h', 'epoll_create1', prefix : prefix)
......@@ -215,7 +224,7 @@ src_libinput_util = [
]
libinput_util = static_library('libinput-util',
src_libinput_util,
dependencies : [dep_udev, dep_libevdev],
dependencies : [dep_udev, dep_libevdev, dep_libwacom],
include_directories : includes_include)
dep_libinput_util = declare_dependency(link_with : libinput_util)
......@@ -233,7 +242,7 @@ src_libfilter = [
'src/filter-private.h'
]
libfilter = static_library('filter', src_libfilter,
dependencies : dep_udev,
dependencies : [dep_udev, dep_libwacom],
include_directories : includes_include)
dep_libfilter = declare_dependency(link_with : libfilter)
......@@ -250,9 +259,8 @@ quirks_data = [
'quirks/30-vendor-aiptek.quirks',
'quirks/30-vendor-alps.quirks',
'quirks/30-vendor-contour.quirks',
'quirks/30-vendor-cyapa.quirks',
'quirks/30-vendor-cypress.quirks',
'quirks/30-vendor-elantech.quirks',
'quirks/30-vendor-huion.quirks',
'quirks/30-vendor-ibm.quirks',
'quirks/30-vendor-kensington.quirks',
'quirks/30-vendor-logitech.quirks',
......@@ -276,7 +284,9 @@ quirks_data = [
test('quirks-in-meson.build',
find_program('quirks/test-quirks-in-meson.build.sh'),
args : [meson.source_root()])
args : [meson.source_root()],
suite : ['all']
)
config_h.set_quoted('LIBINPUT_QUIRKS_FILES', ':'.join(quirks_data))
config_h.set_quoted('LIBINPUT_QUIRKS_SRCDIR', dir_src_quirks)
......@@ -289,7 +299,7 @@ src_libquirks = [
'src/builddir.h',
]
deps_libquirks = [dep_udev, dep_libinput_util]
deps_libquirks = [dep_udev, dep_libwacom, dep_libinput_util]
libquirks = static_library('quirks', src_libquirks,
dependencies : deps_libquirks,
include_directories : includes_include)
......@@ -306,10 +316,12 @@ src_libinput = src_libfilter + [
'src/evdev-debounce.c',
'src/evdev-fallback.c',
'src/evdev-fallback.h',
'src/evdev-totem.c',
'src/evdev-middle-button.c',
'src/evdev-mt-touchpad.c',
'src/evdev-mt-touchpad.h',
'src/evdev-mt-touchpad-tap.c',
'src/evdev-mt-touchpad-thumb.c',
'src/evdev-mt-touchpad-buttons.c',
'src/evdev-mt-touchpad-edge-scroll.c',
'src/evdev-mt-touchpad-gestures.c',
......@@ -318,7 +330,6 @@ src_libinput = src_libfilter + [
'src/evdev-tablet-pad.c',
'src/evdev-tablet-pad.h',
'src/evdev-tablet-pad-leds.c',
'src/path-seat.h',
'src/path-seat.c',
'src/udev-seat.c',
'src/udev-seat.h',
......@@ -349,7 +360,6 @@ libinput_version_h = configure_file(
input : 'src/libinput-version.h.in',
output : 'libinput-version.h',
configuration : libinput_version_h_config,
install : false,
)
mapfile = join_paths(dir_src, 'libinput.sym')
......@@ -425,7 +435,6 @@ executable('libinput-debug-events',
configure_file(input : 'tools/libinput-debug-events.man',
output : 'libinput-debug-events.1',
configuration : man_config,
install : true,
install_dir : dir_man1,
)
......@@ -439,26 +448,24 @@ libinput_quirks = executable('libinput-quirks',
)
test('validate-quirks',
libinput_quirks,
args: ['validate', '--data-dir=@0@'.format(dir_src_quirks)]
args: ['validate', '--data-dir=@0@'.format(dir_src_quirks)],
suite : ['all']
)
configure_file(input : 'tools/libinput-quirks.man',
output : 'libinput-quirks.1',
configuration : man_config,
install : true,
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 : true,
install_dir : dir_man1,
)
configure_file(input : 'tools/libinput-quirks.man',
output : 'libinput-quirks-validate.1',
configuration : man_config,
install : true,
install_dir : dir_man1,
)
......@@ -470,12 +477,13 @@ libinput_list_devices = executable('libinput-list-devices',
install_dir : libinput_tool_path,
install : true,
)
test('list-devices', libinput_list_devices)
test('list-devices',
libinput_list_devices,
suite : ['all', 'root', 'hardware'])
configure_file(input : 'tools/libinput-list-devices.man',
output : 'libinput-list-devices.1',
configuration : man_config,
install : true,
install_dir : dir_man1,
)
......@@ -490,7 +498,6 @@ executable('libinput-measure',
configure_file(input : 'tools/libinput-measure.man',
output : 'libinput-measure.1',
configuration : man_config,
install : true,
install_dir : dir_man1,
)
......@@ -512,7 +519,6 @@ foreach t : src_python_tools
configure_file(input: t,
output: '@BASENAME@',
configuration : config_noop,
install : true,
install_dir : libinput_tool_path
)
endforeach
......@@ -528,7 +534,6 @@ foreach m : src_man
configure_file(input : m,
output : '@BASENAME@.1',
configuration : man_config,
install : true,
install_dir : dir_man1)
endforeach
......@@ -543,7 +548,6 @@ executable('libinput-record',
configure_file(input : 'tools/libinput-record.man',
output : 'libinput-record.1',
configuration : man_config,
install : true,
install_dir : dir_man1,
)
......@@ -552,7 +556,6 @@ install_data('tools/libinput-replay',
configure_file(input : 'tools/libinput-replay.man',
output : 'libinput-replay.1',
configuration : man_config,
install : true,
install_dir : dir_man1,
)
......@@ -577,7 +580,6 @@ if get_option('debug-gui')
configure_file(input : 'tools/libinput-debug-gui.man',
output : 'libinput-debug-gui.1',
configuration : man_config,
install : true,
install_dir : dir_man1,
)
endif
......@@ -593,7 +595,6 @@ libinput_tool = executable('libinput',
configure_file(input : 'tools/libinput.man',
output : 'libinput.1',
configuration : man_config,
install : true,
install_dir : dir_man1,
)
......@@ -608,10 +609,16 @@ executable('ptraccel-debug',
# Don't run the test during a release build because we rely on the magic
# subtool lookup
if get_option('buildtype') == 'debug' or get_option('buildtype') == 'debugoptimized'
config_tool_option_test = configuration_data()
config_tool_option_test.set('MESON_ENABLED_DEBUG_GUI', get_option('debug-gui'))
tool_option_test = configure_file(input: 'tools/test-tool-option-parsing.py',
output: '@BASENAME@',
configuration : config_tool_option_test)
test('tool-option-parsing',
find_program('tools/test-tool-option-parsing.py'),
tool_option_test,
args : ['--tool-path', libinput_tool.full_path()],
timeout : 120)
suite : ['all', 'root'],
timeout : 240)
endif
# the libinput tools check whether we execute from the builddir, this is
......@@ -624,18 +631,21 @@ test_builddir_lookup = executable('test-builddir-lookup',
install : false)
test('tools-builddir-lookup',
test_builddir_lookup,
args : ['--builddir-is-set'])
args : ['--builddir-is-set'],
suite : ['all'])
test('tools-builddir-lookup-installed',
find_program('test/helper-copy-and-exec-from-tmp.sh'),
args : [test_builddir_lookup.full_path(), '--builddir-is-null'],
env : ['LD_LIBRARY_PATH=@0@'.format(meson.build_root())],
suite : ['all'],
workdir : '/tmp')
############ tests ############
test('symbols-leak-test',
find_program('test/symbols-leak-test'),
args : [ join_paths(dir_src, 'libinput.sym'), dir_src])
args : [ join_paths(dir_src, 'libinput.sym'), dir_src],
suite : ['all'])
# build-test only
executable('test-build-pedantic',
......@@ -671,9 +681,6 @@ endif
if get_option('tests')
dep_check = dependency('check', version : '>= 0.9.10')
leftover_rules = find_program('test/check-leftover-udev-rules.sh')
test('leftover-rules', leftover_rules, is_parallel : false)
gstack = find_program('gstack', required : false)
config_h.set10('HAVE_GSTACK', gstack.found())
......@@ -698,6 +705,8 @@ if get_option('tests')
'test/litest-device-bcm5974.c',
'test/litest-device-calibrated-touchscreen.c',
'test/litest-device-cyborg-rat-5.c',
'test/litest-device-dell-canvas-totem.c',
'test/litest-device-dell-canvas-totem-touch.c',
'test/litest-device-elantech-touchpad.c',
'test/litest-device-generic-singletouch.c',
'test/litest-device-gpio-keys.c',
......@@ -757,6 +766,7 @@ if get_option('tests')
'test/litest-device-wacom-intuos5-finger.c',
'test/litest-device-wacom-intuos5-pad.c',
'test/litest-device-wacom-intuos5-pen.c',
'test/litest-device-wacom-isdv4-4200-pen.c',
'test/litest-device-wacom-isdv4-e6-pen.c',
'test/litest-device-wacom-isdv4-e6-finger.c',
'test/litest-device-wacom-mobilestudio-pro-pad.c',
......@@ -765,7 +775,8 @@ if get_option('tests')
'test/litest-device-xen-virtual-pointer.c',
'test/litest-device-vmware-virtual-usb-mouse.c',
'test/litest-device-yubikey.c',
'test/litest.c'
'test/litest.c',
'include/valgrind/valgrind.h'
]
dep_dl = cc.find_library('dl')
......@@ -782,9 +793,11 @@ if get_option('tests')
litest_config_h = configuration_data()
litest_config_h.set_quoted('LIBINPUT_DEVICE_GROUPS_RULES_FILE',
join_paths(meson.build_root(), '80-libinput-device-groups.rules'))
litest_config_h.set_quoted('LIBINPUT_MODEL_QUIRKS_UDEV_RULES_FILE',
join_paths(meson.build_root(), '90-libinput-model-quirks.rules'))
join_paths(meson.build_root(),
'80-libinput-device-groups-litest.rules'))
litest_config_h.set_quoted('LIBINPUT_FUZZ_OVERRIDE_UDEV_RULES_FILE',
join_paths(meson.build_root(),
'90-libinput-fuzz-override-litest.rules'))
def_no_main = '-DLITEST_NO_MAIN'
def_disable_backtrace = '-DLITEST_DISABLE_BACKTRACE_LOGGING'
......@@ -803,14 +816,19 @@ if get_option('tests')
dependencies : deps_litest,
c_args : defs_litest_selftest,
install : false)
test('test-litest-selftest', test_litest_selftest)
test('test-litest-selftest',
test_litest_selftest,
suite : ['all'],
timeout : 100)
def_LT_VERSION = '-DLIBINPUT_LT_VERSION="@0@:@1@:@2@"'.format(libinput_lt_c, libinput_lt_r, libinput_lt_a)
test_library_version = executable('test-library-version',
['test/test-library-version.c'],
c_args : [ def_LT_VERSION ],
install : false)
test('test-library-version', test_library_version)
test('test-library-version',
test_library_version,
suite : ['all'])
test_utils_sources = [
'src/libinput-util.h',
......@@ -822,7 +840,9 @@ if get_option('tests')
include_directories : [includes_src, includes_include],
dependencies : deps_litest,
install: false)
test('test-utils', test_utils)
test('test-utils',
test_utils,
suite : ['all'])
libinput_test_runner_sources = litest_sources + [
'src/libinput-util.h',
......@@ -833,6 +853,7 @@ if get_option('tests')
'test/test-touch.c',
'test/test-log.c',
'test/test-tablet.c',
'test/test-totem.c',
'test/test-pad.c',
'test/test-touchpad.c',
'test/test-touchpad-tap.c',
......@@ -855,23 +876,35 @@ if get_option('tests')
configure_file(input : 'test/libinput-test-suite.man',
output : 'libinput-test-suite.1',
configuration : man_config,
install : true,
install_dir : dir_man1,
)
test('libinput-test-suite-runner',
# 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
test('libinput-test-suite-@0@'.format(group),
libinput_test_runner,
suite : ['all', 'valgrind', 'root', 'hardware'],
args : ['--filter-group=@0@:*'.format(group)],
is_parallel : false,
timeout : 1200)
endforeach
test('libinput-test-deviceless',
libinput_test_runner,
suite : ['all', 'valgrind'],
args: ['--filter-deviceless'])
valgrind = find_program('valgrind', required : false)
if valgrind.found()
valgrind_env = environment()
valgrind_env.set('CK_FORK', 'no')
valgrind_env.set('USING_VALGRIND', '1')
valgrind_env.set('LITEST_JOBS', '4')
valgrind_suppressions_file = join_paths(dir_src_test, 'valgrind.suppressions')
add_test_setup('valgrind',
exe_wrapper : [ valgrind,
......@@ -885,8 +918,7 @@ if get_option('tests')
message('valgrind not found, disabling valgrind test suite')
endif
configure_file(output : 'litest-config.h',
install : false,
configuration : litest_config_h)
endif
############ output files ############
configure_file(output : 'config.h', install : false, configuration : config_h)
configure_file(output : 'config.h', configuration : config_h)
......@@ -3,3 +3,9 @@
[Cyapa Touchpads]
MatchName=*Cypress APA Trackpad ?cyapa?
AttrPressureRange=10:8
[Cypress Touchpads]
MatchUdevType=touchpad
MatchName=*CyPS/2 Cypress Trackpad
AttrPressureRange=10:8
AttrPalmPressureThreshold=254
# Do not edit this file, it will be overwritten on update
# HUION PenTablet device. Some of these devices send a BTN_TOOL_PEN event
# with value 1 on the first event received by the device but never send the
# matching BTN_TOOL_PEN value 0 event. The device appears as if it was
# permanently in proximity.
#
# HUION re-uses USB IDs for its devices, not every HUION tablet is
# affected by this bug, libinput will auto-disable this feature
[HUION PenTablet]
MatchUdevType=tablet
MatchBus=usb
MatchVendor=0x256C
ModelTabletNoProximityOut=1
......@@ -12,3 +12,11 @@ MatchBus=usb
MatchVendor=0x056A
MatchProduct=0x0357
AttrPalmSizeThreshold=5
[Wacom ISDV4 Pen]
MatchUdevType=tablet
MatchBus=usb
MatchVendor=0x56A
MatchProduct=0x4200
ModelWacomISDV4Pen=1
AttrEventCodeDisable=ABS_TILT_X;ABS_TILT_Y;
......@@ -33,6 +33,18 @@ MatchName=*DualPoint Stick
MatchDMIModalias=dmi:*svnDellInc.:pnLatitudeD620*
AttrTrackpointMultiplier=0.5
[Latitude E5480 Trackpoint]
MatchName=*DualPoint Stick
MatchUdevType=pointingstick
MatchDMIModalias=dmi:**bvnDellInc.:*:pnLatitude5480*
AttrTrackpointMultiplier=0.5
[Latitude 5580 Trackpoint]
MatchName=*DualPoint Stick
MatchUdevType=pointingstick
MatchDMIModalias=dmi:**bvnDellInc.:*:pnLatitude5580*
AttrTrackpointMultiplier=0.5
[Latitude E5570 Trackpoint]
MatchName=*DualPoint Stick
MatchDMIModalias=dmi:*svnDellInc.:pnLatitudeE5570*
......@@ -52,3 +64,12 @@ AttrTrackpointMultiplier=1.5
MatchName=*DualPoint Stick
MatchDMIModalias=dmi:*svnDellInc.:pnLatitudeE7470*
AttrTrackpointMultiplier=0.125
# The touch device has the same vid/pid as the totem, the MatchName
# directive is required here
[Canvas Totem]
MatchName=*System Multi Axis
MatchBus=usb
MatchVendor=0x2575
MatchProduct=0x0204
ModelDellCanvasTotem=1
......@@ -41,9 +41,3 @@ MatchDMIModalias=dmi:*svnHP:pnHPSpectrex360Convertible15-bl1XX:*
AttrPressureRange=55:40
AttrThumbPressureThreshold=90
AttrPalmPressureThreshold=100
[HP Spectre x360 Convertible 13-ap0xxx]
MatchUdevType=tablet
MatchName=ELAN2514:00 04F3:2812
MatchDMIModalias=dmi:*svnHP:pnHPSpectrex360Convertible13-ap0xxx:*
ModelTabletNoProximityOut=1
......@@ -1410,7 +1410,7 @@ fallback_pair_tablet_mode(struct evdev_device *keyboard,
return;
evdev_log_debug(keyboard,
"tablet_mode_switch: paired %s<->%s\n",
"tablet-mode: paired %s<->%s\n",
keyboard->devname,
tablet_mode_switch->devname);
......
......@@ -1042,8 +1042,7 @@ tp_clickfinger_within_distance(struct tp_dispatch *tp,
if (!t1 || !t2)
return 0;
if (t1->thumb.state == THUMB_STATE_YES ||
t2->thumb.state == THUMB_STATE_YES)
if (tp_thumb_ignored(tp, t1) || tp_thumb_ignored(tp, t2))
return 0;
x = abs(t1->point.x - t2->point.x);
......@@ -1098,7 +1097,7 @@ tp_clickfinger_set_button(struct tp_dispatch *tp)
if (t->state != TOUCH_BEGIN && t->state != TOUCH_UPDATE)
continue;
if (t->thumb.state == THUMB_STATE_YES)
if (tp_thumb_ignored(tp, t))
continue;
if (t->palm.state != PALM_NONE)
......
......@@ -260,6 +260,7 @@ tp_edge_scroll_handle_event(struct tp_dispatch *tp,
break;
}
if (current != t->scroll.edge_state)
evdev_log_debug(tp->device,
"edge-scroll: touch %d state %s → %s → %s\n",
t->index,
......@@ -398,8 +399,7 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
if (!t->dirty)
continue;
if (t->palm.state != PALM_NONE ||
t->thumb.state == THUMB_STATE_YES)
if (t->palm.state != PALM_NONE || tp_thumb_ignored(tp, t))
continue;
/* only scroll with the finger in the previous edge */
......