Compare commits

..

25 commits
main ... 1.1.8

Author SHA1 Message Date
Peter Hutterer
a341942d7e configure.ac: libinput 1.1.8
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2016-02-18 11:16:14 +10:00
Peter Hutterer
86bd9bad66 touchpad: move the tapping exclusion zone to the top edge of the button
We previously used the half-way mark of the touchpad's y axis to decide where
to ignore tapping. Move this down to the top edge of the software buttons
instead. Users may tap with a finger in the software button areas, on the rest
of the touchpad it's unlikely that they tap within 5% of the edge.

On touchpads with physical buttons or if clickfinger is enabled, the
no-tapping zone extends to the bottom of the touchpad. This required splitting
the tests into clickfinger, softbuttons and hardbuttons.

https://bugs.freedesktop.org/show_bug.cgi?id=93947

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit 79139ebcd1)
2016-02-18 11:15:56 +10:00
Peter Hutterer
fb0f8c6221 touchpad: add synaptics semi-mt devices to those needing hysteresis
https://bugs.freedesktop.org/show_bug.cgi?id=94097

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit d6b889852a)
2016-02-18 11:15:50 +10:00
Peter Hutterer
ecb286fa82 configure.ac: libinput 1.1.7
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2016-02-10 08:22:50 +10:00
Peter Hutterer
e013b7fef8 touchpad: init a default hysteresis for ALPS rushmore touchpads
https://bugs.freedesktop.org/show_bug.cgi?id=90590

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit 07420eec05)
2016-02-10 08:22:02 +10:00
Peter Hutterer
23b506f318 udev: fix ALPS firmware detection
The firmware version is in id.version, not id.model which is always
PSMOUSE_ALPS for ALPS devices.

The various fw versions are listed in <kernel>/drivers/input/mouse/alps.h and
are all hex numbers. Version 8 is actually 0x800, change the match
accordingly.

Expected side-effect: earlier versions of ALPS touchpads now lose their
(erroneous) size assignment.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 1f304763b4)
2016-02-10 08:22:01 +10:00
Peter Hutterer
216c6aae54 touchpad: fix dwt disabling while a key is still down
If dwt is disabled on the commandline, e.g. by setting an xinput property it
may be disabled before the release event comes in. This caused the timer to
refresh indefinitely since the key state mask was still on for that key.
Always updating the key state mask (even when dwt is disabled) fixes that.

If a key is held down while dwt is disabled, this can still cause a indefinite
timer refresh, so in the timer func, check if dwt is enabled before refreshing
the timer.

https://bugs.freedesktop.org/show_bug.cgi?id=94015

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit 0e87dc9af2)
2016-02-10 08:21:59 +10:00
Peter Hutterer
b09856aea8 configure.ac: libinput 1.1.6
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2016-02-05 12:37:00 +10:00
Peter Hutterer
7196f5101e touchpad: if we have a serio keyboard, override any previous dwt pairing
If a USB keyboard like the YubiKey is found before the internal keyboard, it
will be paired with the touchpad when it is seen. The internal keyboard is
seen later bug ignored because we already have a keyboard paired with the
touchpad.

This is obviously wrong. For now, give priority to serio keyboards, and
override existing dwt pairings with the new keyboard.

https://bugs.freedesktop.org/show_bug.cgi?id=93983

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit 0b0150e08d)
2016-02-05 12:37:00 +10:00
Peter Hutterer
f0bb4b0e8c touchpad: while a key is held down, don't disable dwt
If a key enables dwt and is held down when the timeout expires, re-issue the
timeout.

There is a corner case where dwt may not work as expected:
1. key down and held down
2. dwt timer expires, dwt is re-issued
3. touch starts
4. key is released
5. dwt timer expires
6. touch now starts moving the pointer

This is an effect of the smart touch detection. A touch starting after the
last key press is released for pointer motion once dwt turns off again. This
is what happens in the above case, the dwt timer expiring is the last virtual
key press. This is a corner case and likely hard to trigger by a real user.

https://bugs.freedesktop.org/show_bug.cgi?id=93984

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit b27f04689e)
2016-02-05 12:36:59 +10:00
Peter Hutterer
54759c81b5 touchpad: drop motion hysteresis by default
Some older touchpad devices jitter a fair bit when a finger is resting on the
touchpad. That's why the hysteresis was introduced in the synaptics driver
back in 2011. However, the default value of the hysteresis in the synaptics
driver ended up being 0, even though the code looks like it's using a fraction
of the touchpad diagonal. When the hysteresis code was ported to libinput it
was eventually set to 0.5mm.

Turns out this is still too high and tiny finger motions are either
nonreactive or quite jumpy, making it hard to select small targets. Drop the
default hysteresis by reducing its margin to 0, but leave it in place for
those devices where we need them (e.g. the cyapa touchpads).

https://bugs.freedesktop.org/show_bug.cgi?id=93503

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit 6e0553ab5553d63fa737c1739cfa86fbeee9f641)
2016-02-05 12:36:59 +10:00
Peter Hutterer
2e02d94e2b test: fix leaking libevdev fd
This was the reason for the valgrind test case failures whenever we
accumulated too many tests (see 9c2afae1 and 2a110104). The cause was simply
that we ran out of fds which caused libevdev to fail the scandir() searching
for the event node. That resulted in a NULL devnode and an abort in litest.

Close the fd before freeing the evdev device.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit a84bf167a3)
2016-02-05 12:36:59 +10:00
Peter Hutterer
92933e79f8 evdev: disable the mode button on the Cyborg RAT 5
This button sends a release N, press N+1 on each press, cycling through the
three event codes supported. This causes a stuck button since the current mode
is never released.

Long-term this better served by a set of switches that toggle accordingly, for
now disable the button codes.

https://bugs.freedesktop.org/show_bug.cgi?id=92127

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit e19d5d228c)
2016-02-05 12:36:59 +10:00
Peter Hutterer
d06ed108b0 gestures: average motion by active touches, not moved touches
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit b6f59d0e3b)
2016-02-05 12:36:59 +10:00
Peter Hutterer
815af6dec8 test: exclude semi-mt devices from the normal 2fg scroll test
We have a specific semi-mt 2fg scroll test for those.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit c352a50295)
2016-02-05 12:36:59 +10:00
Peter Hutterer
dcd48bb3b3 test: run pinch gesture tests for 2-slot touchpads
Some of the 2-slot touchpads don't do gestures though (e.g. semi-mt) so skip
those.

And change the movement granularity for the pinch and spread tests so we stay
under one degree angle for lower-resolution touchpads too.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit ff2ee2c681)
2016-02-05 12:36:59 +10:00
Peter Hutterer
7cce284063 test: fix compiler warning
litest-selftest.c: In function ‘litest_ptr_eq_notrigger’:
litest-selftest.c:172:10: warning: initialization makes integer from pointer
without a cast [-Wint-conversion]
  int c = NULL;
          ^
litest-selftest.c:173:10: warning: initialization makes integer from pointer
without a cast [-Wint-conversion]
  int d = NULL;
          ^

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 82335b0ab9)
2016-02-04 14:21:10 +10:00
Peter Hutterer
c18f62da14 configure.ac: libinput 1.1.5
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2016-01-25 14:19:36 +10:00
Peter Hutterer
53b021a1da touchpad: disable gestures for single-finger touchpads
No point trying to detect pinch gestures if we only have one set of
coordinates. This makes two-finger scrolling on ST touchpads more reactive.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit 28205d6f29)
2016-01-25 13:38:55 +10:00
Peter Hutterer
983a8ec4c2 touchpad: disable MT for all semi-mt devices
Synaptics, Elantech and Alps semi-mt devices all have issues with reporting
correct MT data, even the bounding box which semi-mt devices are supposed to
report is wrong.

Synaptics devices have massive jumps with two fingers down. Elantech devices
may open slots without coordinate data. Alps devices may send 0/0 coordinates
as initial slot position.

All these may be addressable with specific quirks, but the actual benefit is
largely restricted to better palm detection (though even with quirks this is
unlikely to work) and support for pinch gestures (again, lack of coordinates
makes supporting those hard anyway).

Elantech: https://bugs.freedesktop.org/show_bug.cgi?id=93583
Alps: https://bugzilla.redhat.com/show_bug.cgi?id=1295073

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit 342bc51016)
2016-01-25 13:38:55 +10:00
Peter Hutterer
ea3f1c2131 test: when moving 2 fingers, move them in the same frame
More accurate representation of what we actually want to do. Plus it avoids
weird test case failures in semi-mt where we always pick the t/l and b/r
touches for the bounding box. That is the proper behavior for semi-mt, but
it's not for the tests where we expect simultaneous finger movement.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit d19307f20d)
2016-01-25 13:38:55 +10:00
Peter Hutterer
fd278a2eda touchpad: disable MT for elantech semi-mt touchpads
When three fingers are set down on the touchpad, one finger tends to get a 0/0
coordinate, triggering palm detection in the upper left corner. Handle this
like the jumping semi-mt touchpads and disable MT handling and instead
just rely on the x/y axis and the BTN_TOOL_* events.

https://bugs.freedesktop.org/show_bug.cgi?id=93583

This kernel patch is required:
https://lkml.org/lkml/2016/1/11/171

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit 556aac04b5)
2016-01-25 13:29:16 +10:00
Peter Hutterer
17f742dcd3 doc: add section names to motion normalization subheaders
Otherwise the first word is used as section header and discarded from the
output.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 41cc9053dd)
2016-01-25 13:29:12 +10:00
Peter Hutterer
65f6cd9c6e evdev: only reject devices with missing MT x/y if they're MT devices
A fake MT device may have ABS_MT_POSITION_X but not Y. In this case we don't
care, because we don't handle those axes anyway.

http://bugs.freedesktop.org/show_bug.cgi?id=93474

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit 988cfda42c)
2016-01-25 13:29:07 +10:00
Caibin Chen
9dab84fe92 touchpad: fix DWT pairing for Macbook Pro 2015
Label internal keyboards through the udev hwdb and only pair the internal
(usb) Apple touchpads with those keyboards labelled as such.

https://bugs.freedesktop.org/show_bug.cgi?id=93367

Co-authored-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit b3f11180e3)
2016-01-25 13:29:02 +10:00
564 changed files with 41382 additions and 159542 deletions

View file

@ -1,82 +0,0 @@
AlignAfterOpenBracket: Align
# This option we want but it's frequently broken and causes bad
# misalignment. The canary is wheel_click_count_parser, if that works
# we can actually enable it.
# AlignArrayOfStructures: Left
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: true
AlignConsecutiveShortCaseStatements:
Enabled: true
AcrossEmptyLines: false
AcrossComments: true
AlignCaseColons: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakBeforeMultilineStrings: true
BinPackArguments: false
BinPackParameters: OnePerLine
BraceWrapping:
AfterFunction: true
BreakAfterReturnType: All
BreakBeforeBraces: Custom
BreakStringLiterals: false
ColumnLimit: 88
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^(<|")config\.h(>|")'
Priority: 0
SortPriority: 0
- Regex: '^<.*'
Priority: 1
SortPriority: 0
- Regex: '^"util-.*'
Priority: 2
SortPriority: 0
- Regex: '.*'
Priority: 3
SortPriority: 0
IndentCaseLabels: false
IndentGotoLabels: false
IndentWidth: 8
MaxEmptyLinesToKeep: 1
PointerAlignment: Right
ReflowComments: true
RemoveEmptyLinesInUnwrappedLines: true
RemoveParentheses: MultipleParentheses
RemoveSemicolon: true
SkipMacroDefinitionBody: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeParens: ControlStatementsExceptControlMacros
SpacesInContainerLiterals: true
SpacesInParens: Custom
TabWidth: 8
UseTab: ForContinuationAndIndentation
ForEachMacros:
- ARRAY_FOR_EACH
- list_for_each
- list_for_each_safe
- tp_for_each_touch
- range_for_each
- litest_log_group
- litest_with_logcapture
- litest_with_parameters
- litest_with_event_frame
- udev_list_entry_foreach
# END_TEST is defined as something that enforces a line break
Macros: [ "CASE_RETURN_STRING(s)=case s: return s", "START_TEST(s)=static void s(void)", "END_TEST=enum foo;"]

View file

@ -1 +0,0 @@
include/**/*

View file

@ -1,7 +0,0 @@
# optin.core.unix.Malloc: disabled so we can use __attribute__((cleanup)) without leak complaints
# optin.core.EnumCastOutOfRange: disabled because we use a lot of "wrong" enum values for testing
# and internally and don't want those values leak into the public API
Checks: >
-clang-analyzer-unix.Malloc,
-clang-analyzer-optin.core.EnumCastOutOfRange
WarningsAsErrors: '*'

View file

@ -1 +0,0 @@
include/*

View file

@ -1,4 +0,0 @@
((nil . ((indent-tabs-mode . t)
(tab-width . 8)
(fill-column . 80)))
(c-mode . ((c-basic-offset . 8))))

View file

@ -1,25 +0,0 @@
# https://editorconfig.org/
root = true
[*]
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
[*.{c,h}]
indent_size = 8
indent_style = tab
[*.py]
indent_size = 4
indent_style = space
[{meson.build,meson_options.txt}]
indent_size = 8
indent_style = tab
[*.sym]
indent_size = 8
indent_style = tab

View file

@ -1,21 +0,0 @@
# This file contains revisions to be ignored by git blame.
# These revisions are expected to be formatting-only changes.
#
# Calling `git blame --ignore-revs-file .git-blame-ignore-revs` will
# tell git blame to ignore changes made by these revisions when assigning
# assigning blame, as if the change never happened.
#
# You can enable this as a default for your local repository by running
# `git config blame.ignoreRevsFile .git-blame-ignore-revs`
# Important: if you do this, then switch to a branch without this file,
# `git blame` will fail with an error.
#
# Run clang-format over the code
2a1095924b0be60f822bc0ff20d567e209a9db73
# Add trailing commas to prevent clang-format oddities
aebf3cd4915adc576cf055926caa621e098ec32b
# Fix some inconsistent whitespace.
60abf1575560cb8e2220ae48a67e7f74b5dc70dd

32
.gitignore vendored
View file

@ -1,3 +1,7 @@
*.o
*.pc
*.la
*.lo
*.swp
*~
*.sig
@ -6,7 +10,29 @@
*.patch
*.rej
*.trs
*.gcda
*.gcno
Makefile
Makefile.in
aclocal.m4
autom4te.cache/
config.guess
config.h
config.h.in
config.log
config.status
config.sub
configure
depcomp
install-sh
libtool
ltmain.sh
missing
stamp-h1
.libs/
.deps/
src/libinput-version.h
doc/libinput.doxygen
doc/html
tags
*.gnuplot
test/test-*
test/symbols-leak-test*
test-driver

File diff suppressed because it is too large Load diff

View file

@ -1,803 +0,0 @@
# vim: set expandtab shiftwidth=2 tabstop=8 textwidth=0 filetype=yaml:
{# You're looking at the template here, so you can ignore the below
warning. This is the right file to edit #}
########################################
# #
# THIS FILE IS GENERATED, DO NOT EDIT #
# #
########################################
# To change the gitlab CI, edit .gitlab-ci/ci.template and/or .gitlab-ci/config.yaml
# and run ci-fairy generate-template. For details, see
# https://freedesktop.pages.freedesktop.org/ci-templates/ci-fairy.html#templating-gitlab-ci-yml
# This is a bit complicated for two reasons:
# - we really want to run dnf/apt/... only once, updating on the test runner for
# each job takes forever. So we create a container image for each distribution
# tested, then run the tests on this container image.
#
# This is handled by the ci-templates, ensuring containers are only rebuilt
# when the TAG changes.
#
# - GitLab only allows one script: set per job but we have a bunch of commands
# we need to re-run for each build (meson && ninja && etc). YAML cannot merge
# arrays so we're screwed.
#
# So instead we use a default_build template and override everything with
# variables. The only two variables that matter:
# MESON_ARGS=-Denable-something=true
# NINJA_ARGS=dist ... to run 'ninja -C builddir dist'
# Note that you cannot use scripts: in any target if you expect default_build
# to work.
#
#
# All jobs must follow the naming scheme of
# <distribution>:<version>@activity:
# e.g. fedora:31@build-default
.templates_sha: &template_sha c6aeb16f86e32525fa630fb99c66c4f3e62fc3cb
include:
- project: 'freedesktop/ci-templates'
ref: *template_sha
file:
- '/templates/ci-fairy.yml'
{% for distro in distributions|sort(attribute="name") %}
# {{ distro.name.capitalize() }} container builder template
- '/templates/{{distro.name}}.yml'
{% endfor %}
workflow:
rules:
# do not duplicate pipelines on merge pipelines
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
when: never
# merge pipeline
- if: &is-merge-attempt $GITLAB_USER_LOGIN == "marge-bot" && $CI_PIPELINE_SOURCE == "merge_request_event"
variables:
FDO_RUNNER_JOB_PRIORITY_TAG_X86_64: priority:high
FDO_RUNNER_JOB_PRIORITY_TAG_X86_64_KVM: priority:high-kvm
FDO_RUNNER_JOB_PRIORITY_TAG_AARCH64: priority:high-aarch64
# post-merge pipeline
- if: &is-post-merge $GITLAB_USER_LOGIN == "marge-bot" && $CI_PIPELINE_SOURCE == "push"
variables:
FDO_RUNNER_JOB_PRIORITY_TAG_X86_64: priority:high
FDO_RUNNER_JOB_PRIORITY_TAG_X86_64_KVM: priority:high-kvm
FDO_RUNNER_JOB_PRIORITY_TAG_AARCH64: priority:high-aarch64
# Pre-merge pipeline
- if: &is-pre-merge $CI_PIPELINE_SOURCE == "merge_request_event"
# Push to a branch on a fork
- if: $CI_COMMIT_BRANCH
stages:
- sanity check # CI/commit checks
- prep # prep work like rebuilding the container images if there is a change
- build # for actually building and testing things in a container
- test-suite # for running the test suite in a VM
- test-suite-no-libwacom # for running the test suite in a VM (libwacom disabled)
- valgrind # for running the test suite under valgrind in a VM
- distro # distribs test
- deploy # trigger wayland's website generation
- container_clean # clean up unused container images (scheduled jobs only)
variables:
###############################################################################
# This is the list of packages required to build libinput with the default #
# configuration. #
# #
# Run dnf install/apt-get install/.. with the list of packages for your #
# distribution #
# #
# See the documentation here: #
# https://wayland.freedesktop.org/libinput/doc/latest/building.html #
###############################################################################
{% for distro in distributions %}
{{"%-17s" | format(distro.name.upper() + '_PACKAGES:')}} '{{ distro.packages|join(' ')}}'
{% endfor %}
############################ end of package lists #############################
# these tags should be updated each time the list of packages is updated
# changing these will force rebuilding the associated image
# Note: these tags have no meaning and are not tied to a particular
# libinput version
{% for distro in distributions %}
{{"%-13s"| format(distro.name.upper() + '_TAG:')}}'{{distro.tag}}'
{% endfor %}
FDO_UPSTREAM_REPO: libinput/libinput
MESON_BUILDDIR: "build dir"
NINJA_ARGS: ''
MESON_ARGS: ''
MESON_TEST_ARGS: '--no-suite=hardware'
# udev isn't available/working properly in the containers
UDEV_NOT_AVAILABLE: 1
GIT_DEPTH: 1
# Default priority for non-merge pipelines
FDO_RUNNER_JOB_PRIORITY_TAG_X86_64: "" # Empty tags are ignored by gitlab
FDO_RUNNER_JOB_PRIORITY_TAG_X86_64_KVM: kvm
FDO_RUNNER_JOB_PRIORITY_TAG_AARCH64: aarch64
.policy:
retry:
max: 2
when:
- runner_system_failure
- stuck_or_timeout_failure
# cancel run when a newer version is pushed to the branch
interruptible: true
dependencies: []
.policy-retry-on-failure:
retry:
max: 1
when:
- runner_system_failure
- stuck_or_timeout_failure
# cancel run when a newer version is pushed to the branch
interruptible: true
dependencies: []
.default_artifacts:
artifacts:
name: "meson-logs-$CI_JOB_NAME"
when: always
expire_in: 1 week
paths:
- $MESON_BUILDDIR/meson-logs
- $MESON_BUILDDIR/valgrind.*.log
reports:
junit: $MESON_BUILDDIR/*junit*.xml
.fdo-runner-tags:
tags:
- $FDO_RUNNER_JOB_PRIORITY_TAG_X86_64
#################################################################
# #
# sanity check stage #
# #
#################################################################
fail-if-fork-is-not-public:
extends:
- .fdo-runner-tags
stage: sanity check
script:
- |
if [ $CI_PROJECT_VISIBILITY != "public" ]; then
echo "*************************************************************************************"
echo "Project visibility must be set to 'public'"
echo "Change this in $CI_PROJECT_URL/edit under 'Visibility, project features, permissions'"
echo "*************************************************************************************"
exit 1
fi
except:
- main@libinput/libinput
# Re-generate the CI script and make sure it's the one currently checked in
# If this job fails, re-generate the gitlab-ci.yml script, see
# $SRCDIR/.gitlab-ci/generate-gitlab-ci.py
#
check-ci-script:
extends:
- .fdo.ci-fairy
- .fdo-runner-tags
stage: sanity check
script:
- ci-fairy generate-template --verify && exit 0 || true
- >
printf "%s\n" \
"Committed gitlab-ci.yml differs from generated gitlab-ci.yml. Please verify" \
"https://wayland.freedesktop.org/libinput/doc/latest/contributing.html"
- exit 1
#
# Verify that commit messages are as expected, etc.
#
check-commit:
extends:
- .fdo.ci-fairy
- .fdo-runner-tags
stage: sanity check
script:
- ci-fairy -vv check-commits --junit-xml=results.xml && exit 0 || true
- >
printf "%s\n" \
"Error checking commit format. Please verify" \
"https://wayland.freedesktop.org/libinput/doc/latest/contributing.html"
- exit 1
except:
- main@libinput/libinput
variables:
GIT_DEPTH: 100
artifacts:
reports:
junit: results.xml
#
# Check for trailing whitespaces
#
check-whitespace:
extends:
- .fdo.ci-fairy
- .fdo-runner-tags
stage: sanity check
script:
- .gitlab-ci/whitespace-check.py $(git ls-files)
#
# pre-commit hooks
#
pre-commit-hooks:
extends:
- .fdo.ci-fairy
- .fdo-runner-tags
stage: sanity check
script:
- python3 -m venv venv
- source venv/bin/activate
- pip3 install pre-commit
- pre-commit run --all-files
- git diff --exit-code || (echo "ERROR - Code style errors found, please fix" && false)
#################################################################
# #
# prep stage #
# #
#################################################################
{% for distro in distributions %}
{% for version in distro.versions %}
{{distro.name}}:{{version}}@container-prep:
extends:
{% if distro.qemu_based %}
- .fdo.qemu-build@{{distro.name}}
{% else %}
- .fdo.container-build@{{distro.name}}
{% endif %}
- .policy
- .fdo-runner-tags
{% if distro.qemu_based %}
tags:
- $FDO_RUNNER_JOB_PRIORITY_TAG_X86_64_KVM
{% endif %}
stage: prep
variables:
GIT_STRATEGY: none
FDO_DISTRIBUTION_VERSION: '{{version}}'
FDO_DISTRIBUTION_PACKAGES: ${{distro.name.upper()}}_PACKAGES
FDO_DISTRIBUTION_TAG: ${{distro.name.upper()}}_TAG
{% endfor %}
{% endfor %}
#################################################################
# #
# container clean stage #
# run during the clean stage #
# #
#################################################################
#
# This stage will look for the container images we currently have in
# the registry and will remove any that are not tagged with the provided
# $container_image:$tag
#
.container-clean:
extends:
- .policy
- .fdo.ci-fairy
- .fdo-runner-tags
stage: container_clean
script:
# Go to your Profile, Settings, Access Tokens
# Create a personal token with 'api' scope, copy the value.
# Go to CI/CD, Schedules, schedule a new monthly job (or edit the existing one)
# Define a variable of type File named AUTHFILE. Content is that token
# value.
- ci-fairy -v --authfile $AUTHFILE delete-image
--repository $FDO_DISTRIBUTION_NAME/$FDO_DISTRIBUTION_VERSION
--exclude-tag $FDO_DISTRIBUTION_TAG
allow_failure: true
only:
- schedules
{% for distro in distributions %}
{% for version in distro.versions %}
{{distro.name}}:{{version}}@container-clean:
extends:
- .policy
- .container-clean
variables:
GIT_STRATEGY: none
CURRENT_CONTAINER_IMAGE: $CI_REGISTRY_IMAGE/{{distro.name}}/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_TAG
FDO_DISTRIBUTION_VERSION: '{{version}}'
FDO_DISTRIBUTION_TAG: ${{distro.name.upper()}}_TAG
{% endfor %}
{% endfor %}
#################################################################
# #
# build stage #
# #
#################################################################
.build@template:
extends:
- .policy
- .default_artifacts
- .fdo-runner-tags
stage: build
script:
- .gitlab-ci/meson-build.sh
# Run meson and meson test in the container image through qemu
.build-in-vng@template:
extends:
- .policy
- .default_artifacts
tags:
- $FDO_RUNNER_JOB_PRIORITY_TAG_X86_64_KVM
variables:
MESON_BUILDDIR: build_dir
VNG_KERNEL: {{ vng.kernel }}
script:
# first build in the host container
- .gitlab-ci/meson-build.sh --skip-test
- mkdir -p $MESON_BUILDDIR
- curl -LO $VNG_KERNEL
- export -p > .vngenv
# runs the test suite only
- |
vng --run ./bzImage \
--user root \
--overlay-rwdir=$HOME \
--append HOME=$HOME \
--overlay-rwdir=$(pwd) \
--rwdir=$MESON_BUILDDIR \
--exec "source $PWD/.vngenv; rm $PWD/.vngenv; .gitlab-ci/meson-build.sh --skip-setup --skip-build --run-test"
#
# Fedora
#
.check_tainted: &check_tainted |
# make sure the kernel is not tainted
if [[ "$(ssh localhost -p 5555 cat /proc/sys/kernel/tainted)" -gt 0 ]];
then
echo tainted kernel ;
exit 1 ;
fi
# Run meson and meson test in the qemu image
.build-in-qemu@template:
extends:
- .policy
tags:
- $FDO_RUNNER_JOB_PRIORITY_TAG_X86_64_KVM
variables:
MESON_BUILDDIR: build_dir
script:
# start our vm, no args required
- /app/vmctl start || (echo "Error - Failed to start the VM." && exit 1)
- *check_tainted
- "scp -r $PWD vm:"
- echo "CI_JOB_ID=\"$CI_JOB_ID\"" > sshenv
- echo "CI_JOB_NAME=\"$CI_JOB_NAME\"" >> sshenv
- echo "MESON_ARGS=\"$MESON_ARGS\"" >> sshenv
- echo "MESON_BUILDDIR=\"$MESON_BUILDDIR\"" >> sshenv
- echo "MESON_TEST_ARGS=\"$MESON_TEST_ARGS\"" >> sshenv
- echo "NINJA_ARGS=\"$NINJA_ARGS\"" >> sshenv
- "scp sshenv vm:~/$CI_PROJECT_NAME/.meson_environment"
- /app/vmctl exec "cd $CI_PROJECT_NAME ; .gitlab-ci/meson-build.sh" && touch .success || true
# no matter the results of the tests, we want to fetch the logs
- scp -r vm:$CI_PROJECT_NAME/$MESON_BUILDDIR .
- *check_tainted
- /app/vmctl stop
- if [[ ! -e .success ]] ;
then
exit 1 ;
fi
artifacts:
name: "qemu-meson-logs-$CI_JOB_NAME"
when: always
expire_in: 1 week
paths:
- $MESON_BUILDDIR/meson-logs
- console.out
reports:
junit: $MESON_BUILDDIR/*junit*.xml
# Run in a test suite. Special variables:
# - SUITES: the meson test suites to run, or
# - SUITE_NAMES: all elements will be expanded to libinput-test-suite-$value
# Set one or the other, not both.
.test-suite-vm:
extends:
- .build-in-vng@template
stage: test-suite
variables:
# remove the global --no-suite=hardware
MESON_TEST_ARGS: ''
LITEST_JOBS: 4
before_script:
- if ! [[ -z $SUITE_NAMES ]]; then SUITES=$(echo $SUITE_NAMES | sed 's/\([^ ]*\)/libinput-test-suite-\1/g'); fi
- echo "Testing $SUITES"
- export MESON_TEST_ARGS="$MESON_TEST_ARGS $SUITES"
{# qemu tests are only done for the latest version of any distribution #}
{% for distro in distributions if distro.use_for_qemu_tests %}
{% set version = "{}".format(distro.versions|last()) %}
.{{distro.name}}:{{version}}@test-suite-vm:
extends:
- .fdo.distribution-image@{{distro.name}}
- .test-suite-vm
variables:
FDO_DISTRIBUTION_VERSION: {{version}}
FDO_DISTRIBUTION_TAG: ${{distro.name.upper()}}_TAG
needs:
- "{{distro.name}}:{{version}}@container-prep"
{% for suite in test_suites %}
vm-{{suite.name}}:
extends:
- .{{distro.name}}:{{version}}@test-suite-vm
variables:
SUITE_NAMES: '{{suite.suites|join(' ')}}'
vm-{{suite.name}}-no-libwacom:
extends:
- vm-{{suite.name}}
stage: test-suite-no-libwacom
variables:
MESON_ARGS: '-Dlibwacom=false'
{% endfor %}
{% for suite in test_suites %}
vm-valgrind-{{suite.name}}:
stage: valgrind
extends:
- vm-{{suite.name}}
- .policy-retry-on-failure
variables:
MESON_TEST_ARGS: '--setup=valgrind'
LITEST_JOBS: 0
retry:
max: 2
rules:
- if: $GITLAB_USER_LOGIN != "marge-bot"
{% endfor %}
{% endfor %}{# for if distro.use_for_qemu_tests #}
{% for distro in distributions if distro.use_for_custom_build_tests %}
{% set version = "{}".format(distro.versions|last()) %}
.{{distro.name}}-build@template:
extends:
- .fdo.distribution-image@{{distro.name}}
- .build@template
variables:
FDO_DISTRIBUTION_VERSION: '{{version}}'
FDO_DISTRIBUTION_TAG: ${{distro.name.upper()}}_TAG
needs:
- "{{distro.name}}:{{version}}@container-prep"
default-build-release@{{distro.name}}:{{version}}:
stage: distro
extends:
- .{{distro.name}}-build@template
variables:
MESON_ARGS: "-Dbuildtype=release"
CFLAGS: "-Werror"
clang-tidy@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
variables:
NINJA_ARGS: ''
MESON_TEST_ARGS: ''
CC: 'clang'
script:
- .gitlab-ci/meson-build.sh
- ninja -C "$MESON_BUILDDIR" clang-tidy
# Below jobs are build option combinations. We only
# run them on one image, they shouldn't fail on one distro
# when they succeed on another.
build-no-libwacom@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
variables:
MESON_ARGS: "-Dlibwacom=false"
build-no-libwacom-nodeps@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
variables:
MESON_ARGS: "-Dlibwacom=false"
before_script:
- dnf remove -y libwacom libwacom-devel
build-no-mtdev@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
variables:
MESON_ARGS: "-Dmtdev=false"
build-no-mtdev-nodeps@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
variables:
MESON_ARGS: "-Dmtdev=false"
before_script:
- dnf remove -y mtdev mtdev-devel
build-no-lua@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
variables:
MESON_ARGS: "-Dlua-plugins=disabled"
build-no-lua-nodeps@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
variables:
MESON_ARGS: "-Dlua-plugins=disabled"
before_script:
- dnf remove -y lua lua-devel
build-docs@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
variables:
MESON_ARGS: "-Ddocumentation=true"
build-no-docs-nodeps@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
variables:
MESON_ARGS: "-Ddocumentation=false"
before_script:
- dnf remove -y doxygen graphviz
build-no-debuggui@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
variables:
MESON_ARGS: "-Ddebug-gui=false"
build-no-debuggui-nodeps@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
variables:
MESON_ARGS: "-Ddebug-gui=false"
before_script:
- dnf remove -y gtk3-devel gtk4-devel
build-no-tests@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
variables:
MESON_ARGS: "-Dtests=false"
build-no-tests-nodeps@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
variables:
MESON_ARGS: "-Dtests=false"
before_script:
- dnf remove -y check-devel
valgrind@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
variables:
MESON_TEST_ARGS: '--suite=valgrind --no-suite=hardware --setup=valgrind'
# Python checks, only run on Fedora
usr-bin-env-python@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
script:
- |
if git grep -l '^#!/usr/bin/python'; then
echo "Use '/usr/bin/env python3' in the above files";
/bin/false
fi
# A job to check we're actually running all test suites in the CI
check-test-suites:
extends:
- .{{distro.name}}-build@template
script:
- meson setup builddir
- meson introspect builddir --test | jq -r '.[].name' | grep 'libinput-test-suite' | sort > meson-testsuites
- |
cat <<EOF > ci-testsuites ;
{% for suite in test_suites %}
{% for name in suite.suites %}
libinput-test-suite-{{name}}
{% endfor %}
{% endfor %}
EOF
- sort -o ci-testsuites ci-testsuites
- diff -u8 -w ci-testsuites meson-testsuites || (echo "Some test suites are not run in the CI" && false)
only:
changes:
- "meson.build"
- ".gitlab-ci.yml"
{% endfor %}
#
# coverity run
#
# This requires the COVERITY_SCAN_TOKEN. Log into scan.coverity.com and get
# the token from the respective project settings page.
# Schedule a pipeline and set a variable COVERITY_SCAN_TOKEN with the token value.
# https://gitlab.freedesktop.org/$CI_PROJECT_PATH/-/pipeline_schedules
# Email from coverity will be sent to the GITLAB_USER_EMAIL that scheduled the
# job.
#
# Coverity ratelimits submissions and the coverity tools download is about
# 700M, do not run this too often.
#
coverity:
extends:
- .fdo.distribution-image@debian
- .policy
- .fdo-runner-tags
stage: build
variables:
FDO_DISTRIBUTION_VERSION: 'stable'
FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
# so git-describe works, or should work
GIT_DEPTH: 200
only:
variables:
- $COVERITY_SCAN_TOKEN
script:
- curl https://scan.coverity.com/download/linux64
-o /tmp/cov-analysis-linux64.tgz
--form project=$CI_PROJECT_NAME
--form token=$COVERITY_SCAN_TOKEN
- tar xfz /tmp/cov-analysis-linux64.tgz
# coverity has special build options in meson, make sure we enable those
- meson coverity-build -Ddocumentation=false -Dcoverity=true
- cov-analysis-linux64-*/bin/cov-build --dir cov-int ninja -C coverity-build
- tar cfz cov-int.tar.gz cov-int
- curl https://scan.coverity.com/builds?project=$CI_PROJECT_NAME
--form token=$COVERITY_SCAN_TOKEN --form email=$GITLAB_USER_EMAIL
--form file=@cov-int.tar.gz --form version="$(git describe --tags)"
--form description="$(git describe --tags) / $CI_COMMIT_TITLE / $CI_COMMIT_REF_NAME:$CI_PIPELINE_ID"
artifacts:
name: "coverity-submit-data"
when: always
expire_in: 1 week
paths:
- cov-int.tar.gz
needs:
- "debian:stable@container-prep"
#################################################################
# #
# distro stage #
# #
#################################################################
{% for distro in distributions %}
{% if not distro.qemu_based %}
{% for version in distro.versions %}
{{distro.name}}:{{version}}@default-build:
stage: distro
extends:
- .build@template
- .fdo.distribution-image@{{distro.name}}
variables:
FDO_DISTRIBUTION_VERSION: '{{version}}'
FDO_DISTRIBUTION_TAG: ${{distro.name.upper()}}_TAG
{# Where we have extra_variables defined, add them to the list #}
{% if distro.build is defined and distro.build.extra_variables is defined %}
{% for var in distro.build.extra_variables %}
{{var}}
{% endfor %}
{% endif %}
needs:
- "{{distro.name}}:{{version}}@container-prep"
{% endfor %}
{% else %}
{% set version = "{}".format(distro.versions|last()) %}
{{distro.name}}:{{version}}@default-build:
stage: distro
extends:
- .build-in-qemu@template
- .fdo.distribution-image@{{distro.name}}
variables:
FDO_DISTRIBUTION_VERSION: '{{version}}'
FDO_DISTRIBUTION_TAG: ${{distro.name.upper()}}_TAG
{# Where we have extra_variables defined, add them to the list #}
{% if distro.build is defined and distro.build.extra_variables is defined %}
{% for var in distro.build.extra_variables %}
{{var}}
{% endfor %}
{% endif %}
needs:
- "{{distro.name}}:{{version}}@container-prep"
{% endif %}
{% endfor %}
#################################################################
# #
# deploy stage #
# #
#################################################################
{% for distro in distributions if distro.name == "fedora" %}
{% set version = "{}".format(distro.versions|last()) %}
build rpm:
extends:
- .fdo.distribution-image@fedora
- .policy
- .fdo-runner-tags
stage: deploy
variables:
FDO_DISTRIBUTION_VERSION: '{{version}}'
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
needs:
- "fedora:{{version}}@container-prep"
script:
- meson "$MESON_BUILDDIR"
- VERSION=$(meson introspect "$MESON_BUILDDIR" --projectinfo | jq -r .version)
- sed -e "s/@PIPELINEID@/${CI_PIPELINE_ID}/"
-e "s/@GITVERSION@/${CI_COMMIT_SHA}/"
-e "s/@VERSION@/${VERSION}/" .gitlab-ci/libinput.spec.in > libinput.spec
- git config --local user.name 'gitlab CI'
- git config --local user.email 'noreply@nowhere'
- git add libinput.spec && git commit -m 'Add libinput.spec for build testing' libinput.spec
- cd "$MESON_BUILDDIR"
- meson dist --no-test
- rpmbuild -ta meson-dist/libinput*.tar.xz
{% endfor %}
wayland-web:
stage: deploy
trigger: wayland/wayland.freedesktop.org
variables:
MESON_ARGS: '-Ddocumentation=true -Ddebug-gui=false -Dlibwacom=false -Dtests=false'
MESON_BUILDDIR: 'builddir'
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: never
- if: '$CI_COMMIT_BRANCH == "main" && $GITLAB_USER_LOGIN != "marge-bot" && $CI_PROJECT_PATH == $FDO_UPSTREAM_REPO'
when: on_success
- when: never

View file

@ -1,217 +0,0 @@
# This file contains the configuration for the gitlab ci.
# See the .gitlab-ci/generate-gitlab-ci.py file for more info
#
# We're happy to rebuild all containers when one changes.
.default_tag: &default_tag '2026-01-09.0'
distributions:
- name: fedora
tag: *default_tag
versions:
- '42'
- '43'
use_for_custom_build_tests: true
use_for_qemu_tests: true
packages:
- git-core
- gcc
- gcc-c++
- pkgconf-pkg-config
- meson
- check-devel
- libudev-devel
- libevdev-devel
- doxygen
- graphviz
- python3-sphinx
- python3-recommonmark
- python3-sphinx_rtd_theme
- python3-pytest-xdist
- libwacom-devel
- cairo-devel
- gtk4-devel
- glib2-devel
- mtdev-devel
- diffutils
- wayland-protocols-devel
- black # for the Python black job, optional
- clang # for the clang-tidy build, optional
- clang-tools-extra # for clang-tidy, optional
- jq # for the test suite check job, optional
- rpmdevtools # for the rpm build job, optional
- valgrind # for the valgrind run, optional
# below packages are for the qemu runs, so optional
- systemd-udev # for the qemu run
- qemu-img
- qemu-system-x86-core
- qemu-system-aarch64-core
- jq
- python3-click
- python3-rich
- virtme-ng
- lua-devel
- name: debian
tag: *default_tag
versions:
- 'stable'
packages:
- git
- gcc
- g++
- pkg-config
- meson
- check
- libudev-dev
- libevdev-dev
- doxygen
- graphviz
- python3-sphinx
- python3-recommonmark
- python3-sphinx-rtd-theme
- python3-pytest-xdist
- libwacom-dev
- libcairo2-dev
- libgtk-3-dev
- libglib2.0-dev
- libmtdev-dev
- curl # for the coverity job
- lua5.4-dev
- name: ubuntu
tag: *default_tag
versions:
- '25.10'
packages:
- git
- gcc
- g++
- pkg-config
- meson
- check
- libudev-dev
- libevdev-dev
- doxygen
- graphviz
- python3-sphinx
- python3-recommonmark
- python3-sphinx-rtd-theme
- python3-pytest-xdist
- libwacom-dev
- libcairo2-dev
- libgtk-3-dev
- libglib2.0-dev
- libmtdev-dev
- lua5.4-dev
- name: arch
tag: *default_tag
versions:
- 'rolling'
packages:
- git
- gcc
- pkgconfig
- meson
- check
- libsystemd
- libevdev
- python-pytest-xdist
- libwacom
- gtk4
- mtdev
- diffutils
- lua
build:
extra_variables:
- "MESON_ARGS: '-Ddocumentation=false'" # python-recommonmark is no longer in the repos
- name: alpine
tag: *default_tag
versions:
- 'latest'
packages:
- git
- gcc build-base
- pkgconfig
- meson
- check-dev
- eudev-dev
- libevdev-dev
- libwacom-dev
- cairo-dev
- gtk4.0-dev
- mtdev-dev
- bash
- lua5.4-dev
build:
extra_variables:
- "MESON_ARGS: '-Ddocumentation=false' # alpine does not have python-recommonmark"
# We don't run the tests on alpine. The litest-selftest fails
# for any tcase_add_exit_test/tcase_add_test_raise_signal
# but someone more invested in musl will have to figure that out.
- "MESON_TEST_ARGS: '' # litest-selftest fails on musl"
test_suites:
- name: touchpad
suites:
- touchpad
- name: touchpad_palm
suites:
- touchpad_palm
- name: touchpad_dwt
suites:
- touchpad_dwt
- name: tap
suites:
- touchpad_tap
- name: tap-drag
suites:
- touchpad_tap_drag
- name: tap-palm
suites:
- touchpad_tap_palm
- name: touchpad-buttons
suites:
- touchpad_buttons
- name: tablet
suites:
- tablet
- name: tablet_left_handed
suites:
- tablet_left_handed
- name: tablet_proximity_tip
suites:
- tablet_proximity
- tablet_tip
- name: tablet_eraser
suites:
- tablet_eraser
- name: gestures
suites:
- gestures
- name: backends
suites:
- path
- udev
- name: misc
suites:
- log
- misc
- quirks
- device
- name: other devices
suites:
- keyboard
- pad
- switch
- trackball
- trackpoint
- totem
- touch
- name: pointer
suites:
- pointer
- name: lua
suites:
- lua
vng:
kernel: https://gitlab.freedesktop.org/api/v4/projects/libevdev%2Fhid-tools/packages/generic/kernel-x86_64/v6.14/bzImage

View file

@ -1,149 +0,0 @@
# This specfile should not be used outside the CI
# Its main purpose is to sound alarm if files disappear or are added that
# weren't intended.
%global udevdir %(pkg-config --variable=udevdir udev)
%global pipelineid @PIPELINEID@
%global gitversion @GITVERSION@
Name: libinput
Version: @VERSION@
Release: %{pipelineid}git%{gitversion}%{?dist}
Summary: Input device library
License: MIT
URL: http://www.freedesktop.org/wiki/Software/libinput/
Source0: %{name}-%{version}.tar.xz
# No BuildRequires, we rely on the container setup to have
# all the requires installed
%description
libinput is a library that handles input devices for display servers and other
applications that need to directly deal with input devices.
It provides device detection, device handling, input device event processing
and abstraction so minimize the amount of custom input code the user of
libinput need to provide the common set of functionality that users expect.
%package devel
Summary: Development files for %{name}
Requires: %{name}%{?_isa} = %{version}-%{release}
%description devel
The %{name}-devel package contains libraries and header files for
developing applications that use %{name}.
%package utils
Summary: Utilities and tools for debugging %{name}
Requires: %{name}%{?_isa} = %{version}-%{release}
Requires: python3-pyudev python3-libevdev
%description utils
The %{name}-utils package contains tools to debug hardware and analyze
%{name}.
%package test
Summary: libinput integration test suite
Requires: %{name}%{?_isa} = %{version}-%{release}
%description test
The %{name}-test package contains the libinput test suite. It is not
intended to be run by users.
%prep
%autosetup -S git -n %{name}-%{version}
%build
%meson -Dtests=true \
-Dinstall-tests=true \
-Dudev-dir=%{udevdir}
%meson_build
%install
%meson_install
%post
%{?ldconfig}
%ldconfig_postun
%files
%doc COPYING
%dir %{_sysconfdir}/libinput
%{_libdir}/libinput.so.*
%{udevdir}/libinput-device-group
%{udevdir}/libinput-fuzz-extract
%{udevdir}/libinput-fuzz-to-zero
%{udevdir}/rules.d/80-libinput-device-groups.rules
%{udevdir}/rules.d/90-libinput-fuzz-override.rules
%{_bindir}/libinput
%dir %{_libexecdir}/libinput/
%{_libexecdir}/libinput/libinput-debug-events
%{_libexecdir}/libinput/libinput-list-devices
%{_mandir}/man1/libinput.1*
%{_datadir}/libinput/*.quirks
%dir %{_datadir}/zsh
%dir %{_datadir}/zsh/site-functions
%{_datadir}/zsh/site-functions/*
%{_mandir}/man1/libinput-list-devices.1*
%{_mandir}/man1/libinput-debug-events.1*
%files devel
%{_includedir}/libinput.h
%{_libdir}/libinput.so
%{_libdir}/pkgconfig/libinput.pc
%files utils
%{_libexecdir}/libinput/libinput-debug-gui
%{_libexecdir}/libinput/libinput-debug-tablet
%{_libexecdir}/libinput/libinput-debug-tablet-pad
%{_libexecdir}/libinput/libinput-list-kernel-devices
%{_libexecdir}/libinput/libinput-measure
%{_libexecdir}/libinput/libinput-measure-fuzz
%{_libexecdir}/libinput/libinput-measure-touchpad-tap
%{_libexecdir}/libinput/libinput-measure-touchpad-pressure
%{_libexecdir}/libinput/libinput-measure-touch-size
%{_libexecdir}/libinput/libinput-measure-touchpad-size
%{_libexecdir}/libinput/libinput-quirks
%{_libexecdir}/libinput/libinput-record
%{_libexecdir}/libinput/libinput-replay
%{_libexecdir}/libinput/libinput-analyze
%{_libexecdir}/libinput/libinput-analyze-buttons
%{_libexecdir}/libinput/libinput-analyze-per-slot-delta
%{_libexecdir}/libinput/libinput-analyze-recording
%{_libexecdir}/libinput/libinput-analyze-touch-down-state
%{_mandir}/man1/libinput-debug-gui.1*
%{_mandir}/man1/libinput-debug-tablet.1*
%{_mandir}/man1/libinput-debug-tablet-pad.1*
%{_mandir}/man1/libinput-list-kernel-devices.1*
%{_mandir}/man1/libinput-measure.1*
%{_mandir}/man1/libinput-measure-fuzz.1*
%{_mandir}/man1/libinput-measure-touchpad-tap.1*
%{_mandir}/man1/libinput-measure-touch-size.1*
%{_mandir}/man1/libinput-measure-touchpad-size.1*
%{_mandir}/man1/libinput-measure-touchpad-pressure.1*
%{_mandir}/man1/libinput-quirks.1*
%{_mandir}/man1/libinput-quirks-list.1*
%{_mandir}/man1/libinput-quirks-validate.1*
%{_mandir}/man1/libinput-record.1*
%{_mandir}/man1/libinput-replay.1*
%{_mandir}/man1/libinput-analyze.1*
%{_mandir}/man1/libinput-analyze-buttons.1*
%{_mandir}/man1/libinput-analyze-per-slot-delta.1*
%{_mandir}/man1/libinput-analyze-recording.1*
%{_mandir}/man1/libinput-analyze-touch-down-state.1*
%files test
%{_libexecdir}/libinput/libinput-test
%{_libexecdir}/libinput/libinput-test-suite
%{_libexecdir}/libinput/libinput-test-utils
%{_mandir}/man1/libinput-test.1*
%{_mandir}/man1/libinput-test-suite.1*
%changelog
* Wed Jul 15 2020 Peter Hutterer <peter.hutterer@redhat.com>
- Add basic spec file for package build testing

View file

@ -1,88 +0,0 @@
#!/usr/bin/env bash
#
# This script is sourced from here:
# https://gitlab.freedesktop.org/whot/meson-helper
#
# SPDX-License-Identifier: MIT
set -x
if [[ -f .meson_environment ]]; then
. .meson_environment
fi
# If test args are set, we assume we want to run the tests
MESON_RUN_TEST="$MESON_TEST_ARGS"
while [[ $# -gt 0 ]]; do
case $1 in
--skip-setup)
shift
MESON_SKIP_SETUP="1"
;;
--skip-build)
shift
MESON_SKIP_BUILD="1"
;;
--skip-test)
shift
MESON_RUN_TEST=""
;;
--run-test)
shift
MESON_RUN_TEST="1"
;;
*)
echo "Unknow commandline argument $1"
exit 1
;;
esac
done
if [[ -z "$MESON_BUILDDIR" ]]; then
echo "\$MESON_BUILDDIR undefined."
exit 1
fi
# emulate a few gitlab variables to make it easier to
# run and debug locally.
if [[ -z "$CI_JOB_ID" ]] || [[ -z "$CI_JOB_NAME" ]]; then
echo "Missing \$CI_JOB_ID or \$CI_JOB_NAME".
CI_PROJECT_NAME=$(basename "$PWD")
CI_JOB_ID=$(date +%s)
CI_JOB_NAME="$CI_PROJECT_NAME-job-local"
echo "Simulating gitlab environment: "
echo " CI_JOB_ID=$CI_JOB_ID"
echo " CI_JOB_NAME=$CI_JOB_NAME"
fi
if [[ -n "$FDO_CI_CONCURRENT" ]]; then
jobcount="-j$FDO_CI_CONCURRENT"
export MESON_TESTTHREADS="$FDO_CI_CONCURRENT"
fi
echo "*************************************************"
echo "builddir: $MESON_BUILDDIR"
echo "meson args: $MESON_ARGS"
echo "ninja args: $NINJA_ARGS"
echo "meson test args: $MESON_TEST_ARGS"
echo "job count: ${jobcount-0}"
echo "*************************************************"
set -e
if [[ -z "$MESON_SKIP_SETUP" ]]; then
rm -rf "$MESON_BUILDDIR"
meson setup "$MESON_BUILDDIR" $MESON_ARGS
fi
meson configure "$MESON_BUILDDIR"
if [[ -z "$MESON_SKIP_BUILD" ]]; then
if [[ -n "$NINJA_ARGS" ]]; then
ninja_args="--ninja-args $NINJA_ARGS"
fi
meson compile -v -C "$MESON_BUILDDIR" $jobcount $ninja_args
fi
if [[ -n "$MESON_RUN_TEST" ]]; then
meson test -C "$MESON_BUILDDIR" $MESON_TEST_ARGS --print-errorlogs
fi

View file

@ -1,2 +0,0 @@
#!/bin/sh
scan-build -v --status-bugs -plist-html "$@"

View file

@ -1,119 +0,0 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
from pathlib import Path
from dataclasses import dataclass
import argparse
import itertools
import os
import sys
@dataclass
class WhitespaceError:
message: str
lineno: int
nlines: int = 1
column: None | int = None
ncolumns: int = 1
def test_duplicate_empty_lines(lines: list[str]) -> list[WhitespaceError]:
errors = []
for idx, (l1, l2) in enumerate(itertools.pairwise(lines)):
if not l1 and not l2:
errors.append(WhitespaceError("Duplicated empty lines", idx, nlines=2))
return errors
def test_tab_after_space(lines: list[str]) -> list[WhitespaceError]:
errors = []
for idx, l in enumerate(lines):
index = l.find(" \t")
if index > -1:
errors.append(
WhitespaceError(
"Tab after space", idx, nlines=index, column=index, ncolumns=2
)
)
return errors
def test_trailing_whitespace(lines: list[str]) -> list[WhitespaceError]:
errors = []
for idx, l in enumerate(lines):
if l.rstrip() != l:
errors.append(WhitespaceError("Trailing whitespace", idx))
return errors
def test_empty_line_between_braces(lines: list[str]) -> list[WhitespaceError]:
errors = []
for idx in range(len(lines) - 3):
l1 = lines[idx]
l2 = lines[idx + 1]
l3 = lines[idx + 2]
if l1.strip() == "}" and l3.strip() == "}" and l2.strip() == "":
errors.append(WhitespaceError("Empty line between closing braces", idx + 1))
return errors
def main():
parser = argparse.ArgumentParser(description="Whitespace checker script")
parser.add_argument(
"files",
metavar="FILES",
type=Path,
nargs="+",
help="The files to check",
)
args = parser.parse_args()
have_errors: bool = False
if os.isatty(sys.stderr.fileno()):
red = "\x1b[0;31m"
reset = "\x1b[0m"
else:
red = ""
reset = ""
for file in args.files:
lines = [l.rstrip("\n") for l in file.open().readlines()]
errors = []
errors.extend(test_tab_after_space(lines))
errors.extend(test_trailing_whitespace(lines))
if any(file.name.endswith(suffix) for suffix in [".c", ".h"]):
if not file.parts[0] == "include":
errors.extend(test_duplicate_empty_lines(lines))
errors.extend(test_empty_line_between_braces(lines))
for e in errors:
print(f"{red}ERROR: {e.message} in {file}:{reset}", file=sys.stderr)
print(f"{'-' * 72}", file=sys.stderr)
lineno = max(0, e.lineno - 5)
for idx, l in enumerate(lines[lineno : lineno + 10]):
if e.lineno <= lineno + idx < e.lineno + e.nlines:
prefix = "->"
hl = red
nohl = reset
else:
prefix = " "
hl = ""
nohl = ""
print(f"{hl}{lineno + idx:3d}: {prefix} {l.rstrip()}{nohl}")
print(f"{'-' * 72}", file=sys.stderr)
if errors:
have_errors = True
if have_errors:
sys.exit(1)
if __name__ == "__main__":
main()

View file

@ -1,32 +0,0 @@
<!--
Before your file a feature request, please read
https://wayland.freedesktop.org/libinput/doc/latest/what-is-libinput.html
The amount of developer time libinput has available is very small.
Requesting a feature is no guarantee that it will get implemented. Someone
(you!) needs to step up to do the work.
-->
## Summary
<!-- Summarize the requested feature in a few sentences. -->
## Feature details
<!-- A step-by-step list of what the feature should achieve (where applicable) -->
## Affected Hardware
<!-- Which hardware types would be affected by this -->
## Implementation in Other Systems
<!-- Does this feature already exist elsewhere? How does it work there? Try
to provide as many details as possible -->
/label ~enhancement ~"needs triage"

View file

@ -1,35 +0,0 @@
## Summary
<!--
Summarize the bug encountered concisely. See
https://wayland.freedesktop.org/libinput/doc/latest/reporting-bugs.html for
detailed instructions to report bugs
-->
## Steps to reproduce
<!-- How to reproduce the issue on a developer machine - this is very important -->
## Required information
<!-- Note: if your libinput version is older than the current stable version,
please reproduce with a current version instead -->
- libinput version:
- hardware information:
- `libinput record` output: do not paste, **attach** the file
- `libinput debug-events --verbose` output: do not paste, **attach the file**
<!--
Paste any other relevant logs - please use code blocks (```) to format
console output, logs, and code as it's very hard to read otherwise.)
Do not paste logs longer than 10 lines, **attach** those instead.
If your libinput record is longer than 5-10s, we will not be able to process
it.
-->
/label ~"bug" ~"needs triage"

View file

@ -1,31 +0,0 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- id: no-commit-to-branch
args: ['--branch', 'main']
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.12.2
hooks:
- id: ruff-check
args: ['--ignore=E741,E501', '--extend-exclude=subprojects', '.']
- id: ruff-format
args: ['--check', '--diff']
- repo: https://gitlab.freedesktop.org/freedesktop/ci-templates.git
rev: e195d80f35b45cc73668be3767b923fd76c70ed5
hooks:
- id: check-commits
- id: generate-template
- repo: local
hooks:
- id: run-sed-script
name: Check for whitespace errors
entry: ./.gitlab-ci/whitespace-check.py
language: system
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v20.1.6
hooks:
- id: clang-format
types_or: [c]

View file

@ -1,244 +0,0 @@
# This is a set of bugbot commands for issues and merge requests - setting any of the
# bugbot::foo labels will trigger gitlab-triage to run with this ruleset (well, the
# one we have on the main branch at the time)
#
# Note that for adding labels, the label must first created in the project.
# Re-used in issues and mrs
.close_needinfo: &close_needinfo
name: "Close stale needinfo bugs"
conditions:
labels:
- "bugbot::needinfo-timeout"
actions:
remove_labels:
- "bugbot::needinfo-timeout"
comment: |
I'm closing this bug because some information we requested a while ago was never supplied and
we're not able to continue without this information.
Please feel free to re-open.
status: "close"
.remind_needinfo: &remind_needinfo
name: "Remind users of needinfo bugs"
conditions:
labels:
- "bugbot::needinfo-reminder"
actions:
labels:
- "waiting on reporter"
remove_labels:
- "bugbot::needinfo-reminder"
comment: |
Hi. This is a friendly reminder that the maintainers are waiting on some information by
you (or maybe someone cc'd on this bug). If the information is not provided we may not
be able to proceed with this issue or merge request. Please check the recent comments, thanks.
.help_needed: &help_needed
name: "Remind users help is needed"
conditions:
labels:
- "bugbot::help-needed"
actions:
labels:
- "help needed"
remove_labels:
- "bugbot::help-needed"
comment: |
Hi. This issue or merge request needs help. This simply means that for
the foreseeable future, the maintainers will not have time to work on
this.
If this is a request for a new feature, then the feature is unlikely to
be implemented unless you or another contributor files a merge request.
If a merge request already exists maybe it needs finishing which often
involves adding documentation or tests.
If this is an issue affecting a specific device then it is unlikely to be
fixed. This may be because it requires specific hardware to reproduce or
it may be that the use case is niche enough that the maintainers do not
have time to implement it.
In short, to resolve this issue or get this merge request into libinput
help is needed.
.libinput_record: &libinput_record
name: "Request libinput record output"
conditions:
labels:
- "bugbot::libinput-record"
actions:
remove_labels:
- "bugbot::libinput-record"
comment: |
Looks like we may need some extra information. Please **attach** (do not paste) the full output
of `libinput record` and `libinput debug-events --verbose` (if you haven't yet).
The [documentation](https://wayland.freedesktop.org/libinput/doc/latest/tools.html#libinput-record-and-libinput-replay)
has some information on what we're looking for to be able to triage bugs.
.hid_recorder: &hid_recorder
name: "Request hid-recorder output"
conditions:
labels:
- "bugbot::hid-recorder"
actions:
remove_labels:
- "bugbot::hid-recorder"
comment: |
Looks like we may need some extra information that isn't yet available in this issue.
Please **attach** (do not paste) the output of [`hid-recorder`](https://github.com/hidutils/hid-recorder/)
for this device (run `sudo hid-recorder` without argument and it will let you pick the device).
This should show the data the kernel receives from the device and may provide a hint on what's going on here.
.udev_hid_bpf: &udev_hid_bpf
name: "Punt to udev-hid-bpf"
conditions:
labels:
- "bugbot::udev-hid-bpf"
actions:
remove_labels:
- "bugbot::udev-hid-bpf"
comment: |
This issue looks like it could or should be fixed with [udev-hid-bpf](https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/).
udev-hid-bpf is a collection of BPF programs that modify the HID Report Descriptor and/or HID Reports from the device,
making it possible to change the properties of a device and/or the events to make them compatible with the
expectations the kernel and userspace has of such devices.
Please see the [udev-hid-bpf documentation](https://libevdev.pages.freedesktop.org/udev-hid-bpf/) for details
and/or in particular the [udev-hid-bpf tutorial](https://libevdev.pages.freedesktop.org/udev-hid-bpf/tutorial.html)
if you need to enable a new device.
status: "close"
resource_rules:
issues:
rules:
- name: "Close kernel bugs"
conditions:
labels:
- "bugbot::kernel"
actions:
labels:
- "kernel"
remove_labels:
- "bugbot::kernel"
comment: |
This bug looks like a kernel issue and it cannot be fixed
in libinput directly. I'm closing this bug but do feel free
to continue discussing the issue here.
Kernel bugs are usually best sent to the [`linux-input` list](https://lore.kernel.org/linux-input/).
status: "close"
- name: "Expect a merge request"
conditions:
labels:
- "bugbot::expect-mr"
actions:
remove_labels:
- "bugbot::expect-mr"
comment: |
I'm closing this bug in anticipation of a merge request that fixes this issue.
If you are a new contributor, please see
[the freedesktop.org wiki](https://gitlab.freedesktop.org/freedesktop/freedesktop/-/wikis/home)
on how to get permissions to fork a project and file a merge request.
The [libinput documentation](https://wayland.freedesktop.org/libinput/doc/latest/contributing.html)
also has more details on how to get started.
status: "close"
- name: "Point to 60-evdev.hwdb"
conditions:
labels:
- "bugbot::evdev-hwdb"
actions:
remove_labels:
- "bugbot::evdev-hwdb"
comment: |
Looks like this issue may be solved with a device-specific entry in systemd's hwdb.
You should have a /usr/lib/udev/hwdb.d/60-evdev.hwdb file which includes those quirks. Please see
the top of the file for instructions and follow those. Once the quirk is confirmed working
this issue (or parts thereof) should be fixed and you can submit a pull request to the
[systemd](https://github.com/systemd/systemd/) repository to get that quirk included.
Please link to the systemd issue here, thanks.
I'm closing this issue now, if the hwdb entry does not fix this issue here, please re-open.
status: "close"
- name: "Close bug for reopening"
conditions:
labels:
- "bugbot::close"
actions:
remove_labels:
- "bugbot::close"
comment: |
I'm temporarily closing this bug. The bug may not be fixed yet (see any comments above)
and we **want you to reopen it when/if it becomes actionable again**.
This process may feel unfamiliar but unfortunately closing/re-opening is the only action
all GitLab users are permitted to do. So we close it, you re-open it when whatever
above has been addressed and then we know we need to look at it again.
This issue may be closed more than once in a similar fashion but I only leave this
comment once since now you understand how it works. :smile:
For a detailed explanation on the how and why of this process please see
the [Closed Issues wiki page](https://gitlab.freedesktop.org/libinput/libinput/-/wikis/Closed-Issues).
status: "close"
- name: "Re-close bug for reopening"
conditions:
labels:
- "bugbot::re-close"
actions:
remove_labels:
- "bugbot::re-close"
comment: |
I'm temporarily closing this bug again. This is not a final close, see my comments above for the open/close process.
status: "close"
- *udev_hid_bpf
- *libinput_record
- *hid_recorder
- *close_needinfo
- *remind_needinfo
- *help_needed
merge_requests:
rules:
- name: "Remind contributor of commit rules"
conditions:
labels:
- "bugbot::commit-rules"
actions:
remove_labels:
- "bugbot::commit-rules"
comment: |
Hi. Looks like the pipeline failed because one or more of the commits in this MR do not meet our requirements.
Most commonly this the format of the commit message itself. The "Test summary" above has the details.
Please see [our docs for commit messages](https://wayland.freedesktop.org/libinput/doc/latest/contributing.html#commit-messages)
and [our docs for submitting code](https://wayland.freedesktop.org/libinput/doc/latest/contributing.html#submitting-code)
that explain how to amend and force-push to this repo.
- name: "Remind contributor that info needs to be in commit messages"
conditions:
labels:
- "bugbot::info-in-commit-message"
actions:
remove_labels:
- "bugbot::info-in-commit-message"
comment: |
Hi. Thanks for the merge request. I'm here to request that you add
some documentation about this merge request to the
**commit message** (or messages). You may have already written some
in the merge request description and in many cases it's fine to
copy/paste that into the commit message(s).
The reason is simple: once merged, no-one really looks at this this
page here anymore. The git log on the other hand is what developers
will use to understand the code so the information must be quickly
accessible via git.
Please see [our docs for submitting code](https://wayland.freedesktop.org/libinput/doc/latest/contributing.html#submitting-code)
that explain how to amend and force-push to this repo.
- *udev_hid_bpf
- *libinput_record
- *hid_recorder
- *close_needinfo
- *remind_needinfo
- *help_needed

116
CODING_STYLE Normal file
View file

@ -0,0 +1,116 @@
- Indentation in tabs, 8 characters wide, spaces after the tabs where
vertical alignment is required (see below)
- Max line width 80ch, do not break up printed strings though
- Break up long lines at logical groupings, one line for each logical group
int a = somelongname() +
someotherlongname();
if (a < 0 &&
(b > 20 & d < 10) &&
d != 0.0)
somelongfunctioncall(arg1,
arg2,
arg3);
- Function declarations: return type on separate line, {} on separate line,
arguments broken up as above.
static inline int
foobar(int a, int b)
{
}
void
somenamethatiswaytoolong(int a,
int b,
int c)
{
}
- /* comments only */, no // comments
- variable_name, not VariableName or variableName. same for functions.
- no typedefs of structs, enums, unions
- if it generates a compiler warning, it needs to be fixed
- if it generates a static checker warning, it needs to be fixed or
commented
- declare variables at the top, try to keep them as local as possible.
Exception: if the same variable is re-used in multiple blocks, declare it
at the top.
int a;
int c;
if (foo) {
int b;
c = get_value();
usevalue(c);
}
if (bar) {
c = get_value();
useit(c);
}
- do not mix function invocations and variable definitions.
wrong:
{
int a = foo();
int b = 7;
}
right:
{
int a;
int b = 7;
a = foo();
}
There are exceptions here, e.g. tp_libinput_context(),
litest_current_device()
- if/else: { on the same line, no curly braces if both blocks are a single
statement. If either if or else block are multiple statements, both must
have curly braces.
if (foo) {
blah();
bar();
} else {
a = 10;
}
- public functions MUST be doxygen-commented, use doxygen's @foo rather than
\foo notation
- include "config.h" comes first, followed by system headers, followed by
external library headers, followed by internal headers.
sort alphabetically where it makes sense (specifically system headers)
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <libevdev/libevdev.h>
#include "libinput-private.h"
- goto jumps only to the end of the function, and only for good reasons
(usually cleanup). goto never jumps backwards
- Use stdbool.h's bool for booleans within the library (instead of 'int').
Exception: the public API uses int, not bool.

View file

@ -1,244 +0,0 @@
# Coding style
- Indentation in tabs, 8 characters wide, spaces after the tabs where
vertical alignment is required (see below)
**Note: this file uses spaces due to markdown rendering issues for tabs.
Code must be implemented using tabs.**
- Max line width 80ch, do not break up printed strings though
- Break up long lines at logical groupings, one line for each logical group
```c
int a = somelongname() +
someotherlongname();
if (a < 0 &&
(b > 20 & d < 10) &&
d != 0.0)
somelongfunctioncall(arg1,
arg2,
arg3);
```
- Function declarations: return type on separate line, {} on separate line,
arguments broken up as above.
```c
static inline int
foobar(int a, int b)
{
}
void
somenamethatiswaytoolong(int a,
int b,
int c)
{
}
```
- `/* comments only */`, no `// comments`
- `variable_name`, not `VariableName` or `variableName`. same for functions.
- no typedefs of structs, enums, unions
- if it generates a compiler warning, it needs to be fixed
- if it generates a static checker warning, it needs to be fixed or
commented
- declare variables when they are used first and try to keep them as local as possible.
Exception: basic loop variables, e.g. for (int i = 0; ...) should always be
declared inside the loop even where multiple loops exist
```c
int a;
if (foo) {
int b = 10;
a = get_value();
usevalue(a, b);
}
if (bar) {
a = get_value();
useit(a);
}
int c = a * 100;
useit(c);
```
- avoid uninitialized variables where possible, declare them late instead.
Note that most of libinput predates this style, try to stick with the code
around you if in doubt.
wrong:
```c
int *a;
int b = 7;
... some code ...
a = zalloc(32);
```
right:
```c
int b = 7;
... some code ...
int *a = zalloc(32);
```
- avoid calling non-obvious functions inside declaration blocks for multiple
variables.
bad:
```c
{
int a = 7;
int b = some_complicated_function();
int *c = zalloc(32);
}
```
better:
```c
{
int a = 7;
int *c = zalloc(32);
int b = some_complicated_function();
}
```
There is a bit of gut-feeling involved with this, but the goal is to make
the variable values immediately recognizable.
- Where statements are near-identical and repeated, try to keep them
identical:
bad:
```c
int a = get_some_value(x++);
do_something(a);
a = get_some_value(x++);
do_something(a);
a = get_some_value(x++);
do_something(a);
```
better:
```c
int a;
a = = get_some_value(x++);
do_something(a);
a = get_some_value(x++);
do_something(a);
a = get_some_value(x++);
do_something(a);
```
- if/else: { on the same line, no curly braces if both blocks are a single
statement. If either if or else block are multiple statements, both must
have curly braces.
```c
if (foo) {
blah();
bar();
} else {
a = 10;
}
```
- public functions MUST be doxygen-commented, use doxygen's `@foo` rather than
`\foo` notation
- `#include "config.h"` comes first, followed by system headers, followed by
external library headers, followed by internal headers.
sort alphabetically where it makes sense (specifically system headers)
```c
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <libevdev/libevdev.h>
#include "libinput-private.h"
```
- goto jumps only to the end of the function, and only for good reasons
(usually cleanup). goto never jumps backwards
- Use stdbool.h's bool for booleans within the library (instead of `int`).
Exception: the public API uses int, not bool.
# Git commit message requirements
Our CI will check the commit messages for a few requirements. Below is the
list of what we expect from a git commit.
## Commit message content
A [good commit message](http://who-t.blogspot.com/2009/12/on-commit-messages.html) needs to
answer three questions:
- Why is it necessary? It may fix a bug, it may add a feature, it may
improve performance, reliabilty, stability, or just be a change for the
sake of correctness.
- How does it address the issue? For short obvious patches this part can be
omitted, but it should be a high level description of what the approach
was.
- What effects does the patch have? (In addition to the obvious ones, this
may include benchmarks, side effects, etc.)
These three questions establish the context for the actual code changes, put
reviewers and others into the frame of mind to look at the diff and check if
the approach chosen was correct. A good commit message also helps
maintainers to decide if a given patch is suitable for stable branches or
inclusion in a distribution.
## Commit message format
The canonical git commit message format is:
```
one line as the subject line with a high-level note
full explanation of the patch follows after an empty line. This explanation
can be multiple paragraphs and is largely free-form. Markdown is not
supported.
You can include extra data where required like:
- benchmark one says 10s
- benchmark two says 12s
```
The subject line is the first thing everyone sees about this commit, so make
sure it's on point.
## Commit message technical requirements
- The commit message should use present tense (not past tense). Do write
"change foo to bar", not "changed foo to bar".
- The text width of the commit should be 78 chars or less, especially the
subject line.
- The author must be the name you usually identify as and email address. We do
not accept the default `@users.noreply` gitlab addresses.
```
git config --global user.name Your Name
git config --global user.email your@email
```

View file

@ -1,4 +0,0 @@
Thank you for your interest in contributing to libinput.
Please find more information about how to contribute in
[the documentation](https://wayland.freedesktop.org/libinput/doc/latest/contributing.html).

View file

@ -31,4 +31,4 @@ This copy is provided to provide consistent behavior regardless which kernel
version libinput is compiled against. The header is used during compilation
only, libinput does not link against GPL libraries.
[1] https://gitlab.freedesktop.org/libinput/libinput/blob/main/include/linux/input.h
[1] http://cgit.freedesktop.org/wayland/libinput/tree/include/linux/input.h

6
Makefile.am Normal file
View file

@ -0,0 +1,6 @@
SUBDIRS = src doc test tools udev
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
valgrind:
(cd test; $(MAKE) valgrind)

View file

@ -1,84 +0,0 @@
libinput
========
libinput is a library that provides a full input stack for display servers
and other applications that need to handle input devices provided by the
kernel.
libinput provides device detection, event handling and abstraction to
minimize the amount of custom input code the user of libinput needs to
provide the common set of functionality that users expect. Input event
processing includes scaling touch coordinates, generating
relative pointer events from touchpads, pointer acceleration, etc.
User documentation
------------------
Documentation explaining features available in libinput is available
[here](https://wayland.freedesktop.org/libinput/doc/latest/features.html).
This includes the [FAQ](https://wayland.freedesktop.org/libinput/doc/latest/faqs.html)
and the instructions on
[reporting bugs](https://wayland.freedesktop.org/libinput/doc/latest/reporting-bugs.html).
Source code
-----------
The source code of libinput can be found at:
https://gitlab.freedesktop.org/libinput/libinput
For a list of current and past releases visit:
https://www.freedesktop.org/wiki/Software/libinput/
Build instructions:
https://wayland.freedesktop.org/libinput/doc/latest/building.html
Reporting Bugs
--------------
Bugs can be filed on freedesktop.org GitLab:
https://gitlab.freedesktop.org/libinput/libinput/issues/
Where possible, please provide the `libinput record` output
of the input device and/or the event sequence in question.
See https://wayland.freedesktop.org/libinput/doc/latest/reporting-bugs.html
for more info.
Documentation
-------------
- Developer API documentation: https://wayland.freedesktop.org/libinput/doc/latest/development.html
- High-level documentation about libinput's features:
https://wayland.freedesktop.org/libinput/doc/latest/features.html
- Build instructions:
https://wayland.freedesktop.org/libinput/doc/latest/building.html
- Documentation for previous versions of libinput: https://wayland.freedesktop.org/libinput/doc/
Examples of how to use libinput are the debugging tools in the libinput
repository. Developers are encouraged to look at those tools for a
real-world (yet simple) example on how to use libinput.
- A commandline debugging tool: https://gitlab.freedesktop.org/libinput/libinput/tree/main/tools/libinput-debug-events.c
- A GTK application that draws cursor/touch/tablet positions: https://gitlab.freedesktop.org/libinput/libinput/tree/main/tools/libinput-debug-gui.c
License
-------
libinput is licensed under the MIT license.
> 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: [...]
See the [COPYING](https://gitlab.freedesktop.org/libinput/libinput/tree/main/COPYING)
file for the full license information.
About
-----
Documentation generated from git commit [__GIT_VERSION__](https://gitlab.freedesktop.org/libinput/libinput/commit/__GIT_VERSION__)

85
README.txt Normal file
View file

@ -0,0 +1,85 @@
/*!@mainpage
libinput
========
libinput is a library that handles input devices for display servers and other
applications that need to directly deal with input devices.
It provides device detection, device handling, input device event processing
and abstraction so minimize the amount of custom input code the user of
libinput need to provide the common set of functionality that users expect.
Input event processing includes scaling touch coordinates, generating
pointer events from touchpads, pointer acceleration, etc.
libinput originates from
[weston](http://cgit.freedesktop.org/wayland/weston/), the Wayland reference
compositor.
Architecture
------------
libinput is not used directly by applications, rather it is used by the
xf86-input-libinput X.Org driver or wayland compositors. The typical
software stack for a system running Wayland is:
@dotfile libinput-stack-wayland.gv
Where the Wayland compositor may be Weston, mutter, KWin, etc. Note that
Wayland encourages the use of toolkits, so the Wayland client (your
application) does not usually talk directly to the compositor but rather
employs a toolkit (e.g. GTK) to do so.
The simplified software stack for a system running X.Org is:
@dotfile libinput-stack-xorg.gv
Again, on a modern system the application does not usually talk directly to
the X server using Xlib but rather employs a toolkit to do so.
Source code
-----------
The source code of libinput can be found at:
http://cgit.freedesktop.org/wayland/libinput
For a list of current and past releases visit:
http://www.freedesktop.org/wiki/Software/libinput/
Reporting Bugs
--------------
Bugs can be filed in the libinput component of Wayland:
https://bugs.freedesktop.org/enter_bug.cgi?product=Wayland&component=libinput
Where possible, please provide an
[evemu](http://www.freedesktop.org/wiki/Evemu/) recording of the input
device and/or the event sequence in question.
See @ref reporting_bugs for more info.
Documentation
-------------
Developer API documentation:
http://wayland.freedesktop.org/libinput/doc/latest/modules.html
High-level documentation about libinput's features:
http://wayland.freedesktop.org/libinput/doc/latest/pages.html
License
-------
libinput is licensed under the MIT license.
> 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: [...]
See the [COPYING](http://cgit.freedesktop.org/wayland/libinput/tree/COPYING)
file for the full license information.
*/

9
autogen.sh Executable file
View file

@ -0,0 +1,9 @@
#!/bin/sh
test -n "$srcdir" || srcdir=`dirname "$0"`
test -n "$srcdir" || srcdir=.
(
cd "$srcdir" &&
autoreconf --force -v --install
) || exit
test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"

View file

@ -1,282 +0,0 @@
#compdef libinput
(( $+functions[_libinput_commands] )) || _libinput_commands()
{
local -a commands
commands=(
"list-devices:List all devices recognized by libinput"
"debug-events:Print all events as seen by libinput"
"debug-gui:Show a GUI to visualize libinput's events"
"debug-tablet:Show tablet axis and button values"
"measure:Measure various properties of devices"
"analyze:Analyze device data"
"record:Record the events from a device"
"replay:Replay the events from a device"
)
_describe -t commands 'command' commands
}
__all_seats()
{
# Obviously only works with logind
local -a seats
seats=${(f)"$(loginctl --no-legend --no-pager list-seats 2>/dev/null)"}
if [[ -z $seats ]]; then
# Can always offer seat0, even if we can't enumerate the seats
compadd "$@" - seat0
else
compadd "$@" - $seats
fi
}
(( $+functions[_libinput_list-devices] )) || _libinput_list-devices()
{
_arguments \
'--help[Show help and exit]' \
'--version[show version information and exit]'
}
(( $+functions[_libinput_debug-events] )) || _libinput_debug-events()
{
_arguments \
'--help[Show debug-events help and exit]' \
'--quiet[Only print libinput messages and nothing from this tool]' \
'--verbose[Use verbose output]' \
'--show-keycodes[Make all keycodes visible]' \
'--grab[Exclusively grab all opened devices]' \
'--compress-motion-events[Compress repeated motion events on a TTY]' \
'--device=[Use the given device with the path backend]:device:_files -W /dev/input/ -P /dev/input/' \
'--udev=[Listen for notifications on the given seat]:seat:__all_seats' \
'--apply-to=[Apply configuration options where the device name matches the pattern]:pattern' \
'--disable-sendevents=[Disable send-events option for the devices matching the pattern]:pattern' \
'--set-area=[Set the desired area as "x1/y1 x2/y2" (within \[0.0, 1.0\]) ]' \
'--set-calibration=[Set the first 6 elements of the 3x3 calibration matrix ("1.0 0.0 0.0 0.0 1.0 0.0")]' \
'--set-click-method=[Set the desired click method]:click-method:(none clickfinger buttonareas)' \
'--set-clickfinger-map=[Set button mapping for clickfinger]:tap-map:(( \
lrm\:2-fingers\ right-click\ /\ 3-fingers\ middle-click \
lmr\:2-fingers\ middle-click\ /\ 3-fingers\ right-click \
))' \
'--set-eraser-button-button=[Set button mapping for the eraser button]:eraser-button:(BTN_STYLUS BTN_STYLUS2 BTN_STYLUS3)' \
'--set-eraser-button-mode=[Set the eraser button mode]:eraser-mode:(default button)' \
'--set-pressure-range=[Set the tablet tool pressure range (within range \[0.0, 1.0\])]' \
'--set-profile=[Set pointer acceleration profile]:accel-profile:(adaptive flat custom)' \
'--set-rotation-angle=[Set the rotation angle in degrees]' \
'--set-scroll-button=[Set the button to the given button code]' \
'--set-scroll-method=[Set the desired scroll method]:scroll-method:(none twofinger edge button)' \
'--set-speed=[Set pointer acceleration speed (within range \[-1, 1\])]' \
'--set-tap-map=[Set button mapping for tapping]:tap-map:(( \
lrm\:2-fingers\ right-click\ /\ 3-fingers\ middle-click \
lmr\:2-fingers\ middle-click\ /\ 3-fingers\ right-click \
))' \
+ '(custom pointer acceleration)' \
'--set-custom-points=[Set n points defining a custom acceleration function]' \
'--set-custom-step=[Set the distance along the x axis between the custom points]' \
'--set-custom-type=[Set the type of the acceleration function]:custom-type:(fallback motion scroll)' \
+ '(drag)' \
'--enable-drag[Enable tap-and-drag]' \
'--disable-drag[Disable tap-and-drag]' \
+ '(drag-lock)' \
'--enable-drag-lock[Enable drag-lock]' \
'--disable-drag-lock[Disable drag-lock]' \
+ '(dwt)' \
'--enable-dwt[Enable disable-while-typing]' \
'--disable-dwt[Disable disable-while-typing]' \
+ '(dwtp)' \
'--enable-dwtp[Enable disable-while-trackpointing]' \
'--disable-dwtp[Disable disable-while-trackpointing]' \
+ '(left-handed)' \
'--enable-left-handed[Enable left handed button configuration]' \
'--disable-left-handed[Disable left handed button configuration]' \
+ '(middlebutton)' \
'--enable-middlebutton[Enable middle button emulation]' \
'--disable-middlebutton[Disable middle button emulation]' \
+ '(natural-scrolling)' \
'--enable-natural-scrolling[Enable natural scrolling]' \
'--disable-natural-scrolling[Disable natural scrolling]' \
+ '(plugins)' \
'--enable-plugins[Enable plugins]' \
'--disable-plugins[Disable plugins]' \
+ '(tap-to-click)' \
'--enable-tap[Enable tap-to-click]' \
'--disable-tap[Disable tap-to-click]'
}
(( $+functions[_libinput_debug-gui] )) || _libinput_debug-gui()
{
_arguments \
'--help[Show debug-gui help and exit]' \
'--verbose[Use verbose output]' \
'--grab[Exclusively grab all opened devices]' \
'--device=[Use the given device with the path backend]:device:_files -W /dev/input/ -P /dev/input/' \
'--udev=[Listen for notifications on the given seat]:seat:_libinput_all_seats'
}
(( $+functions[_libinput_debug-tablet] )) || _libinput_debug-tablet()
{
_arguments \
'--help[Show debug-tablet help and exit]' \
'--device=[Use the given device with the path backend]:device:_files -W /dev/input/ -P /dev/input/' \
'--udev=[Use the first tablet device on the given seat]:seat:_libinput_all_seats'
}
(( $+functions[_libinput_measure] )) || _libinput_measure()
{
local curcontext=$curcontext state line ret=1
local features
features=(
"fuzz:Measure touch fuzz to avoid pointer jitter"
"touch-size:Measure touch size and orientation"
"touchpad-tap:Measure tap-to-click time"
"touchpad-pressure:Measure touch pressure"
)
_arguments -C \
'--help[Print help and exit]' \
':feature:->feature' \
'*:: :->option-or-argument'
case $state in
(feature)
_describe -t features 'feature' features
;;
(option-or-argument)
curcontext=${curcontext%:*:*}:libinput-measure-$words[1]:
if ! _call_function ret _libinput_measure_$words[1]; then
_message "unknown feature: $words[1]"
fi
;;
esac
return ret
}
(( $+functions[_libinput_measure_fuzz] )) || _libinput_measure_fuzz()
{
_arguments \
'--help[Show help message and exit]' \
':device:_files -W /dev/input/ -P /dev/input/'
}
(( $+functions[_libinput_measure_touch-size] )) || _libinput_measure_touch-size()
{
_arguments \
'--help[Show help message and exit]' \
'--touch-threshold=[Assume a touch pressure threshold of "down:up"]' \
'--palm-threshold=[Assume a palm threshold of N]' \
':device:_files -W /dev/input/ -P /dev/input/'
}
(( $+functions[_libinput_measure_touchpad-pressure] )) || _libinput_measure_touchpad-pressure()
{
_arguments \
'--help[Show help message and exit]' \
'--touch-threshold=[Assume a touch pressure threshold of "down:up"]' \
'--palm-threshold=[Assume a palm threshold of N]' \
':device:_files -W /dev/input/ -P /dev/input/'
}
(( $+functions[_libinput_measure_touchpad-tap] )) || _libinput_measure_touchpad-tap()
{
_arguments \
'--help[Show help message and exit]' \
'--format=dat[Specify the data format to be printed. The default is "summary"]' \
':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 \
'--help[Print help and exit]' \
':feature:->feature' \
'*:: :->option-or-argument'
case $state in
(feature)
_describe -t features 'feature' features
;;
(option-or-argument)
curcontext=${curcontext%:*:*}:libinput-analyze-$words[1]:
if ! _call_function ret _libinput_analyze_$words[1]; then
_message "unknown feature: $words[1]"
fi
;;
esac
return ret
}
(( $+functions[_libinput_record] )) || _libinput_record()
{
_arguments \
'--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=}'[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]' \
'--with-hidraw[Record hidraw events alongside device events]' \
'*::device:_files -W /dev/input/ -P /dev/input/'
}
(( $+functions[_libinput_replay] )) || _libinput_replay()
{
_arguments \
'--help[Show help message and exit]' \
':recording:_files'
}
_libinput()
{
local curcontext=$curcontext state line ret=1
_arguments -C \
{-h,--help}'[Show help message and exit]' \
'--version[Show version information and exit]' \
':command:->command' \
'*:: :->option-or-argument' && return
case $state in
(command)
_libinput_commands && ret=0
;;
(option-or-argument)
curcontext=${curcontext%:*:*}:libinput-$words[1]:
if ! _call_function ret _libinput_$words[1]; then
_message "unknown libinput command: $words[1]"
fi
;;
esac
return ret
}
_libinput

View file

@ -1,12 +0,0 @@
zshcompletiondir = get_option('zshcompletiondir')
if zshcompletiondir == ''
zshcompletiondir = get_option('datadir') / 'zsh' / 'site-functions'
endif
if zshcompletiondir != 'no'
install_data(
'_libinput',
install_dir: zshcompletiondir,
install_mode: 'rw-r--r--',
)
endif

226
configure.ac Normal file
View file

@ -0,0 +1,226 @@
AC_PREREQ([2.64])
m4_define([libinput_major_version], [1])
m4_define([libinput_minor_version], [1])
m4_define([libinput_micro_version], [8])
m4_define([libinput_version],
[libinput_major_version.libinput_minor_version.libinput_micro_version])
AC_INIT([libinput],
[libinput_version],
[https://bugs.freedesktop.org/enter_bug.cgi?product=Wayland&component=libinput&version=libinput_version],
[libinput],
[http://www.freedesktop.org/wiki/Software/libinput/])
AC_SUBST([LIBINPUT_VERSION_MAJOR], [libinput_major_version])
AC_SUBST([LIBINPUT_VERSION_MINOR], [libinput_minor_version])
AC_SUBST([LIBINPUT_VERSION_MICRO], [libinput_micro_version])
AC_SUBST([LIBINPUT_VERSION], [libinput_version])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
# Before making a release, the LIBINPUT_LT_VERSION string should be
# modified.
# The string is of the form C:R:A.
# a) If binary compatibility has been broken (eg removed or changed interfaces)
# change to C+1:0:0. DO NOT DO THIS! Use symbol versioning instead and
# do b) instead.
# b) If interfaces have been changed or added, but binary compatibility has
# been preserved, change to C+1:0:A+1
# c) If the interface is the same as the previous version, change to C:R+1:A
LIBINPUT_LT_VERSION=16:8:6
AC_SUBST(LIBINPUT_LT_VERSION)
AM_SILENT_RULES([yes])
AC_USE_SYSTEM_EXTENSIONS
# Check for programs
AC_PROG_CC_C99
AC_PROG_CXX # Only used by build C++ test
AC_PROG_GREP
# Initialize libtool
LT_PREREQ([2.2])
LT_INIT
AC_CHECK_DECL(EPOLL_CLOEXEC, [],
[AC_MSG_ERROR("EPOLL_CLOEXEC is needed to compile libinput")],
[[#include <sys/epoll.h>]])
AC_CHECK_DECL(TFD_CLOEXEC,[],
[AC_MSG_ERROR("TFD_CLOEXEC is needed to compile libinput")],
[[#include <sys/timerfd.h>]])
AC_CHECK_DECL(CLOCK_MONOTONIC,[],
[AC_MSG_ERROR("CLOCK_MONOTONIC is needed to compile libinput")],
[[#include <time.h>]])
PKG_PROG_PKG_CONFIG()
PKG_CHECK_MODULES(MTDEV, [mtdev >= 1.1.0])
PKG_CHECK_MODULES(LIBUDEV, [libudev])
PKG_CHECK_MODULES(LIBEVDEV, [libevdev >= 0.4])
AC_ARG_WITH(libunwind,
AS_HELP_STRING([--without-libunwind],[Do not use libunwind]))
AS_IF([test "x$with_libunwind" != "xno"],
[PKG_CHECK_MODULES(LIBUNWIND,
[libunwind],
[HAVE_LIBUNWIND=yes],
[HAVE_LIBUNWIND=no])],
[HAVE_LIBUNWIND=no])
AS_IF([test "x$HAVE_LIBUNWIND" = "xyes"],
[AC_DEFINE(HAVE_LIBUNWIND, 1, [Have libunwind support])],
[AS_IF([test "x$with_libunwind" = "xyes"],
[AC_MSG_ERROR([libunwind requested but not found])])])
AM_CONDITIONAL(HAVE_LIBUNWIND, [test "x$HAVE_LIBUNWIND" = xyes])
AC_PATH_PROG(ADDR2LINE, [addr2line])
if test "x$ADDR2LINE" != "x"; then
AC_DEFINE_UNQUOTED(HAVE_ADDR2LINE, 1, [addr2line found])
AC_DEFINE_UNQUOTED(ADDR2LINE, ["$ADDR2LINE"], [Path to addr2line])
fi
AC_CHECK_LIB([m], [atan2])
AC_CHECK_LIB([rt], [clock_gettime])
if test "x$GCC" = "xyes"; then
GCC_CXXFLAGS="-Wall -Wextra -Wno-unused-parameter -g -fvisibility=hidden"
GCC_CFLAGS="$GCC_CXXFLAGS -Wmissing-prototypes -Wstrict-prototypes"
fi
AC_SUBST(GCC_CFLAGS)
AC_SUBST(GCC_CXXFLAGS)
udev_dir_default="$libdir/udev"
AC_ARG_WITH(udev-dir,
AS_HELP_STRING([--with-udev-dir=DIR],
[udev base directory [[default=$udev_dir_default]]]),
[],
[with_udev_dir="yes"])
AS_CASE($with_udev_dir,
[no|""], [AC_MSG_ERROR([You must define a udev base directory])],
[yes], [udevdir="$udev_dir_default"],
[udevdir="$with_udev_dir"])
UDEV_DIR=${udevdir}
AC_SUBST(UDEV_DIR)
AC_ARG_ENABLE([documentation],
[AC_HELP_STRING([--enable-documentation],
[Enable building the documentation (default=auto)])],
[build_documentation="$enableval"],
[build_documentation="auto"])
if test "x$build_documentation" = "xyes" -o "x$build_documentation" = "xauto"; then
AC_PATH_PROG(DOXYGEN, doxygen)
if test "x$DOXYGEN" = "x"; then
if test "x$build_documentation" = "xyes"; then
AC_MSG_ERROR([Documentation build requested but doxygen not found. Install doxygen or disable the documentation using --disable-documentation])
fi
else
AC_MSG_CHECKING([for compatible doxygen version])
doxygen_version=`$DOXYGEN --version`
AS_VERSION_COMPARE([$doxygen_version], [1.6.0],
[AC_MSG_RESULT([no])
DOXYGEN=""],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([yes])])
if test "x$DOXYGEN" = "x" -a "x$build_documentation" = "xyes"; then
AC_MSG_ERROR([Doxygen $doxygen_version too old. Doxygen 1.6+ required for documentation build. Install required doxygen version or disable the documentation using --disable-documentation])
fi
fi
AC_PATH_PROG(DOT, dot)
if test "x$DOT" = "x"; then
if test "x$build_documentation" = "xyes"; then
AC_MSG_ERROR([Documentation build requested but graphviz's dot not found. Install graphviz or disable the documentation using --disable-documentation])
fi
else
AC_MSG_CHECKING([for compatible dot version])
dot_version=`$DOT -V 2>&1|$GREP -oP '(?<=version\W)@<:@0-9.@:>@*(?=\W(.*))'`
AS_VERSION_COMPARE([$dot_version], [2.26.0],
[AC_MSG_RESULT([no])
DOT=""],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([yes])])
if test "x$DOT" = "x" -a "x$build_documentation" = "xyes"; then
AC_MSG_ERROR([Graphviz dot $dot_version too old. Graphviz 2.26+ required for documentation build. Install required graphviz version or disable the documentation using --disable-documentation])
fi
fi
if test "x$DOXYGEN" != "x" -a "x$DOT" != "x"; then
build_documentation="yes"
else
build_documentation="no"
fi
fi
AC_ARG_ENABLE(event-gui,
AS_HELP_STRING([--enable-event-gui], [Build the GUI event viewer (default=auto)]),
[build_eventgui="$enableval"],
[build_eventgui="auto"])
PKG_CHECK_EXISTS([cairo glib-2.0 gtk+-3.0], [HAVE_GUILIBS="yes"], [HAVE_GUILIBS="no"])
if test "x$build_eventgui" = "xauto"; then
build_eventgui="$HAVE_GUILIBS"
fi
if test "x$build_eventgui" = "xyes"; then
PKG_CHECK_MODULES(CAIRO, [cairo])
PKG_CHECK_MODULES(GTK, [glib-2.0 gtk+-3.0])
fi
AM_CONDITIONAL(BUILD_EVENTGUI, [test "x$build_eventgui" = "xyes"])
AC_ARG_ENABLE(tests,
AS_HELP_STRING([--enable-tests], [Build the tests (default=auto)]),
[build_tests="$enableval"],
[build_tests="auto"])
PKG_CHECK_MODULES(CHECK, [check >= 0.9.10], [HAVE_CHECK="yes"], [HAVE_CHECK="no"])
if test "x$build_tests" = "xauto"; then
build_tests="$HAVE_CHECK"
fi
if test "x$build_tests" = "xyes"; then
if test "x$HAVE_CHECK" = "xno"; then
AC_MSG_ERROR([Cannot build tests, check is missing])
fi
AC_PATH_PROG(VALGRIND, [valgrind])
fi
AM_CONDITIONAL(HAVE_VALGRIND, [test "x$VALGRIND" != "x"])
AM_CONDITIONAL(BUILD_TESTS, [test "x$build_tests" = "xyes"])
AM_CONDITIONAL(BUILD_DOCS, [test "x$build_documentation" = "xyes"])
# Used by the udev rules so we can use callouts during testing without
# installing everything first. Default is the empty string so the installed
# rule will use udev's default path. Override is in udev/Makefile.am
AC_SUBST(UDEV_TEST_PATH, "")
AC_PATH_PROG(SED, [sed])
AC_CONFIG_FILES([Makefile
doc/Makefile
doc/libinput.doxygen
src/Makefile
src/libinput.pc
src/libinput-version.h
test/Makefile
tools/Makefile
udev/Makefile
udev/80-libinput-device-groups.rules
udev/90-libinput-model-quirks.rules])
AC_CONFIG_FILES([test/symbols-leak-test],
[chmod +x test/symbols-leak-test])
AC_OUTPUT
AC_MSG_RESULT([
Prefix ${prefix}
udev base dir ${UDEV_DIR}
Build documentation ${build_documentation}
Build tests ${build_tests}
Tests use valgrind ${VALGRIND}
Tests use libunwind ${HAVE_LIBUNWIND}
Build GUI event tool ${build_eventgui}
])

84
doc/Makefile.am Normal file
View file

@ -0,0 +1,84 @@
EXTRA_DIST = \
middle-button-emulation.svg \
touchpad-tap-state-machine.svg \
touchpad-softbutton-state-machine.svg
if BUILD_DOCS
noinst_DATA = html/index.html
header_files = \
$(top_srcdir)/src/libinput.h \
$(top_srcdir)/README.txt \
$(srcdir)/absolute-axes.dox \
$(srcdir)/clickpad-softbuttons.dox \
$(srcdir)/device-configuration-via-udev.dox \
$(srcdir)/faqs.dox \
$(srcdir)/gestures.dox \
$(srcdir)/normalization-of-relative-motion.dox \
$(srcdir)/palm-detection.dox \
$(srcdir)/page-hierarchy.dox \
$(srcdir)/pointer-acceleration.dox \
$(srcdir)/reporting-bugs.dox \
$(srcdir)/scrolling.dox \
$(srcdir)/seats.dox \
$(srcdir)/t440-support.dox \
$(srcdir)/tapping.dox \
$(srcdir)/test-suite.dox \
$(srcdir)/tools.dox \
$(srcdir)/touchpads.dox
diagram_files = \
$(srcdir)/dot/seats-sketch.gv \
$(srcdir)/dot/seats-sketch-libinput.gv \
$(srcdir)/dot/libinput-stack-wayland.gv \
$(srcdir)/dot/libinput-stack-xorg.gv \
$(srcdir)/dot/libinput-stack-gnome.gv \
$(srcdir)/dot/evemu.gv \
$(srcdir)/svg/software-buttons.svg \
$(srcdir)/svg/clickfinger.svg \
$(srcdir)/svg/button-scrolling.svg \
$(srcdir)/svg/edge-scrolling.svg \
$(srcdir)/svg/palm-detection.svg \
$(srcdir)/svg/pinch-gestures.svg \
$(srcdir)/svg/ptraccel-linear.svg \
$(srcdir)/svg/ptraccel-low-dpi.svg \
$(srcdir)/svg/ptraccel-touchpad.svg \
$(srcdir)/svg/ptraccel-trackpoint.svg \
$(srcdir)/svg/swipe-gestures.svg \
$(srcdir)/svg/tap-n-drag.svg \
$(srcdir)/svg/thumb-detection.svg \
$(srcdir)/svg/top-software-buttons.svg \
$(srcdir)/svg/touchscreen-gestures.svg \
$(srcdir)/svg/twofinger-scrolling.svg
style_files = \
style/header.html \
style/footer.html \
style/customdoxygen.css \
style/bootstrap.css
html/index.html: libinput.doxygen $(header_files) $(diagram_files) $(style_files)
$(AM_V_GEN)(cat $<; \
echo "INPUT = $(header_files)"; \
) | $(DOXYGEN) -
clean-local:
$(AM_V_at)rm -rf html
doc_src= $(shell find html -type f -printf "html/%P\n" 2>/dev/null)
EXTRA_DIST += $(builddir)/html/index.html \
$(doc_src) \
$(diagram_files) \
$(header_files) \
$(style_files)
endif
# make sure doc was built before running dist
dist-hook:
@test -f $(distdir)/html/index.html || (\
echo "******************************************************" && \
echo "Couldn't find documentation files, refusing make dist." && \
echo "Install doxygen to build documentation for tarball." && \
echo "******************************************************" && \
test )

130
doc/absolute-axes.dox Normal file
View file

@ -0,0 +1,130 @@
/**
@page absolute_axes Absolute axes
Devices with absolute axes are those that send positioning data for an axis in
a device-specific coordinate range, defined by a minimum and a maximum value.
Compare this to relative devices (e.g. a mouse) that can only detect
directional data, not positional data.
libinput supports three types of devices with absolute axes:
- multi-touch screens
- single-touch screens
- graphics tablets (currently WIP)
Touchpads are technically absolute devices but libinput converts the axis values
to directional motion and posts events as relative events. Touchpads do not count
as absolute devices in libinput.
For all absolute devices in libinput, the default unit for x/y coordinates is
in mm off the top left corner on the device, or more specifically off the
device's sensor.
@section absolute_axes_handling Handling of absolute coordinates
In most use-cases, absolute input devices are mapped to a single screen. For
direct input devices such as touchscreens the aspect ratio of the screen and
the device match. Mapping the input device position to the output position is
thus a simple mapping between two coordinates. libinput provides the API for
this with
- libinput_event_pointer_get_absolute_x_transformed() for pointer events
- libinput_event_touch_get_x_transformed() for touch events
libinput's API only provides the call to map into a single coordinate range.
If the coordinate range has an offset, the compositor is responsible for
applying that offset after the mapping. For example, if the device is mapped
to the right of two outputs, add the output offset to the transformed
coordinate.
@section absolute_axes_nores Devices without x/y resolution
An absolute device that does not provide a valid resolution is considered
buggy and must be fixed in the kernel. Some touchpad devices that do not
provide resolution, those devices are correctly handled within libinput
(touchpads are not absolute devices, as mentioned above).
@section calibration Calibration of absolute devices
Absolute devices may require calibration to map precisely into the output
range required. This is done by setting a transformation matrix, see
libinput_device_config_calibration_set_matrix() which is applied to
each input coordinate.
@f[
\begin{pmatrix}
cos\theta & -sin\theta & xoff \\
sin\theta & cos\theta & yoff \\
0 & 0 & 1
\end{pmatrix} \begin{pmatrix}
x \\ y \\ 1
\end{pmatrix}
@f]
@f$\theta@f$ is the rotation angle. The offsets @f$xoff@f$ and @f$yoff@f$ are
specified in device dimensions, i.e. a value of 1 equals one device width
or height. Note that rotation applies to the device's origin, rotation
usually requires an offset to move the coordinates back into the original
range.
The most common matrices are:
- 90 degree clockwise:
@f$
\begin{pmatrix}
0 & -1 & 1 \\
1 & 0 & 0 \\
0 & 0 & 1
\end{pmatrix}
@f$
- 180 degree clockwise:
@f$
\begin{pmatrix}
-1 & 0 & 1 \\
0 & -1 & 1 \\
0 & 0 & 1
\end{pmatrix}
@f$
- 270 degree clockwise:
@f$
\begin{pmatrix}
0 & 1 & 0 \\
-1 & 0 & 1 \\
0 & 0 & 1
\end{pmatrix}
@f$
- reflection along y axis:
@f$
\begin{pmatrix}
-1 & 0 & 1 \\
1 & 0 & 0 \\
0 & 0 & 1
\end{pmatrix}
@f$
See Wikipedia's
<a href="http://en.wikipedia.org/wiki/Transformation_matrix">Transformation
Matrix article</a> for more information on the matrix maths.
See libinput_device_config_calibration_get_default_matrix() for how these
matrices must be supplied to libinput.
@section absolute_axes_nonorm Why x/y coordinates are not normalized
x/y are not given in @ref motion_normalization "normalized coordinates"
([0..1]) for one simple reason: the aspect ratio of virtually all current
devices is something other than 1:1. A normalized axes thus is only useful to
determine that the stylus is e.g. at 78% from the left, 34% from the top of
the device. Without knowing the per-axis resolution, these numbers are
meaningless. Worse, calculation based on previous coordinates is simply wrong:
a movement from 0/0 to 50%/50% is not a 45% degree line.
This could be alleviated by providing resolution and information about the
aspect ratio to the caller. Which shifts processing and likely errors into the
caller for little benefit. Providing the x/y axes in mm from the outset
removes these errors.
*/

View file

@ -1,34 +0,0 @@
PROJECT_NAME = @PACKAGE_NAME@
PROJECT_NUMBER = @PACKAGE_VERSION@
PROJECT_BRIEF = "A wrapper library for input devices"
JAVADOC_AUTOBRIEF = YES
TAB_SIZE = 8
OPTIMIZE_OUTPUT_FOR_C = YES
EXTRACT_ALL = YES
EXTRACT_STATIC = YES
MAX_INITIALIZER_LINES = 0
WARNINGS = YES
QUIET = YES
INPUT = "@builddir@"
IMAGE_PATH = "@builddir@"
OUTPUT_DIRECTORY = doc
GENERATE_HTML = YES
HTML_OUTPUT = html
SEARCHENGINE = NO
USE_MATHJAX = YES
MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
GENERATE_LATEX = NO
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
PREDEFINED = LIBINPUT_ATTRIBUTE_PRINTF(f, a)= \
LIBINPUT_ATTRIBUTE_DEPRECATED
DOTFILE_DIRS = "@builddir@"
EXAMPLE_PATH = "@builddir@"
SHOW_NAMESPACES = NO
HAVE_DOT = YES
HTML_HEADER = "@builddir@/header.html"
HTML_FOOTER = "@builddir@/footer.html"
HTML_EXTRA_STYLESHEET = "@builddir@/bootstrap.css" \
"@builddir@/customdoxygen.css" \
"@builddir@/libinputdoxygen.css"

View file

@ -1,135 +0,0 @@
/**
@mainpage
This is the libinput API reference.
This documentation is aimed at developers of Wayland compositors. User
documentation is available
[here](https://wayland.freedesktop.org/libinput/doc/latest).
@section concepts Concepts
@subsection concepts_initialization Initialization of a libinput context
libinput provides two different backends:
- a @ref libinput_udev_create_context "udev backend" where notifications
about new and removed devices are provided by udev, and
- a @ref libinput_path_create_context "path backend" where
@ref libinput_path_add_device "device addition" and
@ref libinput_path_remove_device "device removal" need to be handled by
the caller.
See section @ref base for information about initializing a libinput context.
@subsection concepts_events Monitoring for events
libinput exposes a single @ref libinput_get_fd "file descriptor" to the
caller. This file descriptor should be monitored by the caller, whenever
data is available the caller **must** immediately call libinput_dispatch().
Failure to do so will result in erroneous behavior.
libinput_dispatch() may result in one or more events being available to the
caller. After libinput_dispatch() a caller **should** call
libinput_get_event() to retrieve and process this event. Whenever
libinput_get_event() returns `NULL`, no further events are available.
See section @ref event for more information about events.
@subsection concepts_seats Device grouping into seats
All devices are grouped into physical and logical seats. Button and key
states are available per-device and per-seat. See @ref seat for more
information.
@subsection concepts_devices Device capabilities
libinput does not use device types. All devices have @ref
libinput_device_has_capability "capabilities" that define which events may
be generated. See @ref device for more information about devices.
Specific event types include:
- @ref event_keyboard
- @ref event_pointer
- @ref event_touch
- @ref event_gesture
- @ref event_tablet
- @ref event_tablet_pad
- @ref event_switch
@subsection concepts_configuration Device configuration
libinput relies on the caller for device configuration. See
@ref config for more information.
@subsection example An example libinput program
The simplest libinput program looks like this:
@code
static int open_restricted(const char *path, int flags, void *user_data)
{
int fd = open(path, flags);
return fd < 0 ? -errno : fd;
}
static void close_restricted(int fd, void *user_data)
{
close(fd);
}
const static struct libinput_interface interface = {
.open_restricted = open_restricted,
.close_restricted = close_restricted,
};
int main(void) {
struct libinput *li;
struct libinput_event *event;
li = libinput_udev_create_context(&interface, NULL, udev);
libinput_udev_assign_seat(li, "seat0");
libinput_dispatch(li);
while ((event = libinput_get_event(li)) != NULL) {
// handle the event here
libinput_event_destroy(event);
libinput_dispatch(li);
}
libinput_unref(li);
return 0;
}
@endcode
@section building_against Building against libinput
libinput provides a
[pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/) file.
Software that uses libinput should use pkg-config and the
`PKG_CHECK_MODULES` autoconf macro.
Otherwise, the most rudimentary way to compile and link a program against
libinput is:
@verbatim
gcc -o myprogram myprogram.c `pkg-config --cflags --libs libinput`
@endverbatim
For further information on using pkgconfig see the pkg-config documentation.
@section stability Backwards-compatibility
libinput promises backwards-compatibility across all the 1.x.y version. An
application built against libinput 1.x.y will work with any future 1.*.*
release.
@section About
Documentation generated from git commit [__GIT_VERSION__](https://gitlab.freedesktop.org/libinput/libinput/commit/__GIT_VERSION__)
*/

View file

@ -1,52 +0,0 @@
prg_install = find_program('install')
doxygen = find_program('doxygen', required : false)
if not doxygen.found()
error('Program "doxygen" not found or not executable. Try building with -Ddocumentation=false')
endif
dot = find_program('dot', required : false)
if not dot.found()
error('Program "dot" not found or not executable. Try building with -Ddocumentation=false')
endif
mainpage = vcs_tag(command : ['git', 'log', '-1', '--format=%h'],
fallback : 'unknown',
input : 'mainpage.dox',
output : 'mainpage.dox',
replace_string: '__GIT_VERSION__')
src_doxygen = files(
# source files
'../../src/libinput.h',
# style files
'style/header.html',
'style/footer.html',
'style/customdoxygen.css',
'style/bootstrap.css',
'style/libinputdoxygen.css',
)
doxyfiles = []
foreach f : src_doxygen
df = configure_file(input: f,
output: '@PLAINNAME@',
copy : true)
doxyfiles += [ df ]
endforeach
doc_config = configuration_data()
doc_config.set('PACKAGE_NAME', meson.project_name())
doc_config.set('PACKAGE_VERSION', meson.project_version())
doc_config.set('builddir', meson.current_build_dir())
doxyfile = configure_file(input : 'libinput.doxygen.in',
output : 'libinput.doxygen',
configuration : doc_config)
custom_target('doxygen',
input : [ doxyfiles, doxyfile, mainpage ] + src_doxygen,
output : [ 'html' ],
command : [ doxygen, doxyfile ],
install : false,
depends: [ mainpage ],
build_by_default : true)

View file

@ -1,7 +0,0 @@
/**
@page Tablets
- @subpage tablet serial numbers
*/

View file

@ -1,120 +0,0 @@
@import url("https://fonts.googleapis.com/css?family=Roboto+Mono");
dd {
margin-left: 30px;
}
.title {
font-size: 200%;
font-weight: bold;
}
.title .ingroups {
font-size: 50%;
}
h1 {
font-size: 150%;
color: #354C7B;
background: none;
border-bottom: 1px solid #879ECB;
font-size: 150%;
font-weight: normal;
padding-top: 8px;
padding-bottom: 8px;
padding-left: 0px;
width: 100%;
}
h2 {
font-size: 120%;
color: #354C7B;
background: none;
border-bottom: 1px solid #879ECB;
font-size: 150%;
font-weight: normal;
padding-top: 8px;
padding-bottom: 8px;
padding-left: 0px;
width: 100%;
}
.sm-dox li {
float:left;
border-top: 0;
padding-right: 20px;
}
.sm li, .sm a {
position: relative;
}
.sm, .sm ul, .sm li {
list-style: none;
display: block;
line-height: normal;
direction: ltr;
text-align: left;
}
.sm, .sm *, .sm *::before, .sm *::after {
box-sizing: border-box;
}
#main-nav {
padding: 30px;
}
/* Main menu sub-items like file-list, etc */
#main-menu li ul {
display: none;
}
.paramname {
padding-right: 10px;
}
.memtitle {
background-image: none;
background-color: #F0F0F0;
}
.memproto {
background-color: #F0F0F0;
}
.headertitle {
background-image: none;
background-color: #F0F0F0;
}
div.header {
border: none;
}
td.fieldname {
font-family: 'Roboto Mono', monospace;
}
.fieldtable th {
background-image: none;
background-color: #F0F0F0;
}
body {
letter-spacing: 0px;
}
.mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams {
background-color: #F0F0F0;
}
a {
color: #2873b0;
}
.navpath ul {
background-image: none;
background-color: #F0F0F0;
}

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 97 KiB

View file

@ -1,50 +0,0 @@
# Source for the button debouncing wave diagram
# Paste into http://wavedrom.com/editor.html
{signal: [
{name:'current mode', wave: '3............', data: ['normal button press and release']},
{name:'physical button', wave: '01......0....'},
{name:'application ', wave: '01......0....'},
{},
['bounce mode',
{name:'current mode', wave: '4............', data: ['debounced button press']},
{name:'physical button', wave: '0101...0.....'},
{name: 'timeouts', wave: '01...0.1...0.'},
{name:'application ', wave: '01.....0.....'},
{},
{name:'current mode', wave: '4............', data: ['debounced button release']},
{name:'physical button', wave: '1...010......'},
{name: 'timeouts', wave: '0...1...0....'},
{name:'application ', wave: '1...0........'},
{},
{name:'current mode', wave: '5............', data: ['delayed button press']},
{name:'physical button', wave: '1...01.......'},
{name: 'timeouts', wave: '0...1...0....'},
{name:'application ', wave: '1...0...1....'},
{},
{name:'current mode', wave: '5............', data: ['delayed button release']},
{name:'physical button', wave: '0...10.......'},
{name: 'timeouts', wave: '0...1...0....'},
{name:'application ', wave: '0...1...0....'},
],
{},
['spurious mode',
{name:'current mode', wave: '3............', data: ['first spurious button release ']},
{name:'physical button', wave: '1.......01...'},
{name:'application ', wave: '1.......01...'},
{},
{name:'current mode', wave: '3............', data: ['later spurious button release ']},
{name:'physical button', wave: '1....01......'},
{name: 'timeouts', wave: '0....1..0....'},
{name:'application ', wave: '1............'},
{},
{name:'current mode', wave: '3............', data: ['delayed release in spurious mode ']},
{name:'physical button', wave: '1....0.......'},
{name: 'timeouts', wave: '0....1..0....'},
{name:'application ', wave: '1.......0....'}
],
],
head:{
text:'Button Debouncing Scenarios',
},
}

View file

@ -0,0 +1,95 @@
/**
@page clickpad_softbuttons Clickpad software button behavior
Clickpad is the name given to touchpads without physical buttons below the
touchpad. Instead, the whole touchpad acts as a button and left or right
button clicks are distinguished by the location and/or number of fingers on
the touchpad. <a href="http://www.synaptics.com/en/clickpad.php">"ClickPad" is
a trademark by Synaptics Inc.</a> but for simplicity we refer to any
touchpad with the above feature as Clickpad, regardless of the manufacturer.
A clickpad is always marked with the <a
href="https://www.kernel.org/doc/Documentation/input/event-codes.txt">INPUT_PROP_BUTTONPAD</a> property.
To perform a right-click on a Clickpad, libinput provides @ref
software_buttons and @ref clickfinger.
In the page below, the term "click" shall refer to a physical button press
and/or release of the touchpad, the term "button event" refers to the events
generated by libinput and passed to the caller in response to a click.
@section software_buttons Software button areas
On most clickpads, this is the default behavior. The bottom of the touchpad
is split in the middle to generate left or right button events on click. The
height of the button area depends on the hardware but is usually around
10mm.
Left, right and middle button events can be triggered as follows:
- if a finger is in the main area or the left button area, a click generates
left button events.
- if a finger is in the right area, a click generates right button events.
- if there is a finger in both the left and right button area, a click
generates middle button events.
@image html software-buttons.svg "Left, right and middle-button click with software button areas"
If fingers are down in the main area in addition to fingers in the
left or right button area, those fingers are are ignored.
A release event always releases the buttons logically down, regardless of
the current finger position
The movement of a finger can alter the button area behavior:
- if a finger starts in the main area and moves into the software button
area, the software buttons do not apply to that finger
- a finger in the software button area does not move the pointer
- if a finger moves out out of the button area it will control the pointer
if it's the first finger in the main area
- once a finger has moved out of the button area, it cannot move back in and
trigger a right or middle button event
On some touchpads, notably the 2015 Lenovo X1 Carbon 3rd series, the very
bottom end of the touchpad is outside of the sensor range but it is possible
to trigger a physical click there. To libinput, the click merely shows up as
a left button click without any positional finger data and it is
impossible to determine whether it is a left or a right click. libinput
ignores such button clicks, this behavior is intentional.
@section clickfinger Clickfinger behavior
This is the default behavior on Apple touchpads.
Here, a left, right, middle button event is generated when one, two, or
three fingers are held down on the touchpad when a physical click is
generated. The location of the fingers does not matter and there are no
software-defined button areas.
@image html clickfinger.svg "One, two and three-finger click with Clickfinger behavior"
On some touchpads, libinput imposes a limit on how the fingers may be placed
on the touchpad. In the most common use-case this allows for a user to
trigger a click with the thumb while leaving the pointer-moving finger on
the touchpad.
@image html clickfinger-distance.svg "Illustration of the distance detection algorithm"
In the illustration above the red area marks the proximity area around the
first finger. Since the thumb is outside of that area libinput considers the
click a single-finger click rather than a two-finger click.
Clickfinger configuration can be enabled through the
libinput_device_config_click_set_method() call. If clickfingers are
enabled on a touchpad with top software buttons, the top area will keep
acting as softbuttons for use with the trackpoint. Clickfingers will be used
everywhere else on the touchpad.
@section special_clickpads Special Clickpads
The Lenovo *40 series laptops have a clickpad that provides two software button sections, one at
the top and one at the bottom. See @ref t440_support "Lenovo *40 series touchpad support"
for details on the top software button.
Some Clickpads, notably some Cypress ones, perform right button detection in
firmware and appear to userspace as if the touchpad had physical buttons.
While physically clickpads, these are not handled by the software and
treated like traditional touchpads.
*/

View file

@ -0,0 +1,138 @@
/**
@page udev_config Static device configuration via udev
libinput supports some static configuration through udev properties.
These properties are read when the device is initially added
to libinput's device list, i.e. before the @ref
LIBINPUT_EVENT_DEVICE_ADDED event is generated.
The following udev properties are supported:
<dl>
<dt>LIBINPUT_CALIBRATION_MATRIX</dt>
<dd>Sets the calibration matrix, see
libinput_device_config_calibration_get_default_matrix(). If unset,
defaults to the identity matrix.
The udev property is parsed as 6 floating point numbers separated by a
single space each (scanf(3) format "%f %f %f %f %f %f").
The 6 values represent the first two rows of the calibration matrix as
described in libinput_device_config_calibration_set_matrix().
Example values are:
@code
ENV{LIBINPUT_CALIBRATION_MATRIX}="1 0 0 0 1 0" # default
ENV{LIBINPUT_CALIBRATION_MATRIX}="0 -1 1 1 0 0" # 90 degree clockwise
ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 0 -1 1" # 180 degree clockwise
ENV{LIBINPUT_CALIBRATION_MATRIX}="0 1 0 -1 0 1" # 270 degree clockwise
ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 1 0 0" # reflect along y axis
@endcode
</dd>
<dt>LIBINPUT_DEVICE_GROUP</dt>
<dd>A string identifying the @ref libinput_device_group for this device. Two
devices with the same property value are grouped into the same device group,
the value itself is irrelevant otherwise.
</dd>
<dt>ID_SEAT</dt>
<dd>Assigns the physical seat for this device. See
libinput_seat_get_physical_name(). Defaults to "seat0".</dd>
<dt>ID_INPUT</dt>
<dd>If this property is set, the device is considered an input device. Any
device with this property missing will be ignored, see @ref
udev_device_type.</dt>
</dd>
<dt>ID_INPUT_KEYBOARD, ID_INPUT_KEY, ID_INPUT_MOUSE, ID_INPUT_TOUCHPAD,
ID_INPUT_TOUCHSCREEN, ID_INPUT_TABLET, ID_INPUT_JOYSTICK,
ID_INPUT_ACCELEROMETER</dt>
<dd>If any of the above is set, libinput initializes the device as the given
type, see @ref udev_device_type. Note that for historical reasons more than
one of these may be set at any time, libinput will select only one of these
to determine the device type. To ensure libinput selects the correct device
type, only set one of them.</dd>
<dt>WL_SEAT</dt>
<dd>Assigns the logical seat for this device. See
libinput_seat_get_logical_name()
context. Defaults to "default".</dd>
<dt>MOUSE_DPI</dt>
<dd>HW resolution and sampling frequency of a relative pointer device.
See @ref motion_normalization for details.
</dd>
<dt>MOUSE_WHEEL_CLICK_ANGLE</dt>
<dd>The angle in degrees for each click on a mouse wheel. See
libinput_pointer_get_axis_source() for details.
</dd>
<dt>POINTINGSTICK_CONST_ACCEL</dt>
<dd>A constant (linear) acceleration factor to apply to pointingstick deltas
to normalize them.
<dt>LIBINPUT_MODEL_*</dt>
<dd><b>This prefix is reserved as private API, do not use.</b>. See @ref
model_specific_configuration for details.
</dd>
<dt>LIBINPUT_ATTR_*</dt>
<dd><b>This prefix is reserved as private API, do not use.</b>. See @ref
model_specific_configuration for details.
</dd>
</dl>
Below is an example udev rule to assign "seat1" to a device from vendor
0x012a with the model ID of 0x034b.
@code
ACTION=="add|change", KERNEL=="event[0-9]*", ENV{ID_VENDOR_ID}=="012a", \
ENV{ID_MODEL_ID}=="034b", ENV{ID_SEAT}="seat1"
@endcode
@section udev_device_type Device type assignment via udev
libinput requires the <b>ID_INPUT</b> property to be set on a device,
otherwise the device will be ignored. In addition, one of <b>
ID_INPUT_KEYBOARD, ID_INPUT_KEY, ID_INPUT_MOUSE, ID_INPUT_TOUCHPAD,
ID_INPUT_TOUCHSCREEN, ID_INPUT_TABLET, ID_INPUT_JOYSTICK,
ID_INPUT_ACCELEROMETER</b> must be set on the device to determine the
device type. The usual error handling applies within libinput and a device
type label does not guarantee that the device is initialized by libinput.
If a device fails to meet the requirements for a device type (e.g. a keyboard
labelled as touchpad) the device will not be available through libinput.
Only one device type should be set per device at a type, though libinput can
handle some combinations for historical reasons.
Below is an example udev rule to remove an <b>ID_INPUT_TOUCHPAD</b> setting
and change it into an <b>ID_INPUT_TABLET</b> setting. This rule would apply
for a device with the vendor/model ID of 012a/034b.
@code
ACTION=="add|change", KERNEL=="event[0-9]*", ENV{ID_VENDOR_ID}=="012a", \
ENV{ID_MODEL_ID}=="034b", ENV{ID_INPUT_TOUCHPAD}="", ENV{ID_INPUT_TABLET}="1"
@endcode
@section model_specific_configuration Model-specific configuration
libinput reserves the property prefixes <b>LIBINPUT_MODEL_</b> and
<b>LIBINPUT_ATTR_*</b> for model-specific configuration. <b>These prefixes
are reserved as private API, do not use.</b>
The effect of these properties may be to enable or disable certain
features on a specific device or set of devices, to change configuration
defaults or any other reason. The effects of setting these properties, the
format of the property and the value of the property are subject to change
at any time.
@subsection model_specific_configuration_x220fw81 Lenovo x220 with touchpad firmware v8.1
The property <b>LIBINPUT_MODEL_LENOVO_X220_TOUCHPAD_FW81</b> may be set by a
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
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.
The touchpad firmware version cannot be detected automatically by libinput,
local configuration is required to set this property. Refer to the libinput
model quirks hwdb for instructions.
This property must not be used for any other purpose, no specific behavior
is guaranteed.
*/

View file

@ -23,7 +23,7 @@ digraph stack
gsettings
}
gsd [label="mutter"];
gsd [label="gnome-settings-daemon"];
gsd -> gsettings
gsd -> xserver

View file

@ -0,0 +1,17 @@
digraph stack
{
rankdir="LR";
node [
shape="box";
]
kernel [label="Kernel"];
libinput;
compositor [label="Wayland Compositor"];
client [label="Wayland Client"];
kernel -> libinput
libinput -> compositor
compositor -> client
}

View file

@ -1,6 +1,5 @@
digraph stack
{
compound=true;
rankdir="LR";
node [
shape="box";
@ -9,12 +8,12 @@ digraph stack
kernel [label="Kernel"];
libinput;
xf86libinput [label="xf86-input-libinput"];
xserver [label="X Server"];
record [label="libinput record"];
client [label="X11 client"];
kernel -> libinput
libinput -> xserver
kernel -> record;
record -> stdout
libinput -> xf86libinput
xf86libinput -> xserver
xserver -> client
}

57
doc/faqs.dox Normal file
View file

@ -0,0 +1,57 @@
/**
@page faq FAQs - Frequently Asked Questions
Frequently asked questions about libinput.
@section faq_fast_mouse My mouse moves too fast, even at the slowest setting
This is a symptom of high-dpi mice (greater than 1000dpi). These devices
need a udev hwdb entry to normalize their motion. See @ref
motion_normalization for a detailed explanation.
@section faq_kinetic_scrolling Kinetic scrolling does not work
The X.Org synaptics driver implemented kinetic scrolling in the driver. It
measures the scroll speed and once the finger leaves the touchpad the driver
keeps sending scroll events for a predetermined time. This effectively
provides for kinetic scrolling without client support but triggers an
unfixable [bug](https://bugs.freedesktop.org/show_bug.cgi?id=38909): the
client cannot know that the events are from a kinetic scroll source. Scroll
events in X are always sent to the current cursor position, a movement of the
cursor after lifting the finger will send the kinetic scroll events to the
new client, something the user does not usually expect. A key event during
the kinetic scroll procedure causes side-effects such as triggering zoom.
libinput does not implement kinetic scrolling for touchpads. Instead it
provides the libinput_event_pointer_get_axis_source() function that enables
callers to implement kinetic scrolling on a per-widget basis, see @ref
scroll_sources.
@section faq_gpl Is libinput GPL-licensed?
No, libinput is MIT licensed. The Linux kernel header file linux/input.h in
libinput's tree is provided to ensure the same behavior regardless of which
kernel version libinput is built on. It does not make libinput GPL-licensed.
@section faq_config_options Where is the configuration stored?
libinput does not store configuration options, it is up to the caller to
manage these and decide which configuration option to apply to each device.
This must be done at startup, after a resume and whenever a new device is
detected.
In a GNOME X.Org stack a user would usually toggle an option in
the gnome-control-center which adjusts a gsettings entry. That change is
picked up by gnome-settings-daemon and applied to the device by adjusting
input device properties that the xf86-input-libinput driver provides.
The input device property changes map to the respective libinput
configuration options.
@dotfile libinput-stack-gnome.gv
This has an effect on the availability of configuration options: if an
option is not exposed by the intermediary, it cannot be configured by the
client. Also some configuration options that are provided by the
intermediary may not be libinput-specific configuration options.
*/

91
doc/gestures.dox Normal file
View file

@ -0,0 +1,91 @@
/**
@page gestures Gestures
libinput supports basic gestures on touchpads and other indirect input
devices. Two types of gestures are supported: @ref gestures_pinch and @ref
gestures_swipe. Support for gestures depends on the hardware device, most
touchpads support both gestures and any device that may send gesture events
has the @ref LIBINPUT_DEVICE_CAP_GESTURE capability set.
Note that libinput **does not** support gestures on touchscreens, see
@ref gestures_touchscreens.
@section gestures_lifetime Lifetime of a gesture
A gesture's lifetime has three distinct stages: begin, update and end, each
with their own event types. Begin is sent when the fingers are first set
down or libinput decides that the gesture begins. For @ref gestures_pinch
this sets the initial scale. Any events changing properties of the gesture
are sent as update events. On termination of the gesture, an end event is
sent.
A gesture includes the finger count (see
libinput_event_gesture_get_finger_count()) and that finger count remains the
same for the lifetime of a gesture. Thus, if a user puts down a fourth
finger during a three-finger swipe gesture, libinput will end
the three-finger gesture and, if applicable, start a four-finger swipe
gesture. A caller may decide that those gestures are semantically identical
and continue the two gestures as one single gesture.
@see LIBINPUT_EVENT_GESTURE_PINCH_BEGIN
@see LIBINPUT_EVENT_GESTURE_PINCH_UPDATE
@see LIBINPUT_EVENT_GESTURE_PINCH_END
@see LIBINPUT_EVENT_GESTURE_PINCH_BEGIN
@see LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE
@see LIBINPUT_EVENT_GESTURE_SWIPE_END
@section gestures_pinch Pinch gestures
Pinch gestures are executed when two or more fingers are located on the
touchpad and are either changing the relative distance to each other
(pinching) or are changing the relative angle (rotate). Pinch gestures may
change both rotation and distance at the same time. For such gestures,
libinput calculates a logical center for the gestures and provides the
caller with the delta x/y coordinates of that center, the relative angle of
the fingers compared to the previous event, and the absolute scale compared
to the initial finger position.
@image html pinch-gestures.svg "The pinch and rotate gestures"
The illustration above shows a basic pinch in the left image and a rotate in
the right angle. Not shown is a movement of the logical center if the
fingers move unevenly. Such a movement is supported by libinput, it is
merely left out of the illustration.
Note that while position and angle is relative to the previous event, the
scale is always absolute and a multiplier of the initial finger position's
scale.
@section gestures_swipe Swipe gestures
Swipe gestures are executed when three or more fingers are moved
synchronously in the same direction. libinput provides x and y coordinates
in the gesture and thus allows swipe gestures in any direction, including
the tracing of complex paths. It is up to the caller to interpret the
gesture into an action or limit a gesture to specific directions only.
@image html swipe-gestures.svg "The swipe gestures"
The illustration above shows a vertical three-finger swipe. The coordinates
provided during the gesture are the movements of the logical center.
@section gestures_touchscreens Touchscreen gestures
Touchscreen gestures are **not** interpreted by libinput. Rather, any touch
point is passed to the caller and any interpretation of gestures is up to
the caller or, eventually, the X or Wayland client.
Interpreting gestures on a touchscreen requires context that libinput does
not have, such as the location of windows and other virtual objects on the
screen as well as the context of those virtual objects:
@image html touchscreen-gestures.svg "Context-sensitivity of touchscreen gestures"
In this example, the finger movements are identical but in the left case
both fingers are located within the same window, thus suggesting an attempt
to zoom. In the right case both fingers are located on a window border,
thus suggesting a window movement. libinput only has knowledge of the finger
coordinates (and even then only in device coordinates, not in screen
coordinates) and thus cannot differentiate the two.
*/

29
doc/libinput.doxygen.in Normal file
View file

@ -0,0 +1,29 @@
PROJECT_NAME = @PACKAGE_NAME@
PROJECT_NUMBER = @PACKAGE_VERSION@
PROJECT_BRIEF = "A wrapper library for input devices"
JAVADOC_AUTOBRIEF = YES
TAB_SIZE = 8
OPTIMIZE_OUTPUT_FOR_C = YES
EXTRACT_ALL = YES
EXTRACT_STATIC = YES
MAX_INITIALIZER_LINES = 0
QUIET = YES
INPUT = @top_srcdir@/src/libinput.h \
@top_srcdir@/README.txt
IMAGE_PATH = @top_srcdir@/doc/svg \
@top_srcdir@/doc/dot
GENERATE_HTML = YES
HTML_TIMESTAMP = YES
USE_MATHJAX = YES
GENERATE_LATEX = NO
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
PREDEFINED = LIBINPUT_ATTRIBUTE_PRINTF(f, \
a)= \
LIBINPUT_ATTRIBUTE_DEPRECATED
DOTFILE_DIRS = @top_srcdir@/doc/dot
HTML_HEADER = @top_srcdir@/doc/style/header.html
HTML_FOOTER = @top_srcdir@/doc/style/footer.html
HTML_EXTRA_STYLESHEET = @top_srcdir@/doc/style/customdoxygen.css \
@top_srcdir@/doc/style/bootstrap.css

View file

@ -1,8 +1,5 @@
.. _motion_normalization:
==============================================================================
Normalization of relative motion
==============================================================================
/**
@page motion_normalization Normalization of relative motion
Most relative input devices generate input in so-called "mickeys". A
mickey is in device-specific units that depend on the resolution
@ -27,20 +24,11 @@ libinput applies a dpi-dependent acceleration function. At low speeds, a
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.
.. _motion_normalization_touchpad:
------------------------------------------------------------------------------
Normalization of touchpad coordinates
------------------------------------------------------------------------------
@section motion_normalization_touchpad Normalization of touchpad coordinates
Touchpads may have a different resolution for the horizontal and vertical
axis. Interpreting coordinates from the touchpad without taking resolution
@ -48,50 +36,45 @@ into account results in uneven motion.
libinput scales unaccelerated touchpad motion to the resolution of the
touchpad's x axis, i.e. the unaccelerated value for the y axis is:
``y = (x / resolution_x) * resolution_y``.
y = (x / resolution_x) * resolution_y
.. _motion_normalization_tablet:
------------------------------------------------------------------------------
Normalization of tablet coordinates
------------------------------------------------------------------------------
See :ref:`tablet-relative-motion`
.. _motion_normalization_customization:
------------------------------------------------------------------------------
Setting custom DPI settings
------------------------------------------------------------------------------
@section motion_normalization_customization Setting custom DPI settings
Devices usually do not advertise their resolution and libinput relies on
the udev property **MOUSE_DPI** for this information. This property is usually
set via the
`udev hwdb <http://cgit.freedesktop.org/systemd/systemd/tree/hwdb/70-mouse.hwdb>`_.
The ``mouse-dpi-tool`` utility provided by
`libevdev <https://freedesktop.org/wiki/Software/libevdev/>`_ should be
the udev property <b>MOUSE_DPI</b> for this information. This property is usually
set via the <a
href="http://cgit.freedesktop.org/systemd/systemd/tree/hwdb/70-mouse.hwdb">udev hwdb</a>.
The "mouse-dpi-tool" utility provided by <a
href="http://freedesktop.org/wiki/Software/libevdev/">libevdev</a> should be
used to measure a device's resolution.
The format of the property for single-resolution mice is: ::
MOUSE_DPI=resolution@frequency
The format of the property for single-resolution mice is:
@code
MOUSE_DPI=resolution@frequency
@endcode
The resolution is in dots per inch, the frequency in Hz.
The format of the property for multi-resolution mice may list multiple
resolutions and frequencies: ::
MOUSE_DPI=r1@f1 *r2@f2 r3@f3
resolutions and frequencies:
@code
MOUSE_DPI=r1@f1 *r2@f2 r3@f3
@endcode
The default frequency must be pre-fixed with an asterisk.
For example, these two properties are valid: ::
For example, these two properties are valid:
@code
MOUSE_DPI=800@125
MOUSE_DPI=400@125 800@125 *1000@500 5500@500
@endcode
MOUSE_DPI=800@125
MOUSE_DPI=400@125 800@125 *1000@500 5500@500
The behavior for a malformed property is undefined.
The behavior for a malformed property is undefined. If the property is
unset, libinput assumes the resolution is 1000dpi.
If the property is unset, libinput assumes the resolution is 1000dpi.
Note that HW does not usually provide information about run-time
resolution changes, libinput will thus not detect when a resolution
changes to the non-default value.
*/

36
doc/page-hierarchy.dox Normal file
View file

@ -0,0 +1,36 @@
/**
@page touchpads Touchpads
- @subpage scrolling
- @subpage clickpad_softbuttons
- @subpage tapping
- @subpage gestures
- @subpage palm_detection
- @subpage t440_support
@page touchscreens Touchscreens
- @subpage absolute_axes
@page pointers Mice, Trackballs, etc.
- @subpage motion_normalization
@page general General setup
- @subpage udev_config
- @subpage seats
@page misc Users
- @subpage faq
- @subpage tools
- @subpage reporting_bugs
@page developers Developers
- @subpage test-suite
- @subpage tools
- @subpage pointer-acceleration
*/

114
doc/palm-detection.dox Normal file
View file

@ -0,0 +1,114 @@
/**
@page palm_detection Palm detection
Palm detection tries to identify accidental touches while typing.
On most laptops typing on the keyboard generates accidental touches on the
touchpad with the palm (usually the area below the thumb). This can lead to
cursor jumps or accidental clicks.
Interference from a palm depends on the size of the touchpad and the position
of the user's hand. Data from touchpads showed that almost all palm events on a
Lenovo T440 happened in the left-most and right-most 5% of the touchpad. The
T440 series has one of the largest touchpads, other touchpads are less
affected by palm touches.
@section palm_exclusion_zones Palm exclusion zones
libinput enables palm detection on the edge of the touchpad. Two exclusion
zones are defined on the left and right edge of the touchpad.
If a touch starts in the exclusion zone, it is considered a palm and the
touch point is ignored. However, for fast cursor movements across the
screen, it is common for a finger to start inside an exclusion zone and move
rapidly across the touchpad. libinput detects such movements and avoids palm
detection on such touch sequences.
Each exclusion zone is divided into a top part and a bottom part. A touch
starting in the top part of the exclusion zone does not trigger a
tap (see @ref tapping).
In the diagram below, the exclusion zones are painted red.
Touch 'A' starts inside the exclusion zone and moves
almost vertically. It is considered a palm and ignored for cursor movement,
despite moving out of the exclusion zone.
Touch 'B' starts inside the exclusion zone but moves horizontally out of the
zone. It is considered a valid touch and controls the cursor.
Touch 'C' occurs in the top part of the exclusion zone. Despite being a
tapping motion, it does not generate an emulated button event. Touch 'D'
likewise occurs within the exclusion zone but in the bottom half. libinput
will generate a button event for this touch.
@image html palm-detection.svg
@section trackpoint-disabling Palm detection during trackpoint use
If a device provides a <a
href="http://en.wikipedia.org/wiki/Pointing_stick">trackpoint</a>, it is
usually located above the touchpad. This increases the likelihood of
accidental touches whenever the trackpoint is used.
libinput disables the touchpad whenever it detects trackpoint activity for a
certain timeout until after trackpoint activity stops. Touches generated
during this timeout will not move the pointer, and touches started during
this timeout will likewise not move the pointer (allowing for a user to rest
the palm on the touchpad while using the trackstick).
If the touchpad is disabled, the @ref t440_support "top software buttons"
remain enabled.
@section disable-while-typing Disable-while-typing
libinput automatically disables the touchpad for a timeout after a key
press, a feature traditionally referred to as "disable while typing" and
previously available through the
[syndaemon(1)](http://linux.die.net/man/1/syndaemon) command. libinput does
not require an external command and the feature is currently enabled for all
touchpads but will be reduced in the future to only apply to touchpads where
finger width or pressure data is unreliable.
Notable behaviors of libinput's disable-while-typing feature:
- Two different timeouts are used, after a single key press the timeout is
short to ensure responsiveness. After multiple key events, the timeout is
longer to avoid accidental pointer manipulation while typing.
- Some keys do not trigger the timeout, specifically some modifier keys
(Ctrl, Alt, Shift, and Fn). Actions such as Ctrl + click thus stay
responsive.
- Touches started while typing do not control the cursor even after typing
has stopped, it is thus possible to rest the palm on the touchpad while
typing.
- Physical buttons work even while the touchpad is disabled. This includes
@ref t440_support "software-emulated buttons".
Disable-while-typing can be enabled and disabled by calling
libinput_device_config_dwt_set_enabled().
@section thumb-detection Thumb detection
Many users rest their thumb on the touchpad while using the index finger to
move the finger around. For clicks, often the thumb is used rather than the
finger. The thumb should otherwise be ignored as a touch, i.e. it should not
count towards @ref clickfinger and it should not cause a single-finger
movement to trigger @ref twofinger_scrolling.
libinput uses two triggers for thumb detection: pressure and
location. A touch exceeding a pressure threshold is considered a thumb if it
is within the thumb detection zone.
@note "Pressure" on touchpads is synonymous with "contact area", a large
touch surface area has a higher pressure and thus hints at a thumb or palm
touching the surface.
Pressure readings are unreliable at the far bottom of the touchpad as 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 resting
thumb.
@image html thumb-detection.svg
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 labelled as
thumb if it remains in that area for a time without moving outside.
*/

View file

@ -0,0 +1,127 @@
/**
@page pointer-acceleration Pointer acceleration
libinput uses device-specific pointer acceleration methods, with the default
being the @ref ptraccel-linear. The methods share common properties, such as
@ref ptraccel-velocity.
This page explains the high-level concepts used in the code. It aims to
provide an overview for developers and is not necessarily useful for
users.
@section ptraccel-profiles Pointer acceleration profiles
The profile decides the general method of pointer acceleration.
libinput currently supports two profiles: "adaptive" and "flat". The aptive
profile is the default profile for all devices and takes the current speed
of the device into account when deciding on acceleration. The flat profile
is simply a constant factor applied to all device deltas, regardless of the
speed of motion (see @ref ptraccel-profile-flat). Most of this document
describes the adaptive pointer acceleration.
@section ptraccel-velocity Velocity calculation
The device's speed of movement is measured across multiple input events
through so-called "trackers". Each event prepends a the tracker item, each
subsequent tracker contains the delta of that item to the current position,
the timestamp of the event that created it and the cardinal direction of the
movement at the time. If a device moves into the same direction, the
velocity is calculated across multiple trackers. For example, if a device
moves steadily for 10 events to the left, the velocity is calculated across
all 10 events.
Whenever the movement changes direction or significantly changes speed, the
velocity is calculated from the direction/speed change only. For example, if
a device moves steadily for 8 events to the left and then 2 events to the
right, the velocity is only that of the last 2 events.
An extra time limit prevents events that are too old to factor into the
velocity calculation. For example, if a device moves steadily for 5 events
to the left, then pauses, then moves again for 5 events to the left, only
the last 5 events are used for velocity calculation.
The velocity is then used to calculate the acceleration factor
@section ptraccel-factor Acceleration factor
The acceleration factor is the final outcome of the pointer acceleration
calculations. It is a unitless factor that is applied to the current delta,
a factor of 2 doubles the delta (i.e. speeds up the movement), a factor of
less than 1 reduces the delta (i.e. slows the movement).
Any factor less than 1 requires the user to move the device further to move
the visible pointer. This is called deceleration and enables high precision
target selection through subpixel movements. libinput's current maximum
deceleration factor is 0.3 (i.e. slow down to 30% of the pointer speed).
A factor higher than 1 moves the pointer further than the physical device
moves. This is acceleration and allows a user to cross the screen quickly
but effectively skips pixels. libinput's current maximum acceleration factor
is 3.5.
@section ptraccel-linear Linear pointer acceleration
The linear pointer acceleration method is the default for most pointer
devices. It provides deceleration at very slow movements, a 1:1 mapping for
regular movements and a linear increase to the maximum acceleration factor
for fast movements.
Linear pointer acceleration applies to devices with above 1000dpi resolution
and after @ref motion_normalization is applied.
@image html ptraccel-linear.svg "Linear pointer acceleration"
The image above shows the linear pointer acceleration settings at various
speeds. The line for 0.0 is the default acceleration curve, speed settings
above 0.0 accelerate sooner, faster and to a higher maximum acceleration.
Speed settings below 0 delay when acceleration kicks in, how soon the
maximum acceleration is reached and the maximum acceleration factor.
Extremely low speed settings provide no acceleration and additionally
decelerate all movement by a constant factor.
@section ptraccel-low-dpi Pointer acceleration for low-dpi devices
Low-dpi devices are those with a physical resolution of less than 1000 dots
per inch (dpi). The pointer acceleration is adjusted to provide roughly the
same feel for all devices at normal to high speeds. At slow speeds, the
pointer acceleration works on device-units rather than normalized
coordinates (see @ref motion_normalization).
@image html ptraccel-low-dpi.svg "Pointer acceleration for low-dpi devices"
The image above shows the default pointer acceleration curve for a speed of
0.0 at different DPI settings. A device with low DPI has the acceleration
applied sooner and with a stronger acceleration factor.
@section ptraccel-touchpad Pointer acceleration on touchpads
Touchpad pointer acceleration uses the @ref ptraccel-linear profile, with a
constant deceleration factor applied. The user expectation of how much a
pointer should move in response to finger movement is different to that of a
mouse device, hence the constant deceleration factor.
@image html ptraccel-touchpad.svg "Pointer acceleration curve for touchpads"
The image above shows the touchpad acceleration profile in comparison to the
@ref ptraccel-linear. The shape of the curve is identical but vertically squashed.
@section ptraccel-trackpoint Pointer acceleration on trackpoints
Trackpoint pointer acceleration uses the @ref ptraccel-low-dpi profile, with a
constant deceleration factor taking the place of the DPI settings.
@image html ptraccel-trackpoint.svg "Pointer acceleration curves for trackpoints"
The image above shows the trackpoint acceleration profile in comparison to the
@ref ptraccel-linear. The constant acceleration factor, usually applied by
udev, shapes the acceleration profile.
@section ptraccel-profile-flat The flat pointer acceleration profile
In a flat profile, the acceleration factor is constant regardless of the
velocity of the pointer and each delta (dx, dy) results in an accelerated delta
(dx * factor, dy * factor). This provides 1:1 movement between the device
and the pointer on-screen.
*/

94
doc/reporting-bugs.dox Normal file
View file

@ -0,0 +1,94 @@
/**
@page reporting_bugs Reporting bugs
A new bug can be filed here:
https://bugs.freedesktop.org/enter_bug.cgi?product=Wayland&component=libinput
When reporting bugs against libinput, please follow the instructions below
and provide the required data. This will speed up triage, resulting in a
quicker bugfix.
First, try to identify the bug by reproducing it reliably. The more
specific a bug description is, the easier it is to fix. The @ref
libinput-debug-events helper tool can help identify whether the bug is in
libinput at all. This tool is a direct hook to libinput without a desktop
stack in between and can thus help to identify whether a bug is in libinput
or in one of the higher layers. See the @ref libinput-debug-events section
for information on this tool.
@section triage Required information for triage
When you file a bug, please attach the following information:
- a virtual description of your input device, see @ref evemu. This is the
most important piece of information, do not forget it!
- the libinput version. Either the package version from your distribution
or, when running from git: <tt>git log -n 1 HEAD</tt> or <tt>git describe
HEAD</tt>. As a last resort: <tt>libinput-list-devices --version</tt>.
- the current libinput settings for the device. This is a bit harder to
obtain, for now we'll assume you are running X11. The current settings can
be obtained with <tt>xinput list-props "your device name"</tt>. Use
<tt>xinput list</tt> to obtain the device name.
- if the device is a touchpad or a pointing stick, the vendor model number
of your laptop, and the content of <tt>/sys/class/dmi/id/modalias</tt>.
- if the device is a touchpad, the physical dimensions of your touchpad in
mm
@section evemu Recording devices with evemu
<a href="http://www.freedesktop.org/wiki/Evemu/">evemu</a> records the
device capabilities together with the event stream from the kernel. On our
side, this allows us to recreate a virtual device identical to your device
and re-play the event sequence, hopefully triggering the same bug.
evemu-record takes a <tt>/dev/input/eventX</tt> event node, but without arguments
it will simply show the list of devices and let you select:
@code
$ sudo evemu-record > scroll.evemu
Available devices:
/dev/input/event0: Lid Switch
/dev/input/event1: Sleep Button
/dev/input/event2: Power Button
/dev/input/event3: AT Translated Set 2 keyboard
/dev/input/event4: SynPS/2 Synaptics TouchPad
/dev/input/event5: Video Bus
/dev/input/event6: ELAN Touchscreen
/dev/input/event10: ThinkPad Extra Buttons
/dev/input/event11: HDA Intel HDMI HDMI/DP,pcm=3
/dev/input/event12: HDA Intel HDMI HDMI/DP,pcm=7
/dev/input/event13: HDA Intel HDMI HDMI/DP,pcm=8
/dev/input/event14: HDA Intel PCH Dock Mic
/dev/input/event15: HDA Intel PCH Mic
/dev/input/event16: HDA Intel PCH Dock Headphone
/dev/input/event17: HDA Intel PCH Headphone
/dev/input/event18: Integrated Camera
/dev/input/event19: TPPS/2 IBM TrackPoint
Select the device event number [0-19]:
@endcode
Select the device that triggers the issue, then reproduce the bug and Ctrl+C
the process. The resulting recording, ("scroll.evemu" in this example) will
contain the sequence required to reproduce the bug. If the bug fails to
reproduce during recording, simply Ctrl+C and restart evemu-record.
Always start the recording from a neutral state, i.e. without any buttons or
keys down, with the position of the device in the neutral position, without
touching the screen/touchpad.
@note The longer the recording, the harder it is to identify the event
sequence triggering the bug. Please keep the event sequence as short as possible.
To verify that the recording contains the bug, you can replay it on your
device. For example, to replay the sequence recorded in the example above:
@code
$ sudo evemu-play /dev/input/event4 < scroll.evemu
@endcode
If the bug is triggered by replaying on your device, attach the recording to
the bug report.
@note libinput does not affect the evemu recording. libinput and evemu talk
directly to the kernel's device nodes. An evemu recording is not influenced
by the libinput version or whether a libinput context is currently active.
@dotfile evemu.gv
*/

106
doc/scrolling.dox Normal file
View file

@ -0,0 +1,106 @@
/**
@page scrolling Scrolling
libinput supports three different types of scrolling methods: @ref
twofinger_scrolling, @ref edge_scrolling and @ref button_scrolling. Some
devices support multiple methods, though only one can be enabled at a time.
As a general overview:
- touchpad devices with physical buttons below the touchpad support edge and
two-finger scrolling
- touchpad devices without physical buttons (@ref clickpad_softbuttons
"clickpads") support two-finger scrolling only
- pointing sticks provide on-button scrolling by default
- mice and other pointing devices support on-button scrolling but it is not
enabled by default
A device may differ from the above based on its capabilities. See
libinput_device_config_scroll_set_method() for documentation on how to
switch methods and libinput_device_config_scroll_get_methods() for
documentation on how to query a device for available scroll methods.
@section horizontal_scrolling Horizontal scrolling
Scroll movements provide vertical and horizontal directions, each
scroll event contains both directions where applicable, see
libinput_event_pointer_get_axis_value(). libinput does not provide separate
toggles to enable or disable horizontal scrolling. Instead, horizontal
scrolling is always enabled. This is intentional, libinput does not have
enough context to know when horizontal scrolling is appropriate for a given
widget. The task of filtering horizontal movements is up to the caller.
@section twofinger_scrolling Two-finger scrolling
The default on two-finger capable touchpads (almost all modern touchpads are
capable of detecting two fingers). Scrolling is triggered by two fingers
being placed on the surface of the touchpad, then moving those fingers
vertically or horizontally.
@image html twofinger-scrolling.svg "Vertical and horizontal two-finger scrolling"
For scrolling to trigger, a built-in distance threshold has to be met but once
engaged any movement will scroll. In other words, to start scrolling a
sufficiently large movement is required, once scrolling tiny amounts of
movements will translate into tiny scroll movements.
Scrolling in both directions at once is possible by meeting the required
distance thresholds to enable each direction separately.
Two-finger scrolling requires the touchpad to track both touch points with
reasonable precision. Unfortunately, some so-called "semi-mt" touchpads can
only track the bounding box of the two fingers rather than the actual
position of each finger. In addition, that bounding box usually suffers from
a low resolution, causing jumpy movement during two-finger scrolling.
libinput does not provide two-finger scrolling on those touchpads.
@section edge_scrolling Edge scrolling
On some touchpads, edge scrolling is available, triggered by moving a single
finger along the right edge (vertical scroll) or bottom edge (horizontal
scroll).
@image html edge-scrolling.svg "Vertical and horizontal edge scrolling"
Due to the layout of the edges, diagonal scrolling is not possible. The
behavior of edge scrolling using both edges at the same time is undefined.
Edge scrolling overlaps with @ref clickpad_softbuttons. A physical click on
a clickpad ends scrolling.
@section button_scrolling On-Button scrolling
On-button scrolling converts the motion of a device into scroll events while
a designated button is held down. For example, Lenovo devices provide a
<a href="http://en.wikipedia.org/wiki/Pointing_stick">pointing stick</a> that emulates
scroll events when the trackstick's middle mouse button is held down.
@note On-button scrolling is enabled by default for pointing sticks. This
prevents middle-button dragging; all motion events while the middle button is
down are converted to scroll events.
@image html button-scrolling.svg "Button scrolling"
The button may be changed with
libinput_device_config_scroll_set_button() but must be on the same device as
the motion events. Cross-device scrolling is not supported but
for one exception: libinput's @ref t440_support enables the use of the middle
button for button scrolling (even when the touchpad is disabled).
@section scroll_sources Scroll sources
libinput provides a pointer axis *source* for each scroll event. The
source can be obtained with the libinput_event_pointer_get_axis_source()
function and is one of **wheel**, **finger**, or **continuous**. The source
information lets a caller decide when to implement kinetic scrolling.
Usually, a caller will process events of source wheel as they come in.
For events of source finger a caller should calculate the velocity of the
scroll motion and upon finger release start a kinetic scrolling motion (i.e.
continue executing a scroll according to some friction factor).
libinput expects the caller to be in charge of widget handling, the source
information is thus enough to provide kinetic scrolling on a per-widget
basis. A caller should cancel kinetic scrolling when the pointer leaves the
current widget or when a key is pressed.
See the libinput_event_pointer_get_axis_source() for details on the
behavior of each scroll source.
See also http://who-t.blogspot.com.au/2015/03/libinput-scroll-sources.html
*/

View file

@ -1,8 +1,5 @@
.. _seats:
==============================================================================
Seats
==============================================================================
/**
@page seats Seats
Each device in libinput is assigned to one seat.
A seat has two identifiers, the physical name and the logical name. The
@ -13,15 +10,11 @@ seats as independent device sets. Alternatively, a compositor may limit
itself to a single logical seat, leaving a second compositor to manage
devices on the other logical seats.
.. _seats_overview:
------------------------------------------------------------------------------
Overview
------------------------------------------------------------------------------
@section Overview
Below is an illustration of how physical seats and logical seats interact:
.. graphviz:: seats-sketch.gv
@dotfile seats-sketch.gv
The devices "Foo", "Bar" and "Spam" share the same physical seat and are
thus available in the same libinput context. Only "Foo" and "Bar" share the
@ -29,19 +22,15 @@ same logical seat. The device "Egg" is not available in the libinput context
associated with the physical seat 0.
The above graph is for illustration purposes only. In libinput, a struct
**libinput_seat** comprises both physical seat and logical seat. From a
@ref libinput_seat comprises both physical seat and logical seat. From a
caller's point-of-view the above device layout is presented as:
.. graphviz:: seats-sketch-libinput.gv
@dotfile seats-sketch-libinput.gv
Thus, devices "Foo" and "Bar" both reference the same struct
**libinput_seat**, all other devices reference their own respective seats.
Thus, devices "Foo" and "Bar" both reference the same struct @ref
libinput_seat, all other devices reference their own respective seats.
.. _seats_and_features:
------------------------------------------------------------------------------
The effect of seat assignment
------------------------------------------------------------------------------
@section seats_and_features The effect of seat assignment
A logical set is interpreted as a group of devices that usually belong to a
single user that interacts with a computer. Thus, the devices are
@ -59,27 +48,26 @@ semantically related. This means for devices within the same logical seat:
two touches down.
libinput provides functions to aid with the above:
**libinput_event_pointer_get_seat_button_count()**,
**libinput_event_keyboard_get_seat_key_count()**, and
**libinput_event_touch_get_seat_slot()**.
libinput_event_pointer_get_seat_button_count(),
libinput_event_keyboard_get_seat_key_count(), and
libinput_event_touch_get_seat_slot().
Internally, libinput counts devices within the same logical seat as related.
Cross-device features only activate if all required devices are in the same
logical seat. For example, libinput will only activate the top software
buttons (see :ref:`t440_support`) if both trackstick and touchpad are assigned
buttons (see @ref t440_support) if both trackstick and touchpad are assigned
to the same logical seat.
.. _changing_seats:
------------------------------------------------------------------------------
Changing seats
------------------------------------------------------------------------------
@section changing_seats Changing seats
A device may change the logical seat it is assigned to at runtime with
**libinput_device_set_seat_logical_name()**. The physical seat is immutable and
libinput_device_set_seat_logical_name(). The physical seat is immutable and
may not be changed.
Changing the logical seat for a device is equivalent to unplugging the
device and plugging it back in with the new logical seat. No device state
carries over across a logical seat change.
*/

View file

@ -252,3 +252,4 @@ blockquote {
margin: 0 24px 0 4px;
padding: 0 12px 0 16px;
}

View file

@ -8,7 +8,7 @@
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="generator" content="Doxygen $doxygenversion"/>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
@ -20,6 +20,8 @@
$mathjax
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
$extrastylesheet
<link href="bootstrap.css" rel="stylesheet" type="text/css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<script type="text/javascript" src="doxy-boot.js"></script>
</head>

View file

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View file

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View file

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View file

Before

Width:  |  Height:  |  Size: 7 KiB

After

Width:  |  Height:  |  Size: 7 KiB

View file

@ -36,17 +36,16 @@
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1016"
inkscape:window-height="1136"
id="namedview3477"
showgrid="false"
inkscape:zoom="3.5662625"
inkscape:cx="180.54059"
inkscape:cy="269.48563"
inkscape:cx="199.35048"
inkscape:cy="156.74673"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg2"
inkscape:document-rotation="0" />
inkscape:current-layer="svg2" />
<defs
id="defs4">
<marker
@ -138,8 +137,16 @@
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:6, 1;stroke-dashoffset:0;stroke-opacity:1;marker-mid:none;marker-end:url(#Arrow1Lend-2)"
id="path13492"
d="m 38.928571,67.914286 c 0,0 3.508205,24.810617 9.642857,57.857144 6.134651,33.04652 23.277202,79.68584 89.642852,90.35714" />
<rect
style="fill:#000000;fill-opacity:0.3559322;fill-rule:evenodd;stroke:none;stroke-width:3.30527353px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3490"
width="65.272476"
height="136.21509"
x="7.0411549"
y="7.0411549" />
<text
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:0%;font-family:Utopia;-inkscape-font-specification:Utopia;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
sodipodi:linespacing="100%"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:100%;font-family:Utopia;-inkscape-font-specification:Utopia;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
xml:space="preserve"
id="text13874"
y="63.628628"
@ -148,8 +155,16 @@
id="tspan13876"
y="63.628628"
x="33.214291">A</tspan></text>
<rect
style="fill:#000000;fill-opacity:0.3559322;fill-rule:evenodd;stroke:none;stroke-width:3.30527353px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3490-2"
width="65.272476"
height="136.21509"
x="321.23563"
y="6.7607527" />
<text
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:0%;font-family:Utopia;-inkscape-font-specification:Utopia;text-align:start;writing-mode:lr-tb;text-anchor:start;display:inline;fill:#000000;fill-opacity:1;stroke:none"
sodipodi:linespacing="100%"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:100%;font-family:Utopia;-inkscape-font-specification:Utopia;text-align:start;writing-mode:lr-tb;text-anchor:start;display:inline;fill:#000000;fill-opacity:1;stroke:none"
xml:space="preserve"
id="text13874-8"
y="98.748993"
@ -168,7 +183,8 @@
id="layer1"
style="display:inline" />
<text
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:0%;font-family:Utopia;-inkscape-font-specification:Utopia;text-align:start;writing-mode:lr-tb;text-anchor:start;display:inline;fill:#000000;fill-opacity:1;stroke:none"
sodipodi:linespacing="100%"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:100%;font-family:Utopia;-inkscape-font-specification:Utopia;text-align:start;writing-mode:lr-tb;text-anchor:start;display:inline;fill:#000000;fill-opacity:1;stroke:none"
xml:space="preserve"
id="text13874-8-1"
y="46.009491"
@ -177,6 +193,17 @@
id="tspan13876-7-9"
y="46.009491"
x="342.27759">C</tspan></text>
<text
sodipodi:linespacing="100%"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:100%;font-family:Utopia;-inkscape-font-specification:Utopia;text-align:start;writing-mode:lr-tb;text-anchor:start;display:inline;fill:#000000;fill-opacity:1;stroke:none"
xml:space="preserve"
id="text13874-8-1-4"
y="215.65927"
x="37.970726"><tspan
style="font-size:18px;font-family:Arial;-inkscape-font-specification:Arial"
id="tspan13876-7-9-5"
y="215.65927"
x="37.970726">D</tspan></text>
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1"
id="path4401"
@ -184,18 +211,11 @@
cy="24.53549"
r="4.0658817"
transform="scale(-1,1)" />
<rect
width="248.87633"
height="6.8111157"
x="72.35215"
y="7.1355872"
id="rect4355"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ff0000;fill-opacity:0.32017547;fill-rule:nonzero;stroke:none;stroke-width:1.11822701;marker:none;enable-background:accumulate" />
<rect
y="7.1355872"
x="72.35215"
height="6.8111153"
width="248.87634"
id="rect4353"
style="fill:#000000;fill-opacity:0.3559322;fill-rule:evenodd;stroke:none;stroke-width:1.44321382px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1"
id="path4401-9"
cx="-36.452721"
cy="194.8819"
r="4.0658817"
transform="scale(-1,1)" />
</svg>

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View file

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

5486
doc/svg/ptraccel-linear.svg Normal file

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 550 KiB

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
<svg
width="600" height="480"
viewBox="0 0 600 480"
xmlns="http://www.w3.org/2000/svg"
@ -3745,3 +3745,4 @@
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 377 KiB

After

Width:  |  Height:  |  Size: 377 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 171 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 371 KiB

View file

@ -41,8 +41,8 @@
id="namedview4312"
showgrid="false"
inkscape:zoom="0.57798581"
inkscape:cx="842.57758"
inkscape:cy="-74.644166"
inkscape:cx="1134.9723"
inkscape:cy="-71.183873"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
@ -106,7 +106,7 @@
id="rect2858-7"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.19376326;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" />
<g
transform="matrix(0.79657897,0.11742288,-0.14814182,0.631399,749.8966,-336.99044)"
transform="matrix(0.79657897,0.11742288,-0.14814182,0.631399,665.11943,-345.64117)"
id="g3663-9-8">
<path
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
@ -124,6 +124,30 @@
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.92000002;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;enable-background:accumulate"
inkscape:connector-curvature="0" />
</g>
<g
id="g4656"
transform="translate(-0.31997204,0.28487182)">
<g
id="g4639">
<path
inkscape:connector-curvature="0"
style="fill:none;stroke:#000000;stroke-width:0.72135597px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path2820-0-5"
d="m 970.15914,263.93369 32.58666,-97.47985 c 0,0 12.2603,-46.32869 38.5506,-33.925 20.7457,9.78778 17.4301,24.72594 16.4399,28.75425 -10.1846,41.43257 -30.105,105.84033 -30.105,105.84033 l -0.428,-0.37827 z"
sodipodi:nodetypes="ccssccc" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.00144271;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
id="path2824-9-3"
d="m 987.16367,214.84092 c 8.97014,-26.84686 16.75933,-50.19953 17.30923,-51.89481 3.8651,-11.91483 10.3862,-22.76212 16.5622,-27.54951 6.8496,-5.30946 13.8243,-5.75615 21.9108,-1.40323 3.7999,2.04543 6.0302,3.61208 8.2265,5.77836 2.5214,2.487 3.6881,4.17002 5.1008,7.35828 1.3655,3.08181 1.9391,7.11725 1.5051,10.58923 -0.597,4.77663 -10.2821,40.41668 -20.9931,77.25236 -7.7256,26.56907 -9.371,31.11182 -9.5644,31.10964 -0.1479,-0.002 -55.70067,-1.83937 -56.08626,-2.18017 -0.16723,-0.1478 6.29681,-19.93218 16.02913,-49.06015 z"
sodipodi:nodetypes="scsssscsccs" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.92000002;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;enable-background:accumulate"
id="path2824-7-8-8"
d="m 1008.3595,164.57667 c 3.8651,-11.91483 7.6606,-19.35039 13.8366,-24.13778 6.8495,-5.30946 12.0833,-5.57765 20.1698,-1.22474 9.3061,4.73331 12.9905,9.62271 11.9094,19.03362 -6.3459,19.3209 -6.9054,22.12042 -9.2168,26.32727 -0.1479,-0.002 -33.6651,-14.70742 -35.0296,-15.23839 -1.4035,-0.54616 -1.8884,-3.70289 -1.6694,-4.75998 z" />
</g>
</g>
<g
transform="translate(-386.56163,2.2570367)"
id="g4656-3">

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View file

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View file

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View file

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View file

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View file

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -1,43 +1,29 @@
.. _t440_support:
/**
@page t440_support Lenovo *40 series touchpad support
==============================================================================
Lenovo \*40 series touchpad support
==============================================================================
The Lenovo \*40 series emulates trackstick buttons on the top part of the
The Lenovo *40 series emulates trackstick buttons on the top part of the
touchpads.
.. _t440_support_overview:
@section t440_support_overview Overview
------------------------------------------------------------------------------
Overview
------------------------------------------------------------------------------
The Lenovo \*40 series introduced a new type of touchpad. Previously, all
The Lenovo *40 series introduced a new type of touchpad. Previously, all
laptops had a separate set of physical buttons for the
`trackstick <http://en.wikipedia.org/wiki/Pointing_stick>`_. This
<a href="http://en.wikipedia.org/wiki/Pointing_stick">trackstick</a>. This
series removed these buttons, relying on a software emulation of the top
section of the touchpad. This is visually marked on the trackpad itself,
and clicks can be triggered by pressing the touchpad down with a finger in
the respective area:
.. figure:: top-software-buttons.svg
:align: center
Left, right and middle-button click with top software button areas
@image html top-software-buttons.svg "Left, right and middle-button click with top software button areas"
This page only covers the top software buttons, the bottom button behavior
is covered in :ref:`Clickpad software buttons <clickpad_softbuttons>`.
is covered in @ref clickpad_softbuttons "Clickpad software buttons".
Clickpads with a top button area are marked with the
`INPUT_PROP_TOPBUTTONPAD <https://www.kernel.org/doc/Documentation/input/event-codes.txt>`_
Clickpads with a top button area are marked with the <a
href="https://www.kernel.org/doc/Documentation/input/event-codes.txt">INPUT_PROP_TOPBUTTONPAD</a>
property.
.. _t440_support_btn_size:
------------------------------------------------------------------------------
Size of the buttons
------------------------------------------------------------------------------
@section t440_support_btn_size Size of the buttons
The size of the buttons matches the visual markings on this touchpad.
The width of the left and right buttons is approximately 42% of the
@ -49,23 +35,16 @@ measurements of button presses showed that the size of the buttons needs to
be approximately 10mm high to work reliable (especially when using the
thumb to press the button).
.. _t440_support_btn_behavior:
------------------------------------------------------------------------------
Button behavior
------------------------------------------------------------------------------
@section t440_support_btn_behavior Button behavior
Movement in the top button area does not generate pointer movement. These
buttons are not replacement buttons for the bottom button area but have
their own behavior. Semantically attached to the trackstick device, libinput
re-routes events from these buttons to appear through the trackstick device.
.. graphviz::
digraph top_button_routing
{
@dot
digraph top_button_routing
{
rankdir="LR";
node [shape="box";]
@ -91,12 +70,12 @@ re-routes events from these buttons to appear through the trackstick device.
touchpad -> libinput_tp [color="red4"]
events_tp [label="other touchpad events"];
events_topbutton [label="top software button events"];
events_topbutton [label="top sofware button events"];
libinput_tp -> events_tp [arrowhead="none"]
libinput_ts -> events_topbutton [color="red4"]
}
}
@enddot
The top button areas work even if the touchpad is disabled but will be
@ -106,23 +85,20 @@ and must be lifted to generate future buttons. Likewise, movement into the
top button area does not trigger button events, a click has to start inside
this area to take effect.
.. _t440_support_identification:
------------------------------------------------------------------------------
Kernel support
------------------------------------------------------------------------------
@section t440_support_identification Kernel support
The firmware on the first generation of touchpads providing top software
buttons is buggy and announces wrong ranges.
`Kernel patches <https://lkml.org/lkml/2014/3/7/722>`_ are required;
<a href="https://lkml.org/lkml/2014/3/7/722">Kernel patches</a> are required;
these fixes are available in kernels 3.14.1, 3.15 and later but each
touchpad needs a separate fix.
The October 2014 refresh of these laptops do not have this firmware bug
anymore and should work without per-device patches, though
`this kernel commit <http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=02e07492cdfae9c86e3bd21c0beec88dbcc1e9e8>`_
is required.
<a href="http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=02e07492cdfae9c86e3bd21c0beec88dbcc1e9e8">this kernel commit</a> is required.
For a complete list of supported touchpads check
`the kernel source <http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/input/mouse/synaptics.c>`_
(search for "topbuttonpad_pnp_ids").
For a complete list of supported touchpads check <a
href="http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/input/mouse/synaptics.c">the
kernel source</a> (search for "topbuttonpad_pnp_ids").
*/

66
doc/tapping.dox Normal file
View file

@ -0,0 +1,66 @@
/**
@page tapping Tap-to-click behaviour
"Tapping" or "tap-to-click" is the name given to the behavior where a short
finger touch down/up sequence maps into a button click. This is most
commonly used on touchpads, but may be available on other devices.
libinput implements tapping for one, two, and three fingers, where supported
by the hardware, and maps those taps into a left, right, and middle button
click, respectively. Not all devices support three fingers, libinput will
support tapping up to whatever is supported by the hardware. libinput does
not support four-finger taps or any tapping with more than four fingers,
even though some hardware can distinguish between that many fingers.
Tapping is **disabled** by default, see [this
commit](http://cgit.freedesktop.org/wayland/libinput/commit/?id=2219c12c3aa45b80f235e761e87c17fb9ec70eae)
because:
- if you don't know that tapping is a thing (or enabled by default), you get
spurious button events that make the desktop feel buggy.
- if you do know what tapping is and you want it, you usually know where to
enable it, or at least you can search for it.
Tapping can be enabled on a per-device basis. See
libinput_device_config_tap_set_enabled() for details.
@section tapndrag Tap-and-drag
libinput also supports "tap-and-drag" where a tap immediately followed by a
finger down and that finger being held down emulates a button press. Moving
the finger around can thus drag the selected item on the screen.
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
within a implementation-specific timeout. Drag lock can be enabled and
disabled with libinput_device_config_tap_set_drag_lock_enabled().
@image html tap-n-drag.svg "Tap-and-drag process"
The above diagram explains the process, a tap (a) followed by a finger held
down (b) starts the drag process and logically holds the left mouse button
down. A movement of the finger (c) will drag the selected item until the
finger is released (e). If needed and drag lock is enabled, the finger's
position can be reset by lifting and quickly setting it down again on the
touchpad (d). This will be interpreted as continuing move and is especially
useful on small touchpads or with slow pointer acceleration.
If drag lock is enabled, the release of the mouse buttons after the finger
release (e) is triggered by a timeout. To release the button immediately,
simply tap again (f).
If two fingers are supported by the hardware, a second finger can be used to
drag while the first is held in-place.
@section tap_constraints Constraints while tapping
A couple of constraints apply to the contact to be converted into a press, the most common ones are:
- the touch down and touch up must happen within an implementation-defined timeout
- if a finger moves more than an implementation-defined distance while in contact, it's not a tap
- tapping within @ref clickpad_softbuttons "clickpad software buttons" may not trigger an event
- a tap not meeting required pressure thresholds can be ignored as accidental touch
- a tap exceeding certain pressure thresholds can be ignored (see @ref
palm_detection)
- a tap on the edges of the touchpad can usually be ignored (see @ref
palm_detection)
*/

92
doc/test-suite.dox Normal file
View file

@ -0,0 +1,92 @@
/**
@page test-suite libinput test suite
The libinput test suite is based on
[Check](http://check.sourceforge.net/doc/check_html/) and runs automatically
during `make check`. Check itself is wrapped into a libinput-specific test
suite called *litest*. Tests are found in `$srcdir/test/`, the test binaries are
prefixed with `test-` and can be run individually.
@section test-config X.Org config to avoid interference
uinput devices created by the test suite are usually recognised by X as
input devices. All events sent through these devices will generate X events
and interfere with your desktop.
Copy the file `$srcdir/test/50-litest.conf` into your `/etc/X11/xorg.conf.d`
and restart X. This will ignore any litest devices and thus not interfere
with your desktop.
@section test-root 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.
<b>This usually requires the tests to be run as root</b>.
@section test-filtering Selective running of tests
litest's tests are grouped by test groups and devices. A test group is e.g.
"touchpad:tap" and incorporates all tapping-related tests for touchpads.
Each test function is (usually) run with one or more specific devices.
The `--list` commandline argument shows the list of suites and tests.
@code
$ ./test/test-device --list
device:wheel:
wheel only
blackwidow
device:invalid devices:
no device
device:group:
no device
logitech trackball
MS surface cover
mouse_roccat
wheel only
blackwidow
...
@endcode
In the above example, the "device:wheel" suite is run for the "wheel only" and
the "blackwidow" device. Both devices are automatically instantiated through
uinput by litest. The "no device" entry signals that litest does not
instantiate a uinput device for a specific test (though the test itself may
instantiate one).
The `--filter-test` argument enables selective running of tests through
basic shell-style function name matching. For example:
@code
$ ./test/test-touchpad --filter-test="*1fg_tap*"
@endcode
The `--filter-device` argument enables selective running of tests through
basic shell-style device name matching. The device names matched are the
litest-specific shortnames, see the output of `--list`. For example:
@code
$ ./test/test-touchpad --filter-device="synaptics*"
@endcode
The `--filter-group` argument enables selective running of test groups
through basic shell-style test group matching. The test groups matched are
litest-specific test groups, see the output of `--list`. For example:
@code
$ ./test/test-touchpad --filter-group="touchpad:*hover*"
@endcode
The `--filter-device` and `--filter-group` arguments can be combined with
`--list` to show which groups and devices will be affected.
@section test-verbosity Controlling test output
Each test supports the `--verbose` commandline option to enable debugging
output, see libinput_log_set_priority() for details. The `LITEST_VERBOSE`
environment variable, if set, also enables verbose mode.
@code
$ ./test/test-device --verbose
$ LITEST_VERBOSE=1 make check
@endcode
*/

102
doc/tools.dox Normal file
View file

@ -0,0 +1,102 @@
/**
@page tools Helper tools
libinput provides a couple of tools to query state and events. Two of these
tools are usually installed, others are @ref developer_tools only.
@section user_tools User tools
libinput ships with two tools to gather information about devices:
@ref libinput-list-devices and @ref libinput-debug-events. Both tools must
be run as root to have access to the kernel's @c /dev/input/event* device
files.
@subsection libinput-list-devices
The libinput-list-devices tool shows information about devices recognized by
libinput and can help identifying why a device behaves different than
expected. For example, if a device does not show up in the output, it is not
a supported input device.
@verbatim
$ sudo libinput-list-devices
[...]
Device: SynPS/2 Synaptics TouchPad
Kernel: /dev/input/event4
Group: 9
Seat: seat0, default
Size: 97.33x66.86mm
Capabilities: pointer
Tap-to-click: disabled
Tap drag lock: disabled
Left-handed: disabled
Nat.scrolling: disabled
Middle emulation: n/a
Calibration: n/a
Scroll methods: *two-finger
Click methods: *button-areas clickfinger
[...]
@endverbatim
The above listing shows example output for a touchpad. The
libinput-list-devices tool lists general information about the device (the
kernel event node) but also the configuration options. If an option is
"n/a" it does not exist on this device. Otherwise, the tool will show the
default configuration for this device, for options that have more than a
binary state all available options are listed, with the default one prefixed
with an asterisk (*). In the example above, the default click method is
button-areas but clickinger is available.
Note that the default configuration may differ from the configuration
applied by the desktop environment.
@note This tool is intended to be human-readable and may change its output
at any time.
@subsection libinput-debug-events
This is an installed version of the @ref event-debug developer tool. It
prints events from devices and can help to identify why a device behaves
different than expected.
@verbatim
$ sudo libinput-debug-events --enable-tapping --set-click-method=clickfinger
@endverbatim
See the man page or the @c --help output for information about the available
options.
@section developer_tools Developer tools
The two most common tools used by developers are @ref event-debug and @ref
event-gui.
@subsection event-debug
This is the in-tree version of the @ref libinput-debug-events tool and is
linked to allow for easy debugging (i.e. it avoids libtool shenanigans). The
code is the same. For debugging, run it against a single device only and
enable the --verbose flag. This will print the various state machine
transitions in addition to the events.
@verbatim
$ sudo ./tools/event-debug --verbose --device /dev/input/event3
@endverbatim
See the @c --help output for information about the available options.
@subsection event-gui
A simple GTK-based graphical tool that shows the behavior and location of
touch events, pointer motion, scroll axes and gestures. Since this tool
gathers data directly from libinput, it is thus suitable for
pointer-acceleration testing.
@verbatim
$ sudo ./tools/event-gui
@endverbatim
See the @c --help output for information about the available options.
@note The @c --grab flag puts an exclusive @c EVIOCGRAB on the device to
avoid interference with the desktop while testing.
*/

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 147 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 181 KiB

After

Width:  |  Height:  |  Size: 134 KiB

162
doc/touchpads.dox Normal file
View file

@ -0,0 +1,162 @@
/**
@page touchpads Touchpads
This page provides an outline of touchpad devices. Touchpads aren't simply
categorised into a single type, instead they have a set of properties, a
combination of number of physical buttons, multitouch support abilities and
other properties.
@section touchpads_buttons Number of buttons
@subsection touchapds_buttons_phys Physically separate buttons
Touchpads with physical buttons usually provide two buttons, left and right.
A few touchpads with three buttons exist, and Apple used to have touchpads
with a single physical buttons until ca 2008. Touchpads with only two
buttons require the software stack to emulate a middle button. libinput does
this when both buttons are pressed simultaneously.
Note that many Lenovo laptops provide a pointing stick above the touchpad.
This pointing stick has a set of physical buttons just above the touchpad.
While many users use those as substitute touchpad buttons, they logically
belong to the pointing stick. The *40 and *50 series are an exception here,
the former had no physical buttons on the touchpad and required the top
section of the pad to emulate pointing stick buttons, the *50 series has
physical buttons but they are wired to the touchpads. The kernel re-routes
those buttons through the trackstick device. See @ref t440_support for more
information.
@subsection touchpads_buttons_clickpads Clickpads
Clickpads are the most common type of touchpads these days. A Clickpad has
no separate physical buttons, instead the touchpad itself is clickable as a
whole, i.e. a user presses down on the touch area and triggers a physical
click. Clickpads thus only provide a single button, everything else needs to
be software-emulated. See @ref clickpad_softbuttons for more information.
Clickpads are labelled by the kernel with the @c INPUT_PROP_BUTTONPAD input
property.
@subsection touchpads_buttons_forcepads Forcepads
Forcepads are Clickpads without a physical button underneath the hardware.
They provide pressure and may have a vibration element that is
software-controlled. This element can simulate the feel of a physical
click or be co-opted for other tasks.
@section touchpads_touch Touch capabilities
Virtually all touchpads available now can <b>detect</b> multiple fingers on
the touchpad, i.e. provide information on how many fingers are on the
touchpad. The touch capabilities described here specify how many fingers a
device can <b>track</b>, i.e. provide reliable positional information for.
In the kernel each finger is tracked in a so-called "slot", the number of
slots thus equals the number of simultaneous touches a device can track.
@subsection touchapds_touch_st Single-touch touchpads
Single-finger touchpads can track a single touchpoint. Most single-touch
touchpads can also detect three fingers on the touchpad, but no positional
information is provided for those. In libinput, these touches are termed
"fake touches". The kernel sends @c BTN_TOOL_DOUBLETAP, @c
BTN_TOOL_TRIPLETAP, @c BTN_TOOL_QUADTAP and @c BTN_TOOL_QUINTTAP events when
multiple fingers are detected.
@subsection touchpads_touch_mt Pure multi-touch touchpads
Pure multi-touch touchpads are those that can track, i.e. identify the
location of all fingers on the touchpad. Apple's touchpads support 16
touches, others support 5 touches like the Synaptics touchpads when using
SMBus.
These touchpads usually also provide extra information. Apple touchpads
provide an ellipse and the orientation of the ellipse for each touch point.
Other touchpads provide a pressure value for each touch point (see @ref
touchpads_pressure_handling).
Note that the kernel sends @c BTN_TOOL_DOUBLETAP, @c
BTN_TOOL_TRIPLETAP, @c BTN_TOOL_QUADTAP and @c BTN_TOOL_QUINTTAP events for
all touches for backwards compatibility. libinput ignores these events if
the touchpad can track touches correctly.
@subsection touchpads_touch_partial_mt Partial multi-touch touchpads
The vast majority of touchpads fall into this category, the half-way
point between single-touch and pure multi-touch. These devices can track N
fingers, but detect more than N. For example, when using the serial
protocol, Synaptics touchpads can track two fingers but may detect up to
five.
The number of slots may limit which features are available in libinput.
Any device with two slots can support two-finger scrolling, but @ref
thumb-detection or @ref palm_detection may be limited if only two slots are
available.
@subsection touchpads_touch_semi_mt Semi-mt touchpads
A sub-class of partial multi-touch touchpads. These touchpads can
technically detect two fingers but the location of both is limited to the
bounding box, i.e. the first touch is always the top-left one and the second
touch is the bottom-right one. Coordinates jump around as fingers move past
each other.
Many semi-mt touchpads also have a lower resolution for the second touch, or
both touches. This may limit some features such as @ref gestures or
@ref scrolling.
Semi-mt are labelled by the kernel with the @c INPUT_PROP_SEMI_MT input
property.
@section touchpads_mis Other touchpad properties
@subsection touchpads_external External touchpads
External touchpads are USB or Bluetooth touchpads not in a laptop chassis,
e.g. Apple Magic Trackpad or the Logitech T650. These are usually @ref
touchpads_buttons_clickpads the biggest difference is that they can be
removed or added at runtime.
One interaction method that is only possible on external touchpads is a
thumb resting on the very edge/immediately next to the touchpad. On the far
edge, touchpads don't always detect the finger location so clicking with a
thumb barely touching the edge makes it hard or impossible to figure out
which software button area the finger is on.
These touchpads also don't need @ref palm_detection - since they're not
located underneath the keyboard, accidental palm touches are a non-issue.
@subsection touchpads_pressure_handling Touchpads pressure handling
Pressure is usually directly related to contact area. Human fingers flatten
out as the pressure on the pad increases, resulting in a bigger contact area
and the firmware then calculates that back into a pressure reading.
libinput uses pressure to detect accidental palm contact and thumbs, though
pressure data is often device-specific and unreliable.
@subsection touchpads_circular Circular touchpads
Only listed for completeness, circular touchpads have not been used in
laptops for a number of years. These touchpad shaped in an ellipse or
straight.
@subsection touchpads_tablets Graphics tablets
Touch-capable graphics tablets are effectively external touchpads, with two
differentiators: they are larger than normal touchpads and they have no
regular touchpad buttons. They either work like a @ref
touchpads_buttons_forcepads Forcepad, or rely on interaction methods that
don't require buttons (like @ref tapping). Since the physical device is
shared with the pen input, some touch arbitration is required to avoid touch
input interfering when the pen is in use.
@subsection touchpads_edge_zone Dedicated edge scroll area
Before @ref twofinger_scrolling became the default scroll method, some
touchpads provided a marking on the touch area that designates the
edge to be used for scrolling. A finger movement in that edge zone should
trigger vertical motions. Some touchpads had markers for a horizontal
scroll area too at the bottom of the touchpad.
*/

View file

@ -1,9 +0,0 @@
:orphan:
===
404
===
This page has permanently moved, probably to `<@TARGET@>`_
This placeholder page will be removed soon.

View file

@ -1,144 +0,0 @@
.. _absolute_axes:
==============================================================================
Absolute axes
==============================================================================
Devices with absolute axes are those that send positioning data for an axis in
a device-specific coordinate range, defined by a minimum and a maximum value.
Compare this to relative devices (e.g. a mouse) that can only detect
directional data, not positional data.
libinput supports three types of devices with absolute axes:
- multi-touch screens
- single-touch screens
- :ref:`graphics tablets <tablet-support>`
Touchpads are technically absolute devices but libinput converts the axis values
to directional motion and posts events as relative events. Touchpads do not count
as absolute devices in libinput.
For all absolute devices in libinput, the default unit for x/y coordinates is
in mm off the top left corner on the device, or more specifically off the
device's sensor. If the device is physically rotated from its natural
position and this rotation was communicated to libinput (e.g. by setting
the device left-handed),
the coordinate origin is the top left corner in the current rotation.
.. _absolute_axes_handling:
------------------------------------------------------------------------------
Handling of absolute coordinates
------------------------------------------------------------------------------
In most use-cases, absolute input devices are mapped to a single screen. For
direct input devices such as touchscreens the aspect ratio of the screen and
the device match. Mapping the input device position to the output position is
thus a simple mapping between two coordinates. libinput provides the API for
this with
- **libinput_event_pointer_get_absolute_x_transformed()** for pointer events
- **libinput_event_touch_get_x_transformed()** for touch events
libinput's API only provides the call to map into a single coordinate range.
If the coordinate range has an offset, the compositor is responsible for
applying that offset after the mapping. For example, if the device is mapped
to the right of two outputs, add the output offset to the transformed
coordinate.
.. _absolute_axes_nores:
------------------------------------------------------------------------------
Devices without x/y resolution
------------------------------------------------------------------------------
An absolute device that does not provide a valid resolution is considered
buggy and must be fixed in the kernel. Some touchpad devices do not
provide resolution, those devices are correctly handled within libinput
(touchpads are not absolute devices, as mentioned above).
.. _calibration:
------------------------------------------------------------------------------
Calibration of absolute devices
------------------------------------------------------------------------------
Absolute devices may require calibration to map precisely into the output
range required. This is done by setting a transformation matrix, see
**libinput_device_config_calibration_set_matrix()** which is applied to
each input coordinate.
.. math::
\begin{pmatrix}
cos\theta & -sin\theta & xoff \\
sin\theta & cos\theta & yoff \\
0 & 0 & 1
\end{pmatrix} \begin{pmatrix}
x \\ y \\ 1
\end{pmatrix}
:math:`\theta` is the rotation angle. The offsets :math:`xoff` and :math:`yoff` are
specified in device dimensions, i.e. a value of 1 equals one device width or
height. Note that rotation applies to the device's origin, rotation usually
requires an offset to move the coordinates back into the original range.
The most common matrices are:
- 90 degree clockwise:
.. math::
\begin{pmatrix}
0 & -1 & 1 \\
1 & 0 & 0 \\
0 & 0 & 1
\end{pmatrix}
- 180 degree clockwise:
.. math::
\begin{pmatrix}
-1 & 0 & 1 \\
0 & -1 & 1 \\
0 & 0 & 1
\end{pmatrix}
- 270 degree clockwise:
.. math::
\begin{pmatrix}
0 & 1 & 0 \\
-1 & 0 & 1 \\
0 & 0 & 1
\end{pmatrix}
- reflection along y axis:
.. math::
\begin{pmatrix}
-1 & 0 & 1 \\
1 & 0 & 0 \\
0 & 0 & 1
\end{pmatrix}
See Wikipedia's
`Transformation Matrix article <http://en.wikipedia.org/wiki/Transformation_matrix>`_
for more information on the matrix maths. See
**libinput_device_config_calibration_get_default_matrix()** for how these
matrices must be supplied to libinput.
Once applied, any x and y axis value has the calibration applied before it
is made available to the caller. libinput does not provide access to the
raw coordinates before the calibration is applied.
.. _absolute_axes_nonorm:
------------------------------------------------------------------------------
Why x/y coordinates are not normalized
------------------------------------------------------------------------------
x/y are not given in :ref:`normalized coordinates <motion_normalization>`
([0..1]) for one simple reason: the aspect ratio of virtually all current
devices is something other than 1:1. A normalized axes thus is only useful to
determine that the stylus is e.g. at 78% from the left, 34% from the top of
the device. Without knowing the per-axis resolution, these numbers are
meaningless. Worse, calculation based on previous coordinates is simply wrong:
a movement from 0/0 to 50%/50% is not a 45-degree line.
This could be alleviated by providing resolution and information about the
aspect ratio to the caller. Which shifts processing and likely errors into the
caller for little benefit. Providing the x/y axes in mm from the outset
removes these errors.

View file

@ -1,153 +0,0 @@
.. _absolute_coordinate_ranges:
==============================================================================
Coordinate ranges for absolute axes
==============================================================================
libinput requires that all touchpads provide a correct axis range and
resolution. These are used to enable or disable certain features or adapt
the interaction with the touchpad. For example, the software button area is
narrower on small touchpads to avoid reducing the interactive surface too
much. Likewise, palm detection works differently on small touchpads as palm
interference is less likely to happen.
Touchpads with incorrect axis ranges generate error messages
in the form:
<blockquote>
Axis 0x35 value 4000 is outside expected range [0, 3000]
</blockquote>
This error message indicates that the ABS_MT_POSITION_X axis (i.e. the x
axis) generated an event outside the expected range of 0-3000. In this case
the value was 4000.
This discrepancy between the coordinate range the kernels advertises vs.
what the touchpad sends can be the source of a number of perceived
bugs in libinput.
.. _absolute_coordinate_ranges_fix:
------------------------------------------------------------------------------
Measuring and fixing touchpad ranges
------------------------------------------------------------------------------
To fix the touchpad you need to:
#. measure the physical size of your touchpad in mm
#. run the ``libinput measure touchpad-size`` tool
#. verify the hwdb entry provided by this tool
#. test locally
#. send a patch to the `systemd project <https://github.com/systemd/systemd>`_.
Detailed explanations are below.
The ``libinput measure touchpad-size`` tool is an interactive tool. It must
be called with the physical dimensions of the touchpad in mm. In the example
below, we use 100mm wide and 55mm high. The tool will find the touchpad device
automatically.
::
$> sudo libinput measure touchpad-size 100x55
Using "Touchpad SynPS/2 Synaptics TouchPad": /dev/input/event4
Kernel specified touchpad size: 99.7x75.9mm
User specified touchpad size: 100.0x55.0mm
Kernel axis range: x [1024..5112], y [2024..4832]
Detected axis range: x [ 0.. 0], y [ 0.. 0]
Move one finger along all edges of the touchpad
until the detected axis range stops changing.
...
Move the finger around until the detected axis range matches the data sent
by the device. ``Ctrl+C`` terminates the tool and prints a
suggested hwdb entry. ::
...
Kernel axis range: x [1024..5112], y [2024..4832]
^C
Detected axis range: x [2072..4880], y [2159..4832]
Resolutions calculated based on user-specified size: x 28, y 49 units/mm
Suggested hwdb entry:
Note: the dmi modalias match is a guess based on your machine's modalias:
dmi:bvnLENOVO:bvrGJET72WW(2.22):bd02/21/2014:svnLENOVO:pn20ARS25701:pvrThinkPadT440s:rvnLENOVO:rn20ARS25701:rvrSDK0E50512STD:cvnLENOVO:ct10:cvrNotAvailable:
Please verify that this is the most sensible match and adjust if necessary.
-8<--------------------------
# Laptop model description (e.g. Lenovo X1 Carbon 5th)
evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrThinkPadT440s*
EVDEV_ABS_00=2072:4880:28
EVDEV_ABS_01=2159:4832:49
EVDEV_ABS_35=2072:4880:28
EVDEV_ABS_36=2159:4832:49
-8<--------------------------
Instructions on what to do with this snippet are in /usr/lib/udev/hwdb.d/60-evdev.hwdb
If there are discrepancies between the coordinate range the kernels
advertises and what what the touchpad sends, the hwdb entry should be added to the
``60-evdev.hwdb`` file provided by the `systemd project <https://github.com/systemd/systemd>`_.
An example commit can be found
`here <https://github.com/systemd/systemd/commit/26f667eac1c5e89b689aa0a1daef6a80f473e045>`_.
The ``libinput measure touchpad-size`` tool attempts to provide the correct
dmi match but it does require user verification.
In most cases the dmi match can and should be trimmed to the system vendor (``svn``)
and the product version (``pvr``) or product name (``pn``), with everything else
replaced by a wildcard (``*``). In the above case, the match string is:
::
evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrThinkPadT440s*
As a general rule: for Lenovo devices use ``pvr`` and for all others use
``pn``.
.. note:: hwdb match strings only allow for alphanumeric ascii characters. Use a
wildcard (* or ?, whichever appropriate) for special characters.
The actual axis overrides are in the form:
::
# axis number=min:max:resolution
EVDEV_ABS_00=2072:4880:28
or, if the range is correct but the resolution is wrong
::
# axis number=::resolution
EVDEV_ABS_00=::28
Note the leading single space. The axis numbers are in hex and can be found
in ``linux/input-event-codes.h``. For touchpads ``ABS_X``, ``ABS_Y``,
``ABS_MT_POSITION_X`` and ``ABS_MT_POSITION_Y`` are required.
.. note:: The touchpad's ranges and/or resolution should only be fixed when
there is a significant discrepancy. A few units do not make a
difference and a resolution that is off by 2 or less usually does
not matter either.
Once a match and override rule has been found, follow the instructions at
the top of the
`60-evdev.hwdb <https://github.com/systemd/systemd/blob/main/hwdb.d/60-evdev.hwdb>`_
file to save it locally and trigger the udev hwdb reload. Rebooting is
always a good idea. If the match string is correct, the new properties will
show up in the
output of
::
udevadm info /sys/class/input/event4
Adjust the command for the event node of your touchpad.
A udev builtin will apply the new axis ranges automatically.
When the axis override is confirmed to work, please submit it as a pull
request to the `systemd project <https://github.com/systemd/systemd>`_.

View file

@ -1,416 +0,0 @@
.. _architecture:
==============================================================================
libinput's internal architecture
==============================================================================
This page provides an outline of libinput's internal architecture. The goal
here is to get the high-level picture across and point out the components
and their interplay to new developers.
The public facing API is in ``libinput.c``, this file is thus the entry point
for almost all API calls. General device handling is in ``evdev.c`` with the
device-type-specific implementations in ``evdev-<type>.c``. It is not
necessary to understand all of libinput to contribute a patch.
As of libinput 1.29 libinput has an internal plugin pipeline that modifies
the event stream before libinput proper sees it, see
:ref:`architecture-plugins`.
:ref:`architecture-contexts` is the only user-visible implementation detail,
everything else is purely internal implementation and may change when
required.
.. _architecture-contexts:
------------------------------------------------------------------------------
The udev and path contexts
------------------------------------------------------------------------------
The first building block is the "context" which can be one of
two types, "path" and "udev". See **libinput_path_create_context()** and
**libinput_udev_create_context()**. The path/udev specific bits are in
``path-seat.c`` and ``udev-seat.c``. This includes the functions that add new
devices to a context.
.. graphviz::
digraph context
{
compound=true;
rankdir="LR";
node [
shape="box";
]
libudev [label="libudev 'add' event"]
udev [label="**libinput_udev_create_context()**"];
udev_backend [label="udev-specific backend"];
context [label="libinput context"]
udev -> udev_backend;
libudev -> udev_backend;
udev_backend -> context;
}
The udev context provides automatic device hotplugging as udev's "add"
events are handled directly by libinput. The path context requires that the
caller adds devices.
.. graphviz::
digraph context
{
compound=true;
rankdir="LR";
node [
shape="box";
]
path [label="**libinput_path_create_context()**"];
path_backend [label="path-specific backend"];
xdriver [label="**libinput_path_add_device()**"]
context [label="libinput context"]
path -> path_backend;
xdriver -> path_backend;
path_backend -> context;
}
As a general rule: all Wayland compositors use a udev context, the X.org
stack uses a path context.
Which context was initialized only matters for creating/destroying a context
and adding devices. The device handling itself is the same for both types of
context.
.. _architecture-device:
------------------------------------------------------------------------------
Device initialization
------------------------------------------------------------------------------
libinput only supports evdev devices, all the device initialization is done
in ``evdev.c``. Much of the libinput public API is also a thin wrapper around
the matching implementation in the evdev device.
There is a 1:1 mapping between libinput devices and ``/dev/input/eventX``
device nodes.
.. graphviz::
digraph context
{
compound=true;
rankdir="LR";
node [
shape="box";
]
devnode [label="/dev/input/event0"]
libudev [label="libudev 'add' event"]
xdriver [label="**libinput_path_add_device()**"]
context [label="libinput context"]
evdev [label="evdev_device_create()"]
devnode -> xdriver;
devnode -> libudev;
xdriver -> context;
libudev -> context;
context->evdev;
}
Entry point for all devices is ``evdev_device_create()``, this function
decides to create a ``struct evdev_device`` for the given device node.
Based on the udev tags (e.g. ``ID_INPUT_TOUCHPAD``), a
:ref:`architecture-dispatch` is initialized. All event handling is then in this
dispatch.
Rejection of devices and the application of quirks is generally handled in
``evdev.c`` as well. Common functionality shared across multiple device types
(like button-scrolling) is also handled here.
.. _architecture-dispatch:
------------------------------------------------------------------------------
Device-type specific event dispatch
------------------------------------------------------------------------------
Depending on the device type, ``evdev_configure_device`` creates the matching
``struct evdev_dispatch``. This dispatch interface contains the function
pointers to handle events. Four such dispatch methods are currently
implemented: touchpad, tablet, tablet pad, and the fallback dispatch which
handles mice, keyboards and touchscreens.
.. graphviz::
digraph context
{
compound=true;
rankdir="LR";
node [
shape="box";
]
evdev [label="evdev_device_create()"]
fallback [label="evdev-fallback.c"]
touchpad [label="evdev-mt-touchpad.c"]
tablet [label="evdev-tablet.c"]
pad [label="evdev-tablet-pad.c"]
evdev -> fallback;
evdev -> touchpad;
evdev -> tablet;
evdev -> pad;
}
Event dispatch is done per "evdev frame", a collection of events up until including
the ``SYN_REPORT``. One such ``struct evdev_frame`` represents all state **updates**
to the previous frame.
While ``evdev.c`` pulls the event out of libevdev, the actual handling of the
events is performed within the dispatch method.
.. graphviz::
digraph context
{
compound=true;
rankdir="LR";
node [
shape="box";
]
evdev [label="evdev_device_dispatch()"]
plugins [label="plugin pipline"]
fallback [label="fallback_interface_process()"];
touchpad [label="tp_interface_process()"]
tablet [label="tablet_process()"]
pad [label="pad_process()"]
evdev -> plugins;
plugins -> fallback;
plugins -> touchpad;
plugins -> tablet;
plugins -> pad;
}
The dispatch methods then look at the ``struct evdev_frame`` and proceed to
update the state.
.. _architecture-plugins:
------------------------------------------------------------------------------
The Plugin Pipeline
------------------------------------------------------------------------------
As of libinput 1.29 libinput has an **internal** plugin pipeline. These plugins
logically sit between libevdev and the :ref:`architecture-dispatch` and modify
the device and/or event stream. The primary motivation of such plugins is that
modifying the event stream is often simpler than analyzing the state later.
Plugins are loaded on libinput context startup and are executed in-order. The last
plugin is the hardcoded `evdev-plugin.c` which takes the modified event stream and
passes the events to the dispatch.
.. graphviz::
digraph context
{
compound=true;
rankdir="LR";
node [
shape="box";
]
evdev [label="evdev_device_dispatch()"]
p1 [label="P1"]
p2 [label="P2"]
p3 [label="P3"]
ep [label="evdev-plugin"]
fallback [label="fallback_interface_process()"];
touchpad [label="tp_interface_process()"]
tablet [label="tablet_process()"]
pad [label="pad_process()"]
evdev -> p1;
p1 -> p2;
p2 -> p3;
p3 -> ep;
ep -> fallback;
ep -> touchpad;
ep -> tablet;
ep -> pad;
}
Each plugin may not only modify the current event frame (this includes adding/removing events
from the frame), it may also append or prepend additional event frames. For
example the tablet proximity-timer plugin adds proximity in/out events to the
event stream.
.. graphviz::
digraph context
{
compound=true;
rankdir="LR";
node [
shape="box";
]
n0 [label= "", shape=none,height=.0,width=.0]
n1 [label= "", shape=none,height=.0,width=.0]
p1 [label="P1"]
p2 [label="P2"]
p3 [label="P3"]
ep [label="evdev-plugin"]
n0 -> p1 [label="F1"];
p1 -> p2 [label="F1"];
p2 -> p3 [label="F1,F2"];
p3 -> ep [label="F3,F1,F2"];
ep -> n1 [label="F3,F1,F2"];
}
In the diagram above, the plugin ``P2`` *appends* a new frame (``F2``), the plugin ``P3``
*prepends* a new frame (``F3``). The original event frame ``F1`` thus becomes the event frame
sequence ``F3``, ``F1``, ``F2`` by the time it reaches the :ref:`architecture-dispatch`.
Note that each plugin only sees one event frame at a time, so ``P3`` would see ``F1`` first,
decides to prepend ``F3`` and passes ``F1`` through. It then sees ``F2`` but does nothing with
it (optionally modified in-place).
.. _architecture-configuration:
------------------------------------------------------------------------------
Device configuration
------------------------------------------------------------------------------
All device-specific configuration is handled through ``struct
libinput_device_config_FOO`` instances. These are set up during device init
and provide the function pointers for the ``get``, ``set``, ``get_default``
triplet of configuration queries (or more, where applicable).
For example, the ``struct tablet_dispatch`` for tablet devices has a
``struct libinput_device_config_accel``. This struct is set up with the
required function pointers to change the profiles.
.. graphviz::
digraph context
{
compound=true;
rankdir="LR";
node [
shape="box";
]
tablet [label="struct tablet_dispatch"]
config [label="struct libinput_device_config_accel"];
tablet_config [label="tablet_accel_config_set_profile()"];
tablet->config;
config->tablet_config;
}
When the matching ``**libinput_device_config_set_FOO()**`` is called, this goes
through to the config struct and invokes the function there. Thus, it is
possible to have different configuration functions for a mouse vs a
touchpad, even though the interface is the same.
.. graphviz::
digraph context
{
compound=true;
rankdir="LR";
node [
shape="box";
]
libinput [label="**libinput_device_config_accel_set_profile()**"];
tablet_config [label="tablet_accel_config_set_profile()"];
libinput->tablet_config;
}
.. _architecture-filter:
------------------------------------------------------------------------------
Pointer acceleration filters
------------------------------------------------------------------------------
All pointer acceleration is handled in the ``filter.c`` file and its
associated files.
The ``struct motion_filter`` is initialized during device init, whenever
deltas are available they are passed to ``filter_dispatch()``. This function
returns a set of :ref:`normalized coordinates <motion_normalization_customization>`.
All actual acceleration is handled within the filter, the device itself has
no further knowledge. Thus it is possible to have different acceleration
filters for the same device types (e.g. the Lenovo X230 touchpad has a
custom filter).
.. graphviz::
digraph context
{
compound=true;
rankdir="LR";
node [
shape="box";
]
fallback [label="fallback deltas"];
touchpad [label="touchpad deltas"];
tablet [label="tablet deltas"];
filter [label="filter_dispatch"];
fallback->filter;
touchpad->filter;
tablet->filter;
flat [label="accelerator_interface_flat()"];
x230 [label="accelerator_filter_x230()"];
pen [label="tablet_accelerator_filter_flat_pen()"];
filter->flat;
filter->x230;
filter->pen;
}
Most filters convert the deltas (incl. timestamps) to a motion speed and
then apply a so-called profile function. This function returns a factor that
is then applied to the current delta, converting it into an accelerated
delta. See :ref:`pointer-acceleration` for more details.
the current

View file

@ -1,299 +0,0 @@
.. _building_libinput:
==============================================================================
libinput build instructions
==============================================================================
.. contents::
:local:
:backlinks: entry
Instructions on how to build libinput and its tools and how to build against
libinput.
The build instruction on this page detail how to overwrite your
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:
------------------------------------------------------------------------------
Building libinput
------------------------------------------------------------------------------
libinput uses `meson <https://www.mesonbuild.com>`_ and
`ninja <https://www.ninja-build.org>`_. A build is usually the three-step
process below. A successful build requires the
:ref:`building_dependencies` to be installed before running meson.
::
$> git clone https://gitlab.freedesktop.org/libinput/libinput
$> cd libinput
$> meson setup --prefix=/usr builddir/
$> ninja -C builddir/
$> sudo ninja -C builddir/ install
When running libinput versions 1.11.x or earlier, you must run
::
$> sudo systemd-hwdb update
Additional options may also be specified. For example:
::
$> meson setup --prefix=/usr -Ddocumentation=false builddir/
We recommend that users disable the documentation, it's not usually required
for testing and reduces the number of dependencies needed.
The ``prefix`` or other options can be changed later with the
``meson configure`` command. For example:
::
$> meson configure builddir/ -Dprefix=/some/other/prefix -Ddocumentation=true
$> ninja -C builddir
$> sudo ninja -C builddir/ install
Running ``meson configure builddir/`` with no other arguments lists all
configurable options meson provides.
To rebuild from scratch, simply remove the build directory and run meson
again:
::
$> rm -r builddir/
$> meson setup --prefix=....
.. _verifying_install:
..............................................................................
Verifying the install
..............................................................................
To verify the install worked correctly, check that libinput.so.x.x.x is in
the library path and that all symlinks point to the new library.
::
$> ldconfig -p | grep libinput | awk '{print $NF}' | xargs ls -l
lrwxrwxrwx 1 root root 14 lug 22 13:06 /usr/lib/x86_64-linux-gnu/libinput.so -> libinput.so.10
lrwxrwxrwx 1 root root 19 lug 22 13:06 /usr/lib/x86_64-linux-gnu/libinput.so.10 -> libinput.so.10.13.0
-rwxr-xr-x 1 root root 1064144 lug 22 13:06 /usr/lib/x86_64-linux-gnu/libinput.so.10.13.0
.. _reverting_install:
..............................................................................
Reverting to the system-provided libinput package
..............................................................................
The recommended way to revert to the system install is to use the package
manager to reinstall the libinput package. In some cases, this may leave
files in the system (e.g. ``/usr/lib/libinput.la``) but these files are
usually harmless. To definitely remove all files, run the following command
from the libinput source directory:
::
$> sudo ninja -C builddir/ uninstall
# WARNING: Do not restart the computer/X/the Wayland compositor after
# uninstall, reinstall the system package immediately!
The following commands reinstall the current system package for libinput,
overwriting manually installed files.
- **Debian/Ubuntu** based distributions: ``sudo apt-get install --reinstall libinput``
- **Fedora 22** and later: ``sudo dnf reinstall libinput``
- **RHEL/CentOS/Fedora 21** and earlier: ``sudo yum reinstall libinput``
- **openSUSE**: ``sudo zypper install --force libinput10``
- **Arch**: ``sudo pacman -S libinput``
.. _building_selinux:
..............................................................................
SELinux adjustments
..............................................................................
.. note:: This section only applies to meson version < 0.42.0
On systems with SELinux, overwriting the distribution-provided package with
a manually built libinput may cause SELinux denials. This usually manifests
when gdm does not start because it is denied access to libinput. The journal
shows a log message in the form of:
::
May 25 15:28:42 localhost.localdomain audit[23268]: AVC avc: denied { execute } for pid=23268 comm="gnome-shell" path="/usr/lib64/libinput.so.10.12.2" dev="dm-0" ino=1709093 scontext=system_u:system_r:xdm_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=0
May 25 15:28:42 localhost.localdomain org.gnome.Shell.desktop[23270]: /usr/bin/gnome-shell: error while loading shared libraries: libinput.so.10: failed to map segment from shared object
The summary of this error message is that gdm's gnome-shell runs in the
``system_u:system_r:xdm_t`` context but libinput is installed with the
context ``unconfined_u:object_r:user_home_t``.
To avoid this issue, restore the SELinux context for any system files.
::
$> sudo restorecon /usr/lib*/libinput.so.*
This issue is tracked in https://github.com/mesonbuild/meson/issues/1967.
.. _building_dependencies:
------------------------------------------------------------------------------
Build dependencies
------------------------------------------------------------------------------
libinput has a few build-time dependencies that must be installed prior to
running meson.
.. hint:: The build dependencies for some distributions can be found in the
`GitLab Continuous Integration file <https://gitlab.freedesktop.org/libinput/libinput/blob/main/.gitlab-ci.yml>`_.
Search for **FEDORA_PACKAGES** in the **variables:** definition
and check the list for an entry for your distribution.
In most cases, it is sufficient to install the dependencies that your
distribution uses to build the libinput package. These can be installed
with one of the following commands:
- **Debian/Ubuntu** based distributions: ``sudo apt-get build-dep libinput``
- **Fedora 22** and later: ``sudo dnf builddep libinput``
- **RHEL/CentOS/Fedora 21** and earlier: ``sudo yum-builddep libinput``
- **openSUSE**: ::
$> sudo zypper modifyrepo --enable ``zypper repos | grep source | awk '{print $5}'``
$> sudo zypper source-install -d libinput10
$> sudo zypper install autoconf automake libtool
$> sudo zypper modifyrepo --disable ``zypper repos | grep source | awk '{print $5}'``
- **Arch**: ::
$> sudo pacman -S asp
$> cd $(mktemp -d)
$> asp export libinput
$> cd libinput
$> makepkg --syncdeps --nobuild --noextract
If dependencies are missing, meson shows a message ``No package 'foo'
found``. See
`this blog post here <https://who-t.blogspot.com/2018/07/meson-fails-with-native-dependency-not-found.html>`_
for instructions on how to fix it.
..............................................................................
Build dependencies per distribution
..............................................................................
.. include:: dependencies.rst
.. _building_conditional:
------------------------------------------------------------------------------
Conditional builds
------------------------------------------------------------------------------
libinput supports several meson options to disable parts of the build. See
the ``meson_options.txt`` file in the source tree for a full list of
available options. The default build enables most options and thus requires
more build dependencies. On systems where build dependencies are an issue,
options may be disabled with this meson command: ::
meson setup --prefix=/usr -Dsomefeature=false builddir
Where ``-Dsomefeature=false`` may be one of:
- ``-Ddocumentation=false``
Disables the documentation build (this website). Building the
documentation is only needed on the maintainer machine.
- ``-Dtests=false``
Disables the test suite. The test suite is only needed on developer
systems.
- ``-Ddebug-gui=false``
Disables the ``libinput debug-gui`` helper tool (see :ref:`tools`),
dropping GTK and other build dependencies. The debug-gui is only
required for troubleshooting.
- ``-Dlibwacom=false``
libwacom is required by libinput's tablet code to gather additional
information about tablets that is not available from the kernel device.
It is not recommended to disable libwacom unless libinput is used in an
environment where tablet support is not required. libinput provides tablet
support even without libwacom, but some features may be missing or working
differently.
.. _building_against:
------------------------------------------------------------------------------
Building against libinput
------------------------------------------------------------------------------
libinput provides a
`pkg-config <https://www.freedesktop.org/wiki/Software/pkg-config/>`_ file.
Software that uses autotools should use the ``PKG_CHECK_MODULES`` autoconf
macro: ::
PKG_CHECK_MODULES(LIBINPUT, "libinput")
Software that uses meson should use the ``dependency()`` function: ::
pkgconfig = import('pkgconfig')
dep_libinput = dependency('libinput')
Software that uses CMake should use: ::
find_package(Libinput)
target_link_libraries(myprogram PRIVATE Libinput::Libinput)
Otherwise, the most rudimentary way to compile and link a program against
libinput is:
::
gcc -o myprogram myprogram.c ``pkg-config --cflags --libs libinput``
For further information on using pkgconfig see the pkg-config documentation.

View file

@ -1,56 +0,0 @@
.. _button_debouncing:
==============================================================================
Button debouncing
==============================================================================
Physical buttons experience wear-and-tear with usage. On some devices this
can result in an effect called "contact bouncing" or "chatter". This effect
can cause the button to send multiple events within a short time frame, even
though the user only pressed or clicked the button once. This effect can be
counteracted by "debouncing" the buttons, usually by ignoring erroneous
events.
libinput provides two methods of debouncing buttons, referred to as the
"bounce" and "spurious" methods:
- In the "bounce" method, libinput monitors hardware bouncing on button
state changes, i.e. when a user clicks or releases a button. For example,
if a user presses a button but the hardware generates a
press-release-press sequence in quick succession, libinput ignores the
release and second press event. This method is always enabled.
- in the "spurious" method, libinput detects spurious releases of a button
while the button is physically held down by the user. These releases are
immediately followed by a press event. libinput monitors for these events
and ignores the release and press event. This method is disabled by
default and enables once libinput detects the first faulty event sequence.
The "bounce" method guarantees that all press events are delivered
immediately and most release events are delivered immediately. The
"spurious" method requires that release events are delayed, libinput thus
does not enable this method unless a faulty event sequence is detected. A
message is printed to the log when spurious deboucing was detected.
libinput's debouncing is supposed to correct hardware damage or
substandard hardware. Debouncing also exists as an accessibility feature
but the requirements are different. In the accessibility feature, multiple
physical key presses, usually caused by involuntary muscle movement, must be
filtered to only one key press. This feature must be implemented higher in
the stack, libinput is limited to hardware debouncing.
Below is an illustration of the button debouncing modes to show the relation
of the physical button state and the application state. Where applicable, an
extra line is added to show the timeouts used by libinput that
affect the button state handling. The waveform's high and low states
correspond to the buttons 'pressed' and 'released' states, respectively.
.. figure:: button-debouncing-wave-diagram.svg
:align: center
Diagram illustrating button debouncing
Some devices send events in bursts, erroneously triggering the button
debouncing detection. Please :ref:`file a bug <reporting_bugs>` if that
occurs for your device.

View file

@ -1,144 +0,0 @@
.. _clickpad_softbuttons:
==============================================================================
Clickpad software button behavior
==============================================================================
"Clickpads" are touchpads without separate physical buttons. Instead, the
whole touchpad acts as a button and left or right button clicks are
distinguished by :ref:`the location of the fingers <software_buttons>` or
the :ref:`number of fingers on the touchpad <clickfinger>`.
"ClickPad" is a trademark by `Synaptics Inc. <http://www.synaptics.com/en/clickpad.php>`_
but for simplicity we refer to any touchpad with the above feature as Clickpad,
regardless of the manufacturer.
The kernel marks clickpads with the
`INPUT_PROP_BUTTONPAD <https://www.kernel.org/doc/Documentation/input/event-codes.txt>`_
property. Without this property, libinput would not know whether a touchpad
is a clickpad or not. To perform a right-click on a Clickpad, libinput
provides :ref:`software_buttons` and :ref:`clickfinger`.
.. note:: The term "click" refers refer to a physical button press
and/or release of the touchpad, the term "button event" refers to
the events generated by libinput in response to a click.
.. _software_buttons:
------------------------------------------------------------------------------
Software button areas
------------------------------------------------------------------------------
The bottom of the touchpad is split into three distinct areas generate left,
middle or right button events on click. The height of the button area
depends on the hardware but is usually around 10mm.
.. figure :: software-buttons-visualized.svg
:align: center
The locations of the virtual button areas.
Left, right and middle button events can be triggered as follows:
- if a finger is in the main area or the left button area, a click generates
left button events.
- if a finger is in the right area, a click generates right button events.
- if a finger is in the middle area, a click generates middle button events.
.. figure:: software-buttons.svg
:align: center
Left, right and middle-button click with software button areas
The middle button is always centered on the touchpad and smaller in size
than the left or right button. The actual size is device-dependent. Many
touchpads do not have visible markings so the exact location of the button
is unfortunately not visibly obvious.
.. note:: If :ref:`middle button emulation <middle_button_emulation>` is
enabled on a clickpad, only left and right button areas are
available.
If fingers are down in the main area in addition to fingers in the
left or right button area, those fingers are are ignored.
A release event always releases the buttons logically down, regardless of
the current finger position
.. figure:: software-buttons-thumbpress.svg
:align: center
Only the location of the thumb determines whether it is a left, right or
middle click.
The movement of a finger can alter the button area behavior:
- if a finger starts in the main area and moves into the software button
area, the software buttons do not apply to that finger
- once a finger has moved out of the button area, it cannot move back in and
trigger a right or middle button event
- a finger moving within the software button area does not move the pointer
- once a finger moves out out of the button area it will control the
pointer (this only applies if there is no other finger down on the
touchpad)
.. figure:: software-buttons-conditions.svg
:align: center
**Left:** moving a finger into the right button area does not trigger a
right-button click.
**Right:** moving within the button areas does not generate pointer
motion.
On some touchpads, notably the 2015 Lenovo X1 Carbon 3rd series, the very
bottom end of the touchpad is outside of the sensor range but it is possible
to trigger a physical click there. To libinput, the click merely shows up as
a left button click without any positional finger data and it is
impossible to determine whether it is a left or a right click. libinput
ignores such button clicks, this behavior is intentional.
.. _clickfinger:
------------------------------------------------------------------------------
Clickfinger behavior
------------------------------------------------------------------------------
This is the default behavior on Apple touchpads. Here, a left, right, middle
button event is generated when one, two, or three fingers are held down on the
touchpad when a physical click is generated, given the default mapping. The
location of the fingers does not matter and there are no software-defined
button areas. It is possible to swap right and middle buttons, the same way as
with :ref:`tapping <tapping>`.
.. figure:: clickfinger.svg
:align: center
One, two and three-finger click with Clickfinger behavior
On some touchpads, libinput imposes a limit on how the fingers may be placed
on the touchpad. In the most common use-case this allows for a user to
trigger a click with the thumb while leaving the pointer-moving finger on
the touchpad.
.. figure:: clickfinger-distance.svg
:align: center
Illustration of the distance detection algorithm
In the illustration above the red area marks the proximity area around the
first finger. Since the thumb is outside of that area libinput considers the
click a single-finger click rather than a two-finger click.
.. _special_clickpads:
------------------------------------------------------------------------------
Special Clickpads
------------------------------------------------------------------------------
The Lenovo \*40 series laptops have a clickpad that provides two software button sections, one at
the top and one at the bottom. See :ref:`Lenovo \*40 series touchpad support <t440_support>`
for details on the top software button.
Some Clickpads, notably some Cypress ones, perform right button detection in
firmware and appear to userspace as if the touchpad had physical buttons.
While physically clickpads, these are not handled by the software and
treated like traditional touchpads.

View file

@ -1,46 +0,0 @@
.. _clickpads_with_right_buttons:
==============================================================================
Clickpads with a fake right button
==============================================================================
libinput relies on the kernel to label :ref:`Clickpads <touchpads_buttons_clickpads>`
with the ``INPUT_PROP_BUTTONPAD`` property so it can enable the correct
:ref:`clickpad_softbuttons`. Clickpads are not expected to have a right button
since the whole surface can be depressed.
A common bug encountered with :ref:`Clickpads <touchpads_buttons_clickpads>`
is that the device advertises a physical right button where no such button
exists. This is usually a bug in the firmware of the device and causes the
following warning to be emitted by libinput::
"<device name> clickpad advertising right button"
The user-visible effect of this is usually negligible since these devices
cannot actually trigger a right click and libinput's default behaviors for
clickpads work as expected.
However, we should nonetheless correct the device to get rid of this warning
and avoid potential issues with future features. The :ref:`device-quirks`
provide a simple way to disable the fake right button on the device. The
following quirk disables the right button on the MyModel laptop from the
MyVendor OEM::
[MyVendor MyModel Touchpad]
MatchName=Foo Bar Touchpad
MatchUdevtype=touchpad
MatchDMIModAlias=dmi:*:svnMyVendor:pnMyModel:*
AttrEventCode=-BTN_RIGHT
The name of the device can be obtained using :ref:`libinput record <libinput-record>`,
the modalias match is a shell-style glob against the value of ``/sys/class/dmi/id/modalias``.
In most cases, matching should be against ``svn`` (system vendor) and one of
``pn`` (product name) or ``pvr`` (product version), whichever provides a
useful description of the individual laptop model. See the
:ref:`device-quirks` documentation for details on testing local quirks.
For reference, some example commits that add such a quirk are:
- `bf61ab9bb0694d0ac3d60a7f815779abfe4886e6 <https://gitlab.freedesktop.org/libinput/libinput/-/commit/bf61ab9bb0694d0ac3d60a7f815779abfe4886e6>`__
- `74fac6d040ac62048882dfb6f73da567ace6a6f5 <https://gitlab.freedesktop.org/libinput/libinput/-/commit/74fac6d040ac62048882dfb6f73da567ace6a6f5>`__
- `89cd0f990e3bee9906754d6ca8484ed5aa392249 <https://gitlab.freedesktop.org/libinput/libinput/-/commit/89cd0f990e3bee9906754d6ca8484ed5aa392249>`__

View file

@ -1,193 +0,0 @@
# -*- coding: utf-8 -*-
#
# Configuration file for the Sphinx documentation builder.
#
# This file does only contain a selection of the most common options. For a
# full list see the documentation:
# http://www.sphinx-doc.org/en/stable/config
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# sys.path.insert(0, os.path.abspath('.'))
import sys
import os
sys.path.insert(0, os.path.abspath('@BUILDDIR@'))
# -- Project information -----------------------------------------------------
project = '@PROJECT_NAME@'
copyright = '2019, the libinput authors'
author = 'the libinput authors'
# The short X.Y version
version = '@PROJECT_VERSION@'
# The full version, including alpha/beta/rc tags
release = '@PROJECT_VERSION@'
# -- General configuration ---------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.mathjax',
'sphinx.ext.graphviz',
'sphinx.ext.extlinks',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = 'en'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path .
exclude_patterns = []
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
highlight_language = 'none'
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
html_theme_options = {
'collapse_navigation': False,
'navigation_depth': 3,
}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
# html_static_path = ['_static']
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# The default sidebars (for documents that don't match any pattern) are
# defined by theme itself. Builtin themes are using these templates by
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
# 'searchbox.html']``.
#
# html_sidebars = {}
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = '@PROJECT_NAME@doc'
# -- Options for LaTeX output ------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, '@PROJECT_NAME@.tex', '@PROJECT_NAME@ Documentation',
'Peter Hutterer', 'manual'),
]
# -- Options for manual page output ------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, '@PROJECT_NAME@', '@PROJECT_NAME@ Documentation',
[author], 1)
]
# -- Options for Texinfo output ----------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, '@PROJECT_NAME@', '@PROJECT_NAME@ Documentation',
author, '@PROJECT_NAME@', 'One line description of project.',
'Miscellaneous'),
]
# -- Extension configuration -------------------------------------------------
from recommonmark.parser import CommonMarkParser
extlinks = { 'commit' :
('https://gitlab.freedesktop.org/libinput/libinput/commit/%s',
'git commit %s')
}
# -- git version hack -------------------------------------------------
#
# meson doesn't take configuration_data() for vcs_tag, so we cannot replace
# two substrings in the same file.
#
# sphinx cannot do ..include:: without linebreaks, so in-line replacements
# are a no-go.
#
# Work around this by generating a mini python module in meson through
# vcs_tag, then use that to generate the replacements in rst_prolog.
import git_version
rst_prolog = """
.. |git_version| replace:: :commit:`{}`
.. |git_version_full| replace:: :commit:`{}`
""".format(git_version.get_git_version(),
git_version.get_git_version_full)

View file

@ -1,237 +0,0 @@
.. _config_options:
==============================================================================
Configuration options
==============================================================================
Below is a list of configurable options exposed to the users.
.. contents::
:depth: 1
:local:
.. hint:: Not all configuration options are available on all devices. Use
:ref:`libinput list-devices <libinput-list-devices>` to show the
configuration options for local devices.
libinput's configuration interface is available to the caller only, not
directly to the user. Thus it is the responsibility of the caller to expose
the various options and how these options are exposed. For example, the
`xf86-input-libinput driver <https://gitlab.freedesktop.org/xorg/driver/xf86-input-libinput/>`_
exposes the options through X Input device properties and `xorg.conf.d
<https://linux.die.net/man/5/xorg.conf.d>`_ options. See the `libinput(4)
<https://www.mankier.com/4/libinput>`_ man page for more details.
------------------------------------------------------------------------------
Tap-to-click
------------------------------------------------------------------------------
See :ref:`tapping` for details on how this feature works. Configuration
options exposed by libinput are:
- how many tapping fingers are supported by this device
- a toggle to enable/disable tapping
- a toggle to enable/disable tap-and-drag, see :ref:`tapndrag`.
- a toggle to enable/disable tap-and-drag drag lock, see :ref:`tapndrag`
- The default order is 1, 2, 3 finger tap mapping to left, right, middle
click, respectively. This order can be changed to left, middle, right click,
respectively.
Tapping is usually available on touchpads and the touchpad part of external
graphics tablets. Tapping is usually **not** available on touch screens,
for those devices it is expected to be implemented by the toolkit.
------------------------------------------------------------------------------
Three-finger drag
------------------------------------------------------------------------------
Three-finger drag allows emulates the mouse button down while three fingers
are down on a touchpad without the need to press a physical button or use
:ref:`tapndrag`. See :ref:`drag_3fg` for details on how this feature works.
Three-finger drag is usually available on touchpads and the touchpad part of
external graphics tablets. Three-finger drag is usually **not** available on
touch screens, for those devices it is expected to be implemented by the
toolkit.
------------------------------------------------------------------------------
Send Events Mode
------------------------------------------------------------------------------
The Send Events Mode is libinput's terminology for disabling a device. It is
more precise in that the device only stops sending events but may not get
fully disabled. For example, disabling the touchpad on a
:ref:`Lenovo T440 and similar <t440_support>` leaves the top software
buttons enabled for the trackpoint. Available options are
**enabled** (send events normally), **disabled** ( do not send events),
**disabled on external mouse** (disable the device while an external mouse
is plugged in).
.. _config_pointer_acceleration:
------------------------------------------------------------------------------
Pointer acceleration
------------------------------------------------------------------------------
Pointer acceleration is a function to convert input deltas to output deltas,
usually based on the movement speed of the device, see
:ref:`pointer-acceleration` for details.
Pointer acceleration is normalized into a [-1, 1] range, where -1 is
"slowest" and 1 is "fastest". Most devices use a default speed of 0.
The pointer acceleration profile defines **how** the input deltas are
converted, see :ref:`ptraccel-profiles`. Most devices have their default
profile (usually called "adaptive") and a "flat" profile. The flat profile
does not apply any acceleration.
------------------------------------------------------------------------------
Scrolling
------------------------------------------------------------------------------
"Natural scrolling" is the terminology for moving the content in the
direction of scrolling, i.e. moving the wheel or fingers down moves the page
down. Traditional scrolling moves the content in the opposite direction.
Natural scrolling can be turned on or off, it is usually off by default.
The scroll method defines how to trigger scroll events. On touchpads
libinput provides two-finger scrolling and edge scrolling. Two-finger
scrolling converts a movement with two fingers to a series of scroll events.
Edge scrolling converts a movement with one finger along the right or bottom
edge of the touchpad into a series of scroll events.
On other libinput provides button-scrolling - movement of the device while
the designated scroll button is down is converted to scroll events. The
button used for scrolling is configurable.
The scroll method can be chosen or disabled altogether but most devices only
support a subset of available scroll methods. libinput's default is
two-finger scrolling for multi-touch touchpads, edge scrolling for
single-touch touchpads. On tracksticks, button scrolling is enabled by
default.
See :ref:`scrolling` for more details on how the scroll methods work.
------------------------------------------------------------------------------
Left-handed Mode
------------------------------------------------------------------------------
Left-handed mode switches the device's functionality to be more
accommodating for left-handed users. On mice this usually means swapping the
left and right mouse button, on tablets this allows the tablet to be used
upside-down to present the pad buttons for the non-dominant right hand. Not
all devices have left-handed mode.
Left-handed mode can be enabled or disabled and is disabled by default.
------------------------------------------------------------------------------
Middle Button Emulation
------------------------------------------------------------------------------
Middle button emulation converts a simultaneous left and right button click
into a middle button. The emulation can be enabled or disabled. Middle
button emulation is usually enabled when the device does not provide a
middle button.
------------------------------------------------------------------------------
Click method
------------------------------------------------------------------------------
The click method defines how button events are triggered on a :ref:`clickpad
<clickpad_softbuttons>`. When set to button areas, the bottom area of the
touchpad is divided into a left, middle and right button area. When set to
clickfinger, the number of fingers on the touchpad decide the button type.
Clicking with 1, 2, 3 fingers triggers a left, right, or middle click,
respectively. The default click method is software button areas. Click
methods are usually only available on :ref:`clickpads
<clickpad_softbuttons>`.
------------------------------------------------------------------------------
Disable while typing
------------------------------------------------------------------------------
DWT is the most generic form of palm detection on touchpad. While the user
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.
------------------------------------------------------------------------------
Disable while trackpointing
------------------------------------------------------------------------------
DWTP is a form of palm detecion for devices that have a trackpoint (like
Thinkpads). While the user is using the trackpoint, the touchpad is disabled,
being enabled again after a timeout. See :ref:`disable-while-trackpointing` for
more info.
Disable-while-trackpointing can be enabled or disabled, it is enabled by
default.
------------------------------------------------------------------------------
Calibration
------------------------------------------------------------------------------
Calibration is available for some direct-input devices (touch screens,
graphics tablets, etc.). The purpose of calibration is to ensure the input
lines up with the output and the configuration data is a transformation
matrix. It is thus not expected that the user sets this option. The desktop
environment should provide an interface for this.
------------------------------------------------------------------------------
Rotation
------------------------------------------------------------------------------
The device rotation applies a corrective angle to relative input events,
allowing the device to be used e.g. sideways or upside-down. For example, a
trackball may be used in a 90° rotated position for accessibility reasons -
such a rotated position allows triggering the buttons with the thumb or
the non-dominant hand.
Note that where a device rotation is higher than 160 but less than 200 degrees,
the direction of wheels is also inverted. For all other angles, the wheel
direction is left as-is.
.. _config-tablet-pressure-range:
------------------------------------------------------------------------------
Tablet tool pressure range
------------------------------------------------------------------------------
The pressure range on a :ref:`Tablet tool <tablet-tools>` can be reduced
from the full available hardware range to a subset of that range. The effect
of this is that the tablet will not register pressure below the given
the given threshold is met, and will reach the maximum logical pressure
before the maximum hardware-supported pressure is reached.
See :ref:`tablet-pressure-range` for more info.
.. _config-tablet-eraser-buttons:
------------------------------------------------------------------------------
Tablet tool eraser buttons
------------------------------------------------------------------------------
On many contemporary :ref:`Tablet tools <tablet-tools>` one button is hardcoded
in firmware to emulate an eraser. This button can be remapped to provide
a normal stylus button instead.
See :ref:`tablet-eraser-button` for more info.
------------------------------------------------------------------------------
Area configuration
------------------------------------------------------------------------------
Area configuration is available for some indirect input devices such as
graphics tablets. This configuration allows reducing the active area of
such a device to a subset of the physically possible area.
An example use-case for this is to match the aspect ratio of the device to that
of the screen.
See :ref:`tablet-area` for more info.

View file

@ -1,421 +0,0 @@
.. _contributing:
==============================================================================
Contributing to libinput
==============================================================================
So you want to contribute to libinput? Great! We'd love to help you be a part
of our community. Here is some important information to help you.
.. contents::
:local:
------------------------------------------------------------------------------
Code of Conduct
------------------------------------------------------------------------------
As a freedesktop.org project, libinput follows the `freedesktop.org
Contributor Covenant <https://www.freedesktop.org/wiki/CodeOfConduct>`_.
Please conduct yourself in a respectful and civilised manner when
interacting with community members on mailing lists, IRC, or bug trackers.
The community represents the project as a whole, and abusive or bullying
behaviour is not tolerated by the project.
------------------------------------------------------------------------------
Contact
------------------------------------------------------------------------------
Questions can be asked on ``#wayland`` on oftc or on the
`wayland-devel@lists.freedesktop.org
<https://lists.freedesktop.org/mailman/listinfo/wayland-devel>`_ mailing
list.
For IRC, ping user ``whot`` (Peter Hutterer, the libinput maintainer) though
note that he lives on UTC+10 and thus the rest of the world is out of sync
by default ;)
For anything that appears to be device specific and/or related to a new
feature, just file `an issue in our issue tracker
<https://gitlab.freedesktop.org/libinput/libinput/issues>`_. It's usually the
most efficient way to get answers.
------------------------------------------------------------------------------
What to work on?
------------------------------------------------------------------------------
If you don't already know what you want to improve or fix with libinput,
then a good way of finding something is to search for the ``help needed``
tag in our `issue tracker <https://gitlab.freedesktop.org/libinput/libinput/issues?label_name%5B%5D=help+needed>`_.
These are issues that have been triaged to some degree and deemed to be a
possible future feature to libinput.
.. note:: Some of these issue may require specific hardware to reproduce.
Another good place to help out with is the documentation. For anything you
find in these pages that isn't clear enough please feel free to reword it
and add what is missing.
------------------------------------------------------------------------------
Getting the code
------------------------------------------------------------------------------
The :ref:`building_libinput` have all the details but the short solution
will be:
::
$> git clone https://gitlab.freedesktop.org/libinput/libinput
$> cd libinput
$> meson setup --prefix=/usr builddir/
$> ninja -C builddir/
$> sudo ninja -C builddir/ install
You can omit the last step if you only want to test locally.
------------------------------------------------------------------------------
Working on the code
------------------------------------------------------------------------------
If you are planning to send patches, it's a good idea to set up
`pre-commit <https://pre-commit.com/>`_ with these commands::
$> pre-commit install
$> pre-commit install --hook-type pre-push
This will check a few things before you commit and/or push to your repos to
reduce the turnaround time for some common mistakes.
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``).
- there are device-specific backends which do most of the actual work -
``evdev-mt-touchpad.c`` is the one for touchpads for example.
In general, things that only affect the internal workings of a device only
get implemented in the device-specific backend. You only need to touch the
API when you are adding configuration options. For more details, please read
the :ref:`architecture` document. There's also a `blog post describing the
building blocks
<https://who-t.blogspot.com/2019/03/libinputs-internal-building-blocks.html>`_
that may help to understand how it all fits together.
Documentation is in ``/doc/api`` for the doxygen-generated API documentation.
These are extracted from the libinput source code directly. The
documentation you're reading right now is in ``/doc/user`` and generated with
sphinx. Simply running ``ninja -C builddir`` will rebuild it and the final
product ends up in ``builddir/Documentation``.
------------------------------------------------------------------------------
Testing the code
------------------------------------------------------------------------------
libinput provides a bunch of :ref:`tools` to debug any changes - without
having to install libinput.
The two most useful ones are :ref:`libinput debug-events
<libinput-debug-events>` and :ref:`libinput debug-gui <libinput-debug-gui>`.
Both tools can be run from the build directory directly and are great for
quick test iterations::
$> sudo ./builddir/libinput-debug-events --verbose
$> sudo ./builddir/libinput-debug-gui --verbose
The former provides purely textual output and is useful for verifying event
streams from buttons, etc. The latter is particularly useful when you are
trying to debug pointer movement or placement. ``libinput debug-gui`` will
also visualize the raw data from the device so you can compare pointer
behavior with what comes from the kernel.
These tools create a new libinput context and will not affect your session's
behavior. Only once you've installed libinput and restarted your session
will your changes affect the X server/Wayland compositor.
Once everything seems to be correct, it's time to run the
:ref:`test-suite`::
$> sudo ./builddir/libinput-test-suite
This test suite can take test names etc. as arguments, have a look at
:ref:`test-suite` for more info. There are a bunch of other tests that are
run by the CI on merge requests, you can run those locally with ::
$> sudo ninja -C builddir check
So it always pays to run that before submitting. This will also run the code
through valgrind and pick up any memory leaks.
.. _contributing_submitting_code:
------------------------------------------------------------------------------
Submitting Code
------------------------------------------------------------------------------
Any patches should be sent via a Merge Request (see the `GitLab docs
<https://docs.gitlab.com/ce/gitlab-basics/add-merge-request.htm>`_)
in the `libinput GitLab instance hosted by freedesktop.org
<https://gitlab.freedesktop.org/libinput/libinput>`_.
.. note:: freedesktop.org's GitLab instance has restrictions to prevent Spam
and you cannot fork libinput until you have successfully
`applied for fork permissions <https://gitlab.freedesktop.org/freedesktop/freedesktop/-/wikis/home>`_.
Below are the steps required to submit a merge request. They do not
replace `learning git <https://git-scm.com/doc>`__ but they should be
sufficient to make some of the more confusing steps obvious.
- `Register an account <https://gitlab.freedesktop.org/users/sign_in>`_ in
the freedesktop.org GitLab instance and
`apply for fork permissions <https://gitlab.freedesktop.org/freedesktop/freedesktop/-/wikis/home>`_.
- `Fork libinput <https://gitlab.freedesktop.org/libinput/libinput/-/forks/new>`_
into your username's namespace. Select public visibility.
- 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). git will call this repository ``gitlab``. ::
cd /path/to/libinput.git
git remote add gitlab git@ssh.gitlab.freedesktop.org:USERNAME/libinput.git
git fetch gitlab
- Create a new branch and commit your changes to that branch. ::
git switch -C mynewbranch
# edit files, make changes
git add file1 file2
git commit -s
# edit commit message in the editor
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`` ``main`` 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
<https://docs.gitlab.com/ee/ci/pipelines/#pipeline-mini-graphs>`__). 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
<https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History>`__
to learn how to change multiple commits, or squash new changes into older
commits.
------------------------------------------------------------------------------
Commit History
------------------------------------------------------------------------------
libinput strives to have a
`linear, 'recipe' style history <http://www.bitsnbites.eu/git-history-work-log-vs-recipe/>`_
This means that every commit should be small, digestible, stand-alone, and
functional. Rather than a purely chronological commit history like this: ::
doc: final docs for view transforms
fix tests when disabled, redo broken doc formatting
better transformed-view iteration (thanks Hannah!)
try to catch more cases in tests
tests: add new spline test
fix compilation on splines
doc: notes on reticulating splines
compositor: add spline reticulation for view transforms
We aim to have a clean history which only reflects the final state, broken up
into functional groupings: ::
compositor: add spline reticulation for view transforms
compositor: new iterator for view transforms
tests: add view-transform correctness tests
doc: fix Doxygen formatting for view transforms
This ensures that the final patch series only contains the final state,
without the changes and missteps taken along the development process.
The first line of a commit message should contain a prefix indicating
what part is affected by the patch followed by one sentence that
describes the change. For example: ::
touchpad: add software button behavior
fallback: disable button debouncing on device foo
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
------------------------------------------------------------------------------
When you re-send patches, revised or not, it would be very good to document the
changes compared to the previous revision in the commit message and/or the
merge request. If you have already received Reviewed-by or Acked-by tags, you
should evaluate whether they still apply and include them in the respective
commit messages. Otherwise the tags may be lost, reviewers miss the credit they
deserve, and the patches may cause redundant review effort.
If your commit solves a GitLab issue, add a ``Closes:`` tag followed by the
issue number at the end of your commit message. For example: ::
Closes: #974
If your commit fixes an issue introduced by another commit, use a ``Fixes`` tag
followed by the first 12 characters of the SHA-1 ID and the commit one line
summary at the end of your commit message. For example: ::
Fixes: 123456789012 ("The commit that caused the issue")
For further reading, please see
`'on commit messages' <http://who-t.blogspot.de/2009/12/on-commit-messages.html>`_
as a general guideline on what commit messages should contain.
------------------------------------------------------------------------------
Coding Style
------------------------------------------------------------------------------
Please see the `CODING_STYLE.md
<https://gitlab.freedesktop.org/libinput/libinput/blob/main/CODING_STYLE.md>`_
document in the source tree.
------------------------------------------------------------------------------
Tracking patches and follow-ups
------------------------------------------------------------------------------
Once submitted to GitLab, your patches will be reviewed by the libinput
development team on GitLab. Review may be entirely positive and result in your
code landing instantly, in which case, great! You're done. However, we may ask
you to make some revisions: fixing some bugs we've noticed, working to a
slightly different design, or adding documentation and tests.
If you do get asked to revise the patches, please bear in mind the notes above.
You should use ``git rebase -i`` to make revisions, so that your patches
follow the clear linear split documented above. Following that split makes
it easier for reviewers to understand your work, and to verify that the code
you're submitting is correct.
A common request is to split single large patch into multiple patches. This can
happen, for example, if when adding a new feature you notice a bug in
libinput's core which you need to fix to progress. Separating these changes
into separate commits will allow us to verify and land the bugfix quickly,
pushing part of your work for the good of everyone, whilst revision and
discussion continues on the larger feature part. It also allows us to direct
you towards reviewers who best understand the different areas you are
working on.
When you have made any requested changes, please rebase the commits, verify
that they still individually look good, then force-push your new branch to
GitLab. This will update the merge request and notify everyone subscribed to
your merge request, so they can review it again.
There are also many GitLab CLI clients, if you prefer to avoid the web
interface. It may be difficult to follow review comments without using the
web interface though, so we do recommend using this to go through the review
process, even if you use other clients to track the list of available
patches.
------------------------------------------------------------------------------
Failed pipeline errors
------------------------------------------------------------------------------
After submitting your merge request to GitLab, you might receive an email
informing you that your pipeline failed.
Visit your merge request page and check the `pipeline mini graph
<https://docs.gitlab.com/ee/ci/pipelines/#pipeline-mini-graphs>`_ to know which
step failed.
Follow the appropriate section to fix the errors.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Committed gitlab-ci.yml differs from generated gitlab-ci.yml. Please verify
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When your merge request modifies the CI templates, you might see this error
mainly due two reasons: the wrong file was modified and/or
``ci-fairy generate-template`` wasn't run.
``.gitlab-ci.yaml`` is auto generated, changes should be made in:
- ``.gitlab-ci/ci.template``
- ``.gitlab-ci/config.yaml``
Once the changes are ready, run
`ci-fairy <https://freedesktop.pages.freedesktop.org/ci-templates/ci-fairy.html#templating-gitlab-ci-yml>`_
to update ``.gitlab-ci.yaml``: ::
ci-fairy generate-template
Finally, force-push you changes. See :ref:`contributing_submitting_code` for
more details.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Build errors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Usually, checking the CI log is enough to catch this errors. However, your merge
request is built using different configurations you might have not tested.
In order to fix this kind of problems, you can compile libinput using the same
flags used by the CI.
For example, if an error is found in the ``build-no-libwacom`` step, open the
log and search the build options: ::
[...]
+ rm -rf 'build dir'
+ meson 'build dir' -Dlibwacom=false
The Meson build system
[...]
Use the same flags to fix the issue and force-push you changes. See
:ref:`contributing_submitting_code` for more details.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Test errors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The test suite is run for your merge request to check for bugs, regressions and
memory leaks among other issues.
Open the CI error log and search for a message similar to: ::
:: Failure: ../test/test-touchpad.c:465: touchpad_2fg_scroll_slow_distance(synaptics-t440)
See :ref:`test-suite` to learn how to run the failing tests.
Once the tests are fixed, force-push you changes. See
:ref:`contributing_submitting_code` for more details.

View file

@ -1,21 +0,0 @@
.. warning:: The package lists are autogenerated from the `CI <https://gitlab.freedesktop.org/libinput/libinput/-/tree/master/.gitlab-ci.yml>`_.
- 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@

View file

@ -1,53 +0,0 @@
.. _development:
==============================================================================
Information for developers
==============================================================================
Below is a list of topics of interest to developers, divided into
information for those :ref:`using_libinput_as_library` in a Wayland compositor
or other project. The :ref:`hacking_on_libinput` section applies to developers working on
libinput itself.
.. note:: If you use or work on libinput you should get in touch with the
libinput developers on the wayland-devel@lists.freedesktop.org
mailing lists
.. _using_libinput_as_library:
------------------------------------------------------------------------------
Using libinput as library
------------------------------------------------------------------------------
See :ref:`building_against` for information on how to integrate libinput
with your project's build system.
.. note:: **libinput's API documentation is available here:**
http://wayland.freedesktop.org/libinput/doc/latest/api/
Topics below explain some behaviors of libinput.
.. toctree::
:maxdepth: 1
absolute-axes.rst
absolute-coordinate-ranges.rst
normalization-of-relative-motion.rst
seats.rst
timestamps.rst
wheel-api.rst
.. _hacking_on_libinput:
------------------------------------------------------------------------------
Hacking on libinput
------------------------------------------------------------------------------
.. toctree::
:maxdepth: 1
architecture
test-suite.rst
pointer-acceleration.rst
device-configuration-via-udev.rst

View file

@ -1,245 +0,0 @@
.. _udev_config:
==============================================================================
Static device configuration via udev
==============================================================================
libinput supports some static configuration through udev properties.
These properties are read when the device is initially added
to libinput's device list, i.e. before the
**LIBINPUT_EVENT_DEVICE_ADDED** event is generated.
The following udev properties are supported:
LIBINPUT_CALIBRATION_MATRIX
Sets the calibration matrix, see
**libinput_device_config_calibration_get_default_matrix()**. If unset,
defaults to the identity matrix.
The udev property is parsed as 6 floating point numbers separated by a
single space each (scanf(3) format ``"%f %f %f %f %f %f"``).
The 6 values represent the first two rows of the calibration matrix as
described in **libinput_device_config_calibration_set_matrix()**.
Example values are: ::
ENV{LIBINPUT_CALIBRATION_MATRIX}="1 0 0 0 1 0" # default
ENV{LIBINPUT_CALIBRATION_MATRIX}="0 -1 1 1 0 0" # 90 degree clockwise
ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 0 -1 1" # 180 degree clockwise
ENV{LIBINPUT_CALIBRATION_MATRIX}="0 1 0 -1 0 1" # 270 degree clockwise
ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 0 1 0" # reflect along y axis
LIBINPUT_DEVICE_GROUP
A string identifying the **libinput_device_group** for this device. Two
devices with the same property value are grouped into the same device group,
the value itself is irrelevant otherwise.
LIBINPUT_IGNORE_DEVICE
If set to anything other than "0", the device is ignored by libinput.
See :ref:`ignoring_devices` for more details.
ID_SEAT
Assigns the physical :ref:`seat <seats>` for this device. See
**libinput_seat_get_physical_name()**. Defaults to "seat0".
ID_INPUT
If this property is set, the device is considered an input device. Any
device with this property missing will be ignored, see :ref:`udev_device_type`.
ID_INPUT_KEYBOARD, ID_INPUT_KEY, ID_INPUT_MOUSE, ID_INPUT_TOUCHPAD, ID_INPUT_TOUCHSCREEN, ID_INPUT_TABLET, ID_INPUT_JOYSTICK, ID_INPUT_ACCELEROMETER
If any of the above is set, libinput initializes the device as the given
type, see :ref:`udev_device_type`. Note that for historical reasons more than
one of these may be set at any time, libinput will select only one of these
to determine the device type. To ensure libinput selects the correct device
type, only set one of them.
WL_SEAT
Assigns the logical :ref:`seat <seats>` for this device. See
**libinput_seat_get_logical_name()** context. Defaults to "default".
MOUSE_DPI
HW resolution and sampling frequency of a relative pointer device.
See :ref:`motion_normalization` for details.
MOUSE_WHEEL_CLICK_ANGLE
The angle in degrees for each click on a mouse wheel. See
**libinput_pointer_get_axis_source()** for details.
Below is an example udev rule to assign "seat1" to a device from vendor
``0x012a`` with the model ID of ``0x034b``. ::
$ cat /etc/udev/rules.d/99-my-device-is-on-seat1.rules
ACTION!="remove", KERNEL=="event[0-9]*", \
ENV{ID_VENDOR_ID}=="012a", \
ENV{ID_MODEL_ID}=="034b", \
ENV{ID_SEAT}="seat1"
.. _udev_device_type:
------------------------------------------------------------------------------
Device type assignment via udev
------------------------------------------------------------------------------
libinput requires the **ID_INPUT** property to be set on a device,
otherwise the device will be ignored. In addition, one of
**ID_INPUT_KEYBOARD, ID_INPUT_KEY, ID_INPUT_MOUSE, ID_INPUT_TOUCHPAD,
ID_INPUT_TOUCHSCREEN, ID_INPUT_TABLET, ID_INPUT_JOYSTICK,
ID_INPUT_ACCELEROMETER** must be set on the device to determine the
device type. The usual error handling applies within libinput and a device
type label does not guarantee that the device is initialized by libinput.
If a device fails to meet the requirements for a device type (e.g. a keyboard
labelled as touchpad) the device will not be available through libinput.
Only one device type should be set per device at a type, though libinput can
handle some combinations for historical reasons.
Below is an example udev rule to remove an **ID_INPUT_TOUCHPAD** setting
and change it into an **ID_INPUT_TABLET** setting. This rule would apply
for a device with the vendor/model ID of ``012a``/``034b``. ::
$ cat /etc/udev/rules.d/99-my-device-is-a-tablet.rules
ACTION!="remove", KERNEL=="event[0-9]*", \
ENV{ID_VENDOR_ID}=="012a", \
ENV{ID_MODEL_ID}=="034b", \
ENV{ID_INPUT_TOUCHPAD}="", ENV{ID_INPUT_TABLET}="1"
.. _model_specific_configuration:
------------------------------------------------------------------------------
Model-specific configuration
------------------------------------------------------------------------------
As of libinput 1.12, model-specific configuration is stored in the
:ref:`device-quirks` and not in the hwdb anymore. Please see
:ref:`device-quirks` for
details.
.. _model_specific_configuration_x220fw81:
..............................................................................
Lenovo x220 with touchpad firmware v8.1
..............................................................................
The property **LIBINPUT_MODEL_LENOVO_X220_TOUCHPAD_FW81** may be set by a
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
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.
The touchpad firmware version cannot be detected automatically by libinput,
local configuration is required to set this property. Refer to the libinput
model quirks hwdb for instructions.
This property must not be used for any other purpose, no specific behavior
is guaranteed.
.. _hwdb:
------------------------------------------------------------------------------
Configuring the hwdb
------------------------------------------------------------------------------
This section outlines how to query the
`udev hwdb <https://www.freedesktop.org/software/systemd/man/hwdb.html>`_
and reload properties so they are available to libinput.
The hwdb contains a set of match rules that assign udev properties that are
available to libinput when the device is connected and/or libinput is
initialized. This section only describes the hwdb in relation to libinput,
it is not a full documentation on how the hwdb works.
libinput's use of the hwdb is limited to properties systemd and custom
rules files (where available) provide. Hardware-specific quirks as used by
libinput are in the :ref:`device-quirks` system.
.. _hwdb_querying:
..............................................................................
Querying the hwdb
..............................................................................
libinput only uses device nodes in the form of ``/dev/input/eventX`` where X
is the number of the specific device. Running ``libinput debug-events`` lists
all devices currently available to libinput and their event node name: ::
$> sudo libinput debug-events
-event2 DEVICE_ADDED Power Button seat0 default group1 cap:k
-event5 DEVICE_ADDED Video Bus seat0 default group2 cap:k
-event0 DEVICE_ADDED Lid Switch seat0 default group3 cap:S
...
Note the event node name for your device and translate it into a syspath in
the form of ``/sys/class/input/eventX``. This path can be supplied to ``udevadm
info`` ::
$> udevadm info
P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0D:00/input/input0/event0
N: input/event0
E: DEVNAME=/dev/input/event0
E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0D:00/input/input0/event0
E: ID_INPUT=1
E: ID_INPUT_SWITCH=1
E: MAJOR=13
E: MINOR=64
E: SUBSYSTEM=input
E: TAGS=:power-switch:
E: USEC_INITIALIZED=7167898
Lines starting with ``E:`` are udev properties available to libinput. For
example, the above device's ``ID_INPUT_SWITCH`` property will cause libinput
to treat this device as switch device.
.. _hwdb_reloading:
..............................................................................
Reloading the hwdb
..............................................................................
The actual hwdb is stored in binary file on-disk and must be updated
manually whenever a ``.hwdb`` file changes. This is required both when a user
manually edits the ``.hwdb`` file but also when the git tree is updated (and
that update causes a hwdb change).
To update the binary file on-disk, run: ::
sudo systemd-hwdb update
Then, to trigger a reload of all properties on your device, run: ::
sudo udevadm trigger /sys/class/input/eventX
Then check with ``udevadm info`` whether the properties were updated, see
:ref:`hwdb_querying`. If a new property does not appear on the device, use ``udevadm
test`` to check for error messages by udev and the hwdb (e.g. syntax errors
in the udev rules files). ::
sudo udevadm test /sys/class/input/eventX
.. warning:: ``udevadm test`` does not run commands specified in ``RUN``
directives. This affects the udev properties relying on e.g.
the udev keyboard builtin such as the :ref:`touchpad_jitter`
workarounds.
.. _hwdb_modifying:
..............................................................................
Modifying the hwdb
..............................................................................
.. warning:: This section has been removed as it no longer applies in libinput 1.12
and later. libinput users should not need to modify the hwdb, any
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 available in: https://wayland.freedesktop.org/libinput/doc/

Some files were not shown because too many files have changed in this diff Show more