Compare commits

..

20 commits
main ... 1.14.3

Author SHA1 Message Date
Peter Hutterer
94b5be448e libinput 1.14.3
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-10-28 13:34:31 +10:00
Peter Hutterer
39d353ddcb CI: UI improvements
This should not change the overall time, but allows for a nicer
UI when looking at the pipelines:

* first "check" icon is the container_prep stage
* second icon is all of the variations of builds
* third is the full test suite in the VM
* forth is the distribution specifics
* last one is the deploy

This allows to see which step fails from the UI instead of having
a lengthy list of jobs all in the same column.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
(cherry picked from commit 44b5fea14e)
2019-10-28 13:29:28 +10:00
Peter Hutterer
e4fdb5fe86 gitlab CI: run the valgrind test suite as well
Separate instance so we can speed things up a bit.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 16ad7cca28)
2019-10-28 13:11:56 +10:00
Peter Hutterer
f634256ab0 doc/user: drop markdown source parsers
This is deprecated in sphinx 1.8 but we don't include any markdown sources
anyway, so let's just drop it.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 058e198067)
2019-10-28 13:11:19 +10:00
John Chadwick
65cfa032a0 tablet: Improve forced prox out behavior.
Some graphics tablets (most or all Wacom, for example) do not emit
proximity out events when the tablet pen goes out of range. To
compensate for this, libinput synthesizes proximity out events when no
events are received for a certain period of time. Unfortunately, on some
tablets, this is fairly failure prone when moving the pen slowly. As a
workaround, this patch causes libinput to avoid synthesizing proximity
out events when the pen is still in contact with the tablet pad, as
defined by the TABLET_TOOL_IN_CONTACT status.

(cherry picked from commit 8568cf1b3a)
2019-10-25 15:37:54 +10:00
Peter Hutterer
68b471b31f fallback: don't send a single-touch motion if we just sent a begin
Any touch down event will also provide motion data, but we must not send a
motion event for those in the same frame as the down event.

Fixes #375

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit f392766155)
2019-10-24 11:12:32 +10:00
Balazs Endresz
47df5c173a Fix horizontal scrolling for Logitech MX Master 3 on bluetooth
(cherry picked from commit 8c92328dc5)
2019-10-24 11:12:32 +10:00
Peter Hutterer
e3d402fa3c touchpad: use the same speed for scrolling as the baseline of the accel curve
Scrolling and gestures use unaccelerated motion. The idea behind it was that
at least for the default speed setting of 0, the accelerated speed and
unaccelerated speed are identical where meaningful.

The touchpad speed curve has a plateau for 'normal' speeds (i.e. not very slow
and not very fast) where the acceleration factor is constant. This is the
reference factor that the unaccelerated motion should use as well.

Since the touchpad acceleration rework in d6e5313497 the reference factor is
0.9 * TP_MAGIC_SLOWDOWN (previously the factor was 1.0 * TP_MAGIC_SLOWDOWN)
and scroll motion is thus 10% faster than the pointer movement at the default
speeds. Let's fix this and let the two match up.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 2b33445bc9)
2019-10-24 11:12:32 +10:00
Peter Hutterer
f65b1a2e33 libinput 1.14.2
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-10-17 10:15:28 +10:00
Benjamin Tissoires
6dc9de071e gitlab-ci: use one sha1 instead of duplicates
because we can

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
(cherry picked from commit 779ce028c3)
2019-10-16 13:38:37 +10:00
Benjamin Tissoires
fa10459082 gitlab-ci: use qemu to run the full test suite
We currently allow the stage to fail, but at least,
we can make use of it.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
(cherry picked from commit 60595e1cbb)
2019-10-16 13:38:34 +10:00
yy
34a7365235 Added quirk for Lenovo ThinkPad X200 Tablet.
(cherry picked from commit 863aa2b706)
2019-10-16 13:38:25 +10:00
Jakub Schmidtke
62382f7d79 Fixed horizontal scrolling on Logitech MX Master 2S/3
Logitech MX Master 2S and 3 by default use natural scrolling
for the horizontal scroll wheel, while the main wheel
uses traditional mode. This change inverts the default
direction of horizontal scrolling.

(cherry picked from commit 8490384c68)
2019-10-16 13:38:23 +10:00
John Chadwick
a7d2b749f3 test: Make udev_properties array fixed-size.
The udev_properties array is currently variable length, which causes the
tests to invoke undefined behavior on empty lists, as it attempts to
access the first array item to check if the key is NULL, which is an out
of bounds read and will fail when the struct alignment happens to line
up such that there is no padding after the list in the empty list case.

By making the udev_properties array 32 items long, it can encapsulate
every existing case, with only a fairly small amount of memory overhead,
and without requiring every single `TEST_DEVICE` call to initialize
`udev_properties`.

(cherry picked from commit b71a1b6e2d)
2019-10-16 13:38:11 +10:00
Peter Hutterer
c8daa2c0a1 gestures: where we have more fingers than slots, default to swipe
Fixes #360

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit cb1be90439)
2019-10-16 13:37:50 +10:00
Peter Hutterer
093a87898b touchpad: only identify for pinch in a distinct pinch position
Previously, any lower finger spaced more than the vertical threshold apart
would be labelled as thumb. This causes some taps to be detected as
single-taps, particularly where the user's hand is at an angle that causes the
touches to be effectively vertical.

Restructure that condition so that we only go for a thumb if we're
distinctively apart, and we only *not* go for thumb if we're distinctively
close together.

Fixes #359

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 0ce06d1314)
2019-10-16 13:37:43 +10:00
Serhii Chaplia
ad7708f6a5 Touchpad fix and trackpoint speed adjustment for Lenovo T490s
Same issue as #177

(cherry picked from commit 79e91f8a30)
2019-10-16 13:37:30 +10:00
Richard McIntosh
b927b42235 Added magic trackpoint multiplier for Thinkpad 13 G2
(cherry picked from commit 4f9a795765)
2019-10-16 13:36:45 +10:00
RussianNeuroMancer
b9ba9e7236 Mark HP Elite x2 1013 G3 keyboard as external
Keyboard+touchpad is external:
http://h10032.www1.hp.com/ctg/Manual/c06077534 (page 12)

(cherry picked from commit 8635d546ce)
2019-10-16 13:36:42 +10:00
RussianNeuroMancer
535cc9879b Tablet Mode Switch on HP Elite x2 1013 G3 is unreliable:
https://bugzilla.kernel.org/show_bug.cgi?id=204719
https://bugzilla.kernel.org/show_bug.cgi?id=204739

Keyboard+touchpad is external:
http://h10032.www1.hp.com/ctg/Manual/c06077534 (page 12)

(cherry picked from commit 3c13dd9ccd)
2019-10-16 13:36:41 +10:00
453 changed files with 28487 additions and 79890 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,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

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

@ -0,0 +1,13 @@
#!/bin/bash
set -e
set -x
export DEBIAN_FRONTEND=noninteractive
apt-get install -y software-properties-common
add-apt-repository universe
apt-get update
apt-get -y upgrade
apt-get install -y $@

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

@ -0,0 +1,31 @@
## 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 one can reproduce the issue - this is very important -->
## libinput version you encountered the bug on
<!-- Note: if your libinput version is older than the current stable version,
please reproduce with a current version instead -->
## Hardware information:
<!-- Model name/number and general hardware information if applicable -->
## Other log output:
- `libinput record` output: <!-- attach file here -->
- `libinput debug-events --verbose` output: <!-- attach file here -->
<!-- Paste any other relevant logs - please use code blocks (```) to format
console output, logs, and code as it's very hard to read otherwise.) -->
/label ~bug ~"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

View file

@ -1,4 +1,3 @@
# Coding style
- Indentation in tabs, 8 characters wide, spaces after the tabs where - Indentation in tabs, 8 characters wide, spaces after the tabs where
vertical alignment is required (see below) vertical alignment is required (see below)
@ -52,102 +51,51 @@ somenamethatiswaytoolong(int a,
- if it generates a static checker warning, it needs to be fixed or - if it generates a static checker warning, it needs to be fixed or
commented commented
- declare variables when they are used first and try to keep them as local as possible. - declare variables at the top, try to keep them as local as possible.
Exception: basic loop variables, e.g. for (int i = 0; ...) should always be Exception: if the same variable is re-used in multiple blocks, declare it
declared inside the loop even where multiple loops exist at the top.
Exception: basic loop variables, e.g. for (int i = 0; ...)
```c ```c
int a; int a;
int c;
if (foo) { if (foo) {
int b = 10; int b;
a = get_value(); c = get_value();
usevalue(a, b); usevalue(c);
} }
if (bar) { if (bar) {
a = get_value(); c = get_value();
useit(a); useit(c);
} }
int c = a * 100;
useit(c);
``` ```
- avoid uninitialized variables where possible, declare them late instead. - do not mix function invocations and variable definitions.
Note that most of libinput predates this style, try to stick with the code
around you if in doubt.
wrong: wrong:
```c ```c
int *a; {
int a = foo();
int b = 7; int b = 7;
}
... some code ...
a = zalloc(32);
``` ```
right: right:
```c ```c
{
int a;
int b = 7; int b = 7;
... some code ...
int *a = zalloc(32); a = foo();
```
- 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: There are exceptions here, e.g. `tp_libinput_context()`,
```c `litest_current_device()`
{
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 - 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 statement. If either if or else block are multiple statements, both must
@ -185,60 +133,3 @@ if (foo) {
- Use stdbool.h's bool for booleans within the library (instead of `int`). - Use stdbool.h's bool for booleans within the library (instead of `int`).
Exception: the public API uses int, not bool. 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 version libinput is compiled against. The header is used during compilation
only, libinput does not link against GPL libraries. only, libinput does not link against GPL libraries.
[1] https://gitlab.freedesktop.org/libinput/libinput/blob/main/include/linux/input.h [1] https://gitlab.freedesktop.org/libinput/libinput/blob/master/include/linux/input.h

View file

@ -60,8 +60,8 @@ Examples of how to use libinput are the debugging tools in the libinput
repository. Developers are encouraged to look at those tools for a repository. Developers are encouraged to look at those tools for a
real-world (yet simple) example on how to use libinput. 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 commandline debugging tool: https://gitlab.freedesktop.org/libinput/libinput/tree/master/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 - A GTK application that draws cursor/touch/tablet positions: https://gitlab.freedesktop.org/libinput/libinput/tree/master/tools/libinput-debug-gui.c
License License
------- -------
@ -75,10 +75,10 @@ libinput is licensed under the MIT license.
> and/or sell copies of the Software, and to permit persons to whom the > 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: [...] > Software is furnished to do so, subject to the following conditions: [...]
See the [COPYING](https://gitlab.freedesktop.org/libinput/libinput/tree/main/COPYING) See the [COPYING](https://gitlab.freedesktop.org/libinput/libinput/tree/master/COPYING)
file for the full license information. file for the full license information.
About About
----- -----
Documentation generated from git commit [__GIT_VERSION__](https://gitlab.freedesktop.org/libinput/libinput/commit/__GIT_VERSION__) Documentation generated by from git commit [__GIT_VERSION__](https://gitlab.freedesktop.org/libinput/libinput/commit/__GIT_VERSION__)

View file

@ -7,9 +7,7 @@
"list-devices:List all devices recognized by libinput" "list-devices:List all devices recognized by libinput"
"debug-events:Print all events as seen by libinput" "debug-events:Print all events as seen by libinput"
"debug-gui:Show a GUI to visualize libinput's events" "debug-gui:Show a GUI to visualize libinput's events"
"debug-tablet:Show tablet axis and button values"
"measure:Measure various properties of devices" "measure:Measure various properties of devices"
"analyze:Analyze device data"
"record:Record the events from a device" "record:Record the events from a device"
"replay:Replay the events from a device" "replay:Replay the events from a device"
) )
@ -45,61 +43,40 @@ __all_seats()
'--verbose[Use verbose output]' \ '--verbose[Use verbose output]' \
'--show-keycodes[Make all keycodes visible]' \ '--show-keycodes[Make all keycodes visible]' \
'--grab[Exclusively grab all opened devices]' \ '--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/' \ '--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' \ '--udev=[Listen for notifications on the given seat]:seat:__all_seats' \
'--apply-to=[Apply configuration options where the device name matches the pattern]:pattern' \ '--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' \ '--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-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-scroll-method=[Set the desired scroll method]:scroll-method:(none twofinger edge button)' \
'--set-scroll-button=[Set the button to the given button code]' \
'--set-profile=[Set pointer acceleration profile]:accel-profile:(adaptive flat)' \
'--set-speed=[Set pointer acceleration speed (within range \[-1, 1\])]' \ '--set-speed=[Set pointer acceleration speed (within range \[-1, 1\])]' \
'--set-tap-map=[Set button mapping for tapping]:tap-map:(( \ '--set-tap-map=[Set button mapping for tapping]:tap-map:(( \
lrm\:2-fingers\ right-click\ /\ 3-fingers\ middle-click \ lrm\:2-fingers\ right-click\ /\ 3-fingers\ middle-click \
lmr\:2-fingers\ middle-click\ /\ 3-fingers\ right-click \ lmr\:2-fingers\ middle-click\ /\ 3-fingers\ right-click \
))' \ ))' \
+ '(custom pointer acceleration)' \ + '(tap-to-click)' \
'--set-custom-points=[Set n points defining a custom acceleration function]' \ '--enable-tap[Enable tap-to-click]' \
'--set-custom-step=[Set the distance along the x axis between the custom points]' \ '--disable-tap[Disable tap-to-click]' \
'--set-custom-type=[Set the type of the acceleration function]:custom-type:(fallback motion scroll)' \
+ '(drag)' \ + '(drag)' \
'--enable-drag[Enable tap-and-drag]' \ '--enable-drag[Enable tap-and-drag]' \
'--disable-drag[Disable tap-and-drag]' \ '--disable-drag[Disable tap-and-drag]' \
+ '(drag-lock)' \ + '(drag-lock)' \
'--enable-drag-lock[Enable drag-lock]' \ '--enable-drag-lock[Enable drag-lock]' \
'--disable-drag-lock[Disable drag-lock]' \ '--disable-drag-lock[Disable drag-lock]' \
+ '(dwt)' \ + '(natural-scrolling)' \
'--enable-dwt[Enable disable-while-typing]' \ '--enable-natural-scrolling[Enable natural scrolling]' \
'--disable-dwt[Disable disable-while-typing]' \ '--disable-natural-scrolling[Disable natural scrolling]' \
+ '(dwtp)' \
'--enable-dwtp[Enable disable-while-trackpointing]' \
'--disable-dwtp[Disable disable-while-trackpointing]' \
+ '(left-handed)' \ + '(left-handed)' \
'--enable-left-handed[Enable left handed button configuration]' \ '--enable-left-handed[Enable left handed button configuration]' \
'--disable-left-handed[Disable left handed button configuration]' \ '--disable-left-handed[Disable left handed button configuration]' \
+ '(middlebutton)' \ + '(middlebutton)' \
'--enable-middlebutton[Enable middle button emulation]' \ '--enable-middlebutton[Enable middle button emulation]' \
'--disable-middlebutton[Disable middle button emulation]' \ '--disable-middlebutton[Disable middle button emulation]' \
+ '(natural-scrolling)' \ + '(dwt)' \
'--enable-natural-scrolling[Enable natural scrolling]' \ '--enable-dwt[Enable disable-while-typing]' \
'--disable-natural-scrolling[Disable natural scrolling]' \ '--disable-dwt[Disable enable-while-typing]'
+ '(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() (( $+functions[_libinput_debug-gui] )) || _libinput_debug-gui()
@ -112,15 +89,6 @@ __all_seats()
'--udev=[Listen for notifications on the given seat]:seat:_libinput_all_seats' '--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() (( $+functions[_libinput_measure] )) || _libinput_measure()
{ {
local curcontext=$curcontext state line ret=1 local curcontext=$curcontext state line ret=1
@ -180,71 +148,20 @@ __all_seats()
{ {
_arguments \ _arguments \
'--help[Show help message and exit]' \ '--help[Show help message and exit]' \
'--format=dat[Specify the data format to be printed. The default is "summary"]' \ '--format=dat[Specify the data format to be printed. The default is "summary"]'
':device:_files -W /dev/input/ -P /dev/input/' ':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() (( $+functions[_libinput_record] )) || _libinput_record()
{ {
_arguments \ _arguments \
'--help[Show help message and exit]' \ '--help[Show help message and exit]' \
'--all[Record all /dev/input/event* devices available on the system]' \ '--all[Record all /dev/input/event* devices available on the system]' \
'--autorestart=[Terminate the current recording after s seconds of device inactivity]' \ '--autorestart=[Terminate the current recording after s seconds of device inactivity]' \
{-o+,--output=}'[Specify the output file to use]:file:_files -g "*.yml"' \ {-o+,--output=}'[Speficy the output file to use]:file:_files -g "*.yml"' \
'--multiple[Record multiple devices at once]' \ '--multiple[Record multiple devices at once]' \
'--show-keycodes[Show keycodes as-is in the recording]' \ '--show-keycodes[Show keycodes as-is in the recording]' \
'--with-libinput[Record libinput events alongside device events]' \ '--with-libinput[Record libinput events alongside device events]' \
'--with-hidraw[Record hidraw events alongside device events]' \
'*::device:_files -W /dev/input/ -P /dev/input/' '*::device:_files -W /dev/input/ -P /dev/input/'
} }

View file

@ -1,6 +1,6 @@
zshcompletiondir = get_option('zshcompletiondir') zshcompletiondir = get_option('zshcompletiondir')
if zshcompletiondir == '' if zshcompletiondir == ''
zshcompletiondir = get_option('datadir') / 'zsh' / 'site-functions' zshcompletiondir = join_paths(get_option('datadir'), 'zsh', 'site-functions')
endif endif
if zshcompletiondir != 'no' if zshcompletiondir != 'no'

View file

@ -10,10 +10,10 @@ MAX_INITIALIZER_LINES = 0
WARNINGS = YES WARNINGS = YES
QUIET = YES QUIET = YES
INPUT = "@builddir@" INPUT = "@builddir@"
FILTER_PATTERNS = *.h *.dox
IMAGE_PATH = "@builddir@" IMAGE_PATH = "@builddir@"
OUTPUT_DIRECTORY = doc
GENERATE_HTML = YES GENERATE_HTML = YES
HTML_OUTPUT = html HTML_OUTPUT = api
SEARCHENGINE = NO SEARCHENGINE = NO
USE_MATHJAX = YES USE_MATHJAX = YES
MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
@ -25,7 +25,6 @@ PREDEFINED = LIBINPUT_ATTRIBUTE_PRINTF(f, a)= \
DOTFILE_DIRS = "@builddir@" DOTFILE_DIRS = "@builddir@"
EXAMPLE_PATH = "@builddir@" EXAMPLE_PATH = "@builddir@"
SHOW_NAMESPACES = NO SHOW_NAMESPACES = NO
HAVE_DOT = YES
HTML_HEADER = "@builddir@/header.html" HTML_HEADER = "@builddir@/header.html"
HTML_FOOTER = "@builddir@/footer.html" HTML_FOOTER = "@builddir@/footer.html"

View file

@ -130,6 +130,6 @@ release.
@section About @section About
Documentation generated from git commit [__GIT_VERSION__](https://gitlab.freedesktop.org/libinput/libinput/commit/__GIT_VERSION__) Documentation generated by from git commit [__GIT_VERSION__](https://gitlab.freedesktop.org/libinput/libinput/commit/__GIT_VERSION__)
*/ */

View file

@ -9,6 +9,26 @@ if not dot.found()
error('Program "dot" not found or not executable. Try building with -Ddocumentation=false') error('Program "dot" not found or not executable. Try building with -Ddocumentation=false')
endif endif
doxygen_version_cmd = run_command(doxygen.path(), '--version')
if doxygen_version_cmd.returncode() != 0
error('Command "doxygen --version" failed.')
endif
doxygen_version = doxygen_version_cmd.stdout()
if doxygen_version.version_compare('< 1.8.3')
error('doxygen needs to be at least version 1.8.3 (have @0@)'.format(doxygen_version))
endif
grep = find_program('grep')
dot_version_cmd = run_command(dot.path(), '-V')
if dot_version_cmd.returncode() != 0
error('Command "dot -V" failed.')
endif
# dot -V output is (to stderr):
# dot - graphviz version 2.38.0 (20140413.2041)
dot_version = dot_version_cmd.stderr().split(' ')[4]
if dot_version.version_compare('< 2.26')
error('Graphviz dot needs to be at least version 2.26 (have @0@)'.format(dot_version))
endif
mainpage = vcs_tag(command : ['git', 'log', '-1', '--format=%h'], mainpage = vcs_tag(command : ['git', 'log', '-1', '--format=%h'],
fallback : 'unknown', fallback : 'unknown',
input : 'mainpage.dox', input : 'mainpage.dox',
@ -17,7 +37,7 @@ mainpage = vcs_tag(command : ['git', 'log', '-1', '--format=%h'],
src_doxygen = files( src_doxygen = files(
# source files # source files
'../../src/libinput.h', join_paths(meson.source_root(), 'src', 'libinput.h'),
# style files # style files
'style/header.html', 'style/header.html',
'style/footer.html', 'style/footer.html',
@ -26,11 +46,19 @@ src_doxygen = files(
'style/libinputdoxygen.css', 'style/libinputdoxygen.css',
) )
config_noop = configuration_data()
# Set a dummy replacement to silence meson warnings:
# meson.build:487: WARNING: Got an empty configuration_data() object and
# found no substitutions in the input file 'foo'. If you
# want to copy a file to the build dir, use the 'copy:'
# keyword argument added in 0.47.0
config_noop.set('dummy', 'dummy')
doxyfiles = [] doxyfiles = []
foreach f : src_doxygen foreach f : src_doxygen
df = configure_file(input: f, df = configure_file(input: f,
output: '@PLAINNAME@', output: '@PLAINNAME@',
copy : true) configuration : config_noop)
doxyfiles += [ df ] doxyfiles += [ df ]
endforeach endforeach
@ -45,7 +73,7 @@ doxyfile = configure_file(input : 'libinput.doxygen.in',
custom_target('doxygen', custom_target('doxygen',
input : [ doxyfiles, doxyfile, mainpage ] + src_doxygen, input : [ doxyfiles, doxyfile, mainpage ] + src_doxygen,
output : [ 'html' ], output : [ '.' ],
command : [ doxygen, doxyfile ], command : [ doxygen, doxyfile ],
install : false, install : false,
depends: [ mainpage ], depends: [ mainpage ],

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 81 KiB

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: 166 KiB

View file

@ -33,78 +33,59 @@ Measuring and fixing touchpad ranges
To fix the touchpad you need to: To fix the touchpad you need to:
#. measure the physical size of your touchpad in mm #. measure the physical size of your touchpad in mm
#. run the ``libinput measure touchpad-size`` tool #. run touchpad-edge-detector
#. verify the hwdb entry provided by this tool #. trim the udev match rule to something sensible
#. replace the resolution with the calculated resolution based on physical settings
#. test locally #. test locally
#. send a patch to the `systemd project <https://github.com/systemd/systemd>`_. #. send a patch to the systemd project
Detailed explanations are below. Detailed explanations are below.
The ``libinput measure touchpad-size`` tool is an interactive tool. It must `libevdev <http://freedesktop.org/wiki/Software/libevdev/>`_ provides a tool
be called with the physical dimensions of the touchpad in mm. In the example called **touchpad-edge-detector** that allows measuring the touchpad's input
below, we use 100mm wide and 55mm high. The tool will find the touchpad device ranges. Run the tool as root against the device node of your touchpad device
automatically. and repeatedly move a finger around the whole outside area of the
touchpad. Then control+c the process and note the output.
An example output is below:
:: ::
$> sudo libinput measure touchpad-size 100x55 $> sudo touchpad-edge-detector /dev/input/event4
Using "Touchpad SynPS/2 Synaptics TouchPad": /dev/input/event4 Touchpad SynPS/2 Synaptics TouchPad on /dev/input/event4
Move one finger around the touchpad to detect the actual edges
Kernel says: x [1024..3112], y [2024..4832]
Touchpad sends: x [2445..4252], y [3464..4071]
Kernel specified touchpad size: 99.7x75.9mm Touchpad size as listed by the kernel: 49x66mm
User specified touchpad size: 100.0x55.0mm Calculate resolution as:
x axis: 2088/<width in mm>
y axis: 2808/<height in mm>
Kernel axis range: x [1024..5112], y [2024..4832] Suggested udev rule:
Detected axis range: x [ 0.. 0], y [ 0.. 0] # <Laptop model description goes here>
evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvnLENOVO:bvrGJET72WW(2.22):bd02/21/2014:svnLENOVO:pn20ARS25701:pvrThinkPadT440s:rvnLENOVO:rn20ARS25701:rvrSDK0E50512STD:cvnLENOVO:ct10:cvrNotAvailable:*
Move one finger along all edges of the touchpad EVDEV_ABS_00=2445:4252:<x resolution>
until the detected axis range stops changing. EVDEV_ABS_01=3464:4071:<y resolution>
EVDEV_ABS_35=2445:4252:<x resolution>
... EVDEV_ABS_36=3464:4071:<y resolution>
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 Note the discrepancy between the coordinate range the kernels advertises vs.
``60-evdev.hwdb`` file provided by the `systemd project <https://github.com/systemd/systemd>`_. what the touchpad sends.
To fix the advertised ranges, the udev rule should be taken and trimmed
before being sent to the `systemd project <https://github.com/systemd/systemd>`_.
An example commit can be found An example commit can be found
`here <https://github.com/systemd/systemd/commit/26f667eac1c5e89b689aa0a1daef6a80f473e045>`_. `here <https://github.com/systemd/systemd/commit/26f667eac1c5e89b689aa0a1daef6a80f473e045>`_.
The ``libinput measure touchpad-size`` tool attempts to provide the correct In most cases the match can and should be trimmed to the system vendor (svn)
dmi match but it does require user verification. and the product version (pvr), with everything else replaced by a wildcard
(*). In this case, a Lenovo T440s, a suitable match string would be:
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* 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 .. note:: hwdb match strings only allow for alphanumeric ascii characters. Use a
wildcard (* or ?, whichever appropriate) for special characters. wildcard (* or ?, whichever appropriate) for special characters.
@ -114,19 +95,19 @@ The actual axis overrides are in the form:
:: ::
# axis number=min:max:resolution # axis number=min:max:resolution
EVDEV_ABS_00=2072:4880:28 EVDEV_ABS_00=2445:4252:42
or, if the range is correct but the resolution is wrong or, if the range is correct but the resolution is wrong
:: ::
# axis number=::resolution # axis number=::resolution
EVDEV_ABS_00=::28 EVDEV_ABS_00=::42
Note the leading single space. The axis numbers are in hex and can be found 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``, in *linux/input-event-codes.h*. For touchpads ABS_X, ABS_Y,
``ABS_MT_POSITION_X`` and ``ABS_MT_POSITION_Y`` are required. ABS_MT_POSITION_X and ABS_MT_POSITION_Y are required.
.. note:: The touchpad's ranges and/or resolution should only be fixed when .. 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 there is a significant discrepancy. A few units do not make a
@ -135,7 +116,7 @@ in ``linux/input-event-codes.h``. For touchpads ``ABS_X``, ``ABS_Y``,
Once a match and override rule has been found, follow the instructions at Once a match and override rule has been found, follow the instructions at
the top of the the top of the
`60-evdev.hwdb <https://github.com/systemd/systemd/blob/main/hwdb.d/60-evdev.hwdb>`_ `60-evdev.hwdb <https://github.com/systemd/systemd/blob/master/hwdb/60-evdev.hwdb>`_
file to save it locally and trigger the udev hwdb reload. Rebooting is 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 always a good idea. If the match string is correct, the new properties will
show up in the show up in the

View file

@ -13,10 +13,6 @@ 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 device-type-specific implementations in ``evdev-<type>.c``. It is not
necessary to understand all of libinput to contribute a patch. 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, :ref:`architecture-contexts` is the only user-visible implementation detail,
everything else is purely internal implementation and may change when everything else is purely internal implementation and may change when
required. required.
@ -154,8 +150,10 @@ pointers to handle events. Four such dispatch methods are currently
implemented: touchpad, tablet, tablet pad, and the fallback dispatch which implemented: touchpad, tablet, tablet pad, and the fallback dispatch which
handles mice, keyboards and touchscreens. handles mice, keyboards and touchscreens.
.. graphviz:: .. graphviz::
digraph context digraph context
{ {
compound=true; compound=true;
@ -179,15 +177,13 @@ handles mice, keyboards and touchscreens.
} }
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 While ``evdev.c`` pulls the event out of libevdev, the actual handling of the
events is performed within the dispatch method. events is performed within the dispatch method.
.. graphviz:: .. graphviz::
digraph context digraph context
{ {
compound=true; compound=true;
@ -198,107 +194,22 @@ events is performed within the dispatch method.
evdev [label="evdev_device_dispatch()"] evdev [label="evdev_device_dispatch()"]
plugins [label="plugin pipline"]
fallback [label="fallback_interface_process()"]; fallback [label="fallback_interface_process()"];
touchpad [label="tp_interface_process()"] touchpad [label="tp_interface_process()"]
tablet [label="tablet_process()"] tablet [label="tablet_process()"]
pad [label="pad_process()"] pad [label="pad_process()"]
evdev -> plugins; evdev -> fallback;
plugins -> fallback; evdev -> touchpad;
plugins -> touchpad; evdev -> tablet;
plugins -> tablet; evdev -> pad;
plugins -> pad;
} }
The dispatch methods then look at the ``struct evdev_frame`` and proceed to The dispatch methods then look at the ``struct input_event`` and proceed to
update the state. update the state. Note: the serialized nature of the kernel evdev protocol
requires that the device updates the state with each event but to delay
.. _architecture-plugins: processing until the ``SYN_REPORT`` event is received.
------------------------------------------------------------------------------
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: .. _architecture-configuration:

View file

@ -16,29 +16,6 @@ The build instruction on this page detail how to overwrite your
system-provided libinput with one from the git repository, see system-provided libinput with one from the git repository, see
see :ref:`reverting_install` to revert to the previous state. 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:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -55,7 +32,7 @@ process below. A successful build requires the
$> git clone https://gitlab.freedesktop.org/libinput/libinput $> git clone https://gitlab.freedesktop.org/libinput/libinput
$> cd libinput $> cd libinput
$> meson setup --prefix=/usr builddir/ $> meson --prefix=/usr builddir/
$> ninja -C builddir/ $> ninja -C builddir/
$> sudo ninja -C builddir/ install $> sudo ninja -C builddir/ install
@ -71,7 +48,7 @@ Additional options may also be specified. For example:
:: ::
$> meson setup --prefix=/usr -Ddocumentation=false builddir/ $> meson --prefix=/usr -Ddocumentation=false builddir/
We recommend that users disable the documentation, it's not usually required We recommend that users disable the documentation, it's not usually required
@ -96,7 +73,7 @@ again:
:: ::
$> rm -r builddir/ $> rm -r builddir/
$> meson setup --prefix=.... $> meson --prefix=....
.. _verifying_install: .. _verifying_install:
@ -110,10 +87,12 @@ the library path and that all symlinks point to the new library.
:: ::
$> ldconfig -p | grep libinput | awk '{print $NF}' | xargs ls -l $> ls -l /usr/lib64/libinput.*
lrwxrwxrwx 1 root root 14 lug 22 13:06 /usr/lib/x86_64-linux-gnu/libinput.so -> libinput.so.10 -rwxr-xr-x 1 root root 946 Apr 28 2015 /usr/lib64/libinput.la
lrwxrwxrwx 1 root root 19 lug 22 13:06 /usr/lib/x86_64-linux-gnu/libinput.so.10 -> libinput.so.10.13.0 lrwxrwxrwx 1 root root 19 Feb 1 15:12 /usr/lib64/libinput.so -> 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 lrwxrwxrwx 1 root root 19 Feb 1 15:12 /usr/lib64/libinput.so.10 -> libinput.so.10.13.0
-rwxr-xr-x 1 root root 204992 Feb 1 15:12 /usr/lib64/libinput.so.10.13.0
.. _reverting_install: .. _reverting_install:
@ -142,7 +121,7 @@ overwriting manually installed files.
- **Fedora 22** and later: ``sudo dnf reinstall libinput`` - **Fedora 22** and later: ``sudo dnf reinstall libinput``
- **RHEL/CentOS/Fedora 21** and earlier: ``sudo yum reinstall libinput`` - **RHEL/CentOS/Fedora 21** and earlier: ``sudo yum reinstall libinput``
- **openSUSE**: ``sudo zypper install --force libinput10`` - **openSUSE**: ``sudo zypper install --force libinput10``
- **Arch**: ``sudo pacman -S libinput`` - **Arch**: ``sudo packman -S libinput``
.. _building_selinux: .. _building_selinux:
@ -188,8 +167,8 @@ libinput has a few build-time dependencies that must be installed prior to
running meson. running meson.
.. hint:: The build dependencies for some distributions can be found in the .. 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>`_. `GitLab Continuous Integration file <https://gitlab.freedesktop.org/libinput/libinput/blob/master/.gitlab-ci.yml>`_.
Search for **FEDORA_PACKAGES** in the **variables:** definition Search for **FEDORA_RPMS** in the **variables:** definition
and check the list for an entry for your distribution. and check the list for an entry for your distribution.
In most cases, it is sufficient to install the dependencies that your In most cases, it is sufficient to install the dependencies that your
@ -222,14 +201,6 @@ found``. See
`this blog post here <https://who-t.blogspot.com/2018/07/meson-fails-with-native-dependency-not-found.html>`_ `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. for instructions on how to fix it.
..............................................................................
Build dependencies per distribution
..............................................................................
.. include:: dependencies.rst
.. _building_conditional: .. _building_conditional:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -242,7 +213,7 @@ available options. The default build enables most options and thus requires
more build dependencies. On systems where build dependencies are an issue, more build dependencies. On systems where build dependencies are an issue,
options may be disabled with this meson command: :: options may be disabled with this meson command: ::
meson setup --prefix=/usr -Dsomefeature=false builddir meson --prefix=/usr -Dsomefeature=false builddir
Where ``-Dsomefeature=false`` may be one of: Where ``-Dsomefeature=false`` may be one of:
@ -282,11 +253,6 @@ Software that uses meson should use the ``dependency()`` function: ::
pkgconfig = import('pkgconfig') pkgconfig = import('pkgconfig')
dep_libinput = dependency('libinput') 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 Otherwise, the most rudimentary way to compile and link a program against
libinput is: libinput is:

View file

@ -102,12 +102,11 @@ ignores such button clicks, this behavior is intentional.
Clickfinger behavior Clickfinger behavior
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
This is the default behavior on Apple touchpads. Here, a left, right, middle This is the default behavior on Apple touchpads.
button event is generated when one, two, or three fingers are held down on the Here, a left, right, middle button event is generated when one, two, or
touchpad when a physical click is generated, given the default mapping. The three fingers are held down on the touchpad when a physical click is
location of the fingers does not matter and there are no software-defined generated. The location of the fingers does not matter and there are no
button areas. It is possible to swap right and middle buttons, the same way as software-defined button areas.
with :ref:`tapping <tapping>`.
.. figure:: clickfinger.svg .. figure:: clickfinger.svg
:align: center :align: center

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

@ -21,7 +21,7 @@ sys.path.insert(0, os.path.abspath('@BUILDDIR@'))
# -- Project information ----------------------------------------------------- # -- Project information -----------------------------------------------------
project = '@PROJECT_NAME@' project = '@PROJECT_NAME@'
copyright = '2019, the libinput authors' copyright = '2018, the libinput authors'
author = 'the libinput authors' author = 'the libinput authors'
# The short X.Y version # The short X.Y version
@ -62,7 +62,7 @@ master_doc = 'index'
# #
# This is also used if you do content translation via gettext catalogs. # This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases. # Usually you set "language" from the command line for these cases.
language = 'en' language = None
# List of patterns, relative to source directory, that match files and # List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files. # directories to ignore when looking for source files.
@ -169,7 +169,7 @@ from recommonmark.parser import CommonMarkParser
extlinks = { 'commit' : extlinks = { 'commit' :
('https://gitlab.freedesktop.org/libinput/libinput/commit/%s', ('https://gitlab.freedesktop.org/libinput/libinput/commit/%s',
'git commit %s') 'git commit ')
} }
# -- git version hack ------------------------------------------------- # -- git version hack -------------------------------------------------

View file

@ -6,21 +6,15 @@ Configuration options
Below is a list of configurable options exposed to the users. 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 .. hint:: Not all configuration options are available on all devices. Use
:ref:`libinput list-devices <libinput-list-devices>` to show the :ref:`libinput list-devices <libinput-list-devices>` to show the
configuration options for local devices. configuration options for local devices.
libinput's configuration interface is available to the caller only, not 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 directly to the user. Thus is is the responsibility of the caller to expose
the various options and how these options are exposed. For example, the 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/>`_ xf86-input-libinput driver exposes the options through X Input device
exposes the options through X Input device properties and `xorg.conf.d properties and xorg.conf.d options. See the `libinput(4)
<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. <https://www.mankier.com/4/libinput>`_ man page for more details.
@ -34,7 +28,7 @@ options exposed by libinput are:
- how many tapping fingers are supported by this device - how many tapping fingers are supported by this device
- a toggle to enable/disable tapping - 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, see :ref:`tapndrag`.
- a toggle to enable/disable tap-and-drag drag lock, 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 - 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, click, respectively. This order can be changed to left, middle, right click,
respectively. respectively.
@ -43,19 +37,6 @@ Tapping is usually available on touchpads and the touchpad part of external
graphics tablets. Tapping is usually **not** available on touch screens, graphics tablets. Tapping is usually **not** available on touch screens,
for those devices it is expected to be implemented by the toolkit. 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 Send Events Mode
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -154,25 +135,12 @@ Disable while typing
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
DWT is the most generic form of palm detection on touchpad. While the user 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 typing the touchpad is disabled, the touchpad is enabled after a timeout.
is enabled again after a timeout. See :ref:`disable-while-typing` for more See :ref:`disable-while-typing` for more info.
info.
Disable-while-typing can be enabled or disabled, it is enabled by default on Disable-while-typing can be enabled or disabled, it is enabled by default on
most touchpads. 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
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -187,51 +155,8 @@ environment should provide an interface for this.
Rotation Rotation
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
The device rotation applies a corrective angle to relative input events, 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 This is currently only available on trackpoints which may be used sideways
trackball may be used in a 90° rotated position for accessibility reasons - or upside-down. The angle can be freely chosen but not all devices support
such a rotated position allows triggering the buttons with the thumb or rotation other than 0, 90, 180, or 270 degrees. Rotation is off (0 degrees)
the non-dominant hand. by default.
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

@ -5,152 +5,18 @@
Contributing to libinput Contributing to libinput
============================================================================== ==============================================================================
Contributions to libinput are always welcome. Please see the steps below for
So you want to contribute to libinput? Great! We'd love to help you be a part details on how to create merge requests, correct git formatting and other
of our community. Here is some important information to help you. topics:
.. contents:: .. contents::
:local: :local:
------------------------------------------------------------------------------ Questions regarding this process can be asked on ``#wayland-devel`` on
Code of Conduct freenode or on the `wayland-devel@lists.freedesktop.org
------------------------------------------------------------------------------
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 <https://lists.freedesktop.org/mailman/listinfo/wayland-devel>`_ mailing
list. 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 Submitting Code
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -160,80 +26,32 @@ Any patches should be sent via a Merge Request (see the `GitLab docs
in the `libinput GitLab instance hosted by freedesktop.org in the `libinput GitLab instance hosted by freedesktop.org
<https://gitlab.freedesktop.org/libinput/libinput>`_. <https://gitlab.freedesktop.org/libinput/libinput>`_.
.. note:: freedesktop.org's GitLab instance has restrictions to prevent Spam To submit a merge request, you need to
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 - `Register an account <https://gitlab.freedesktop.org/users/sign_in>`_ in
the freedesktop.org GitLab instance and the freedesktop.org GitLab instance.
`apply for fork permissions <https://gitlab.freedesktop.org/freedesktop/freedesktop/-/wikis/home>`_. - `Fork libinput <https://gitlab.freedesktop.org/libinput/libinput/forks/new>`_
- `Fork libinput <https://gitlab.freedesktop.org/libinput/libinput/-/forks/new>`_ into your username's namespace
into your username's namespace. Select public visibility. - Get libinput's main repository: ::
- Get libinput's main repository. git will call this repository ``origin``. ::
git clone https://gitlab.freedesktop.org/libinput/libinput.git git clone https://gitlab.freedesktop.org/libinput/libinput.git
- Add the forked git repository to your remotes (replace ``USERNAME`` - Add the forked git repository to your remotes (replace ``USERNAME``
with your username). git will call this repository ``gitlab``. :: with your username): ::
cd /path/to/libinput.git cd /path/to/libinput.git
git remote add gitlab git@ssh.gitlab.freedesktop.org:USERNAME/libinput.git git remote add gitlab git@gitlab.freedesktop.org:USERNAME/libinput.git
git fetch gitlab git fetch gitlab
- Create a new branch and commit your changes to that branch. :: - Push your changes to your fork: ::
git switch -C mynewbranch git push gitlab BRANCHNAME
# 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 - Submit a merge request. The URL for a merge request is: ::
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 https://gitlab.freedesktop.org/USERNAME/libinput/merge_requests
Select your branch name to merge and ``libinput/libinput`` ``main`` as target branch. Select your branch name to merge and ``libinput/libinput`` ``master`` as target branch.
- Verify that the CI completes successfully by visiting the merge request
page. A successful pipeline shows only green ticks, failure is indicated
by a red cross or a yellow exclamation mark (see
the `GitLab Docs
<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 Commit History
@ -274,12 +92,23 @@ describes the change. For example: ::
If in doubt what prefix to use, look at other commits that change the If in doubt what prefix to use, look at other commits that change the
same file(s) as the patch being sent. same file(s) as the patch being sent.
.. _contributing_commit_messages:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
Commit Messages Commit Messages
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
Read `on commit messages <http://who-t.blogspot.de/2009/12/on-commit-messages.html>`_
as a general guideline on what commit messages should contain.
Commit messages **should** contain a **Signed-off-by** line with your name
and email address. If you're not the patch's original author, you should
also gather S-o-b's by them (and/or whomever gave the patch to you.) The
significance of this is that it certifies that you created the patch, that
it was created under an appropriate open source license, or provided to you
under those terms. This lets us indicate a chain of responsibility for the
copyright status of the code.
We won't reject patches that lack S-o-b, but it is strongly recommended.
When you re-send patches, revised or not, it would be very good to document the 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 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 merge request. If you have already received Reviewed-by or Acked-by tags, you
@ -287,27 +116,12 @@ 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 commit messages. Otherwise the tags may be lost, reviewers miss the credit they
deserve, and the patches may cause redundant review effort. 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 Coding Style
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
Please see the `CODING_STYLE.md Please see the `CODING_STYLE.md
<https://gitlab.freedesktop.org/libinput/libinput/blob/main/CODING_STYLE.md>`_ <https://gitlab.freedesktop.org/libinput/libinput/blob/master/CODING_STYLE.md>`_
document in the source tree. document in the source tree.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -347,75 +161,13 @@ process, even if you use other clients to track the list of available
patches. patches.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
Failed pipeline errors Code of Conduct
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
After submitting your merge request to GitLab, you might receive an email As a freedesktop.org project, libinput follows the `freedesktop.org
informing you that your pipeline failed. Contributor Covenant <https://www.freedesktop.org/wiki/CodeOfConduct>`_.
Visit your merge request page and check the `pipeline mini graph Please conduct yourself in a respectful and civilised manner when
<https://docs.gitlab.com/ee/ci/pipelines/#pipeline-mini-graphs>`_ to know which interacting with community members on mailing lists, IRC, or bug trackers.
step failed. The community represents the project as a whole, and abusive or bullying
behaviour is not tolerated by the project.
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

@ -36,7 +36,6 @@ Topics below explain some behaviors of libinput.
normalization-of-relative-motion.rst normalization-of-relative-motion.rst
seats.rst seats.rst
timestamps.rst timestamps.rst
wheel-api.rst
.. _hacking_on_libinput: .. _hacking_on_libinput:
@ -47,6 +46,7 @@ Hacking on libinput
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
contributing.rst
architecture architecture
test-suite.rst test-suite.rst
pointer-acceleration.rst pointer-acceleration.rst

View file

@ -68,13 +68,10 @@ MOUSE_WHEEL_CLICK_ANGLE
Below is an example udev rule to assign "seat1" to a device from vendor Below is an example udev rule to assign "seat1" to a device from vendor
``0x012a`` with the model ID of ``0x034b``. :: 0x012a with the model ID of 0x034b. ::
$ cat /etc/udev/rules.d/99-my-device-is-on-seat1.rules ACTION=="add|change", KERNEL=="event[0-9]*", ENV{ID_VENDOR_ID}=="012a", \
ACTION!="remove", KERNEL=="event[0-9]*", \ ENV{ID_MODEL_ID}=="034b", ENV{ID_SEAT}="seat1"
ENV{ID_VENDOR_ID}=="012a", \
ENV{ID_MODEL_ID}=="034b", \
ENV{ID_SEAT}="seat1"
@ -99,13 +96,37 @@ handle some combinations for historical reasons.
Below is an example udev rule to remove an **ID_INPUT_TOUCHPAD** setting 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 and change it into an **ID_INPUT_TABLET** setting. This rule would apply
for a device with the vendor/model ID of ``012a``/``034b``. :: for a device with the vendor/model ID of 012a/034b. ::
$ cat /etc/udev/rules.d/99-my-device-is-a-tablet.rules ACTION=="add|change", KERNEL=="event[0-9]*", ENV{ID_VENDOR_ID}=="012a", \
ACTION!="remove", KERNEL=="event[0-9]*", \ ENV{ID_MODEL_ID}=="034b", ENV{ID_INPUT_TOUCHPAD}="", ENV{ID_INPUT_TABLET}="1"
ENV{ID_VENDOR_ID}=="012a", \
ENV{ID_MODEL_ID}=="034b", \
ENV{ID_INPUT_TOUCHPAD}="", ENV{ID_INPUT_TABLET}="1"
.. _ignoring_devices:
------------------------------------------------------------------------------
Ignoring specific devices
------------------------------------------------------------------------------
If a device has the **LIBINPUT_IGNORE_DEVICE** udev property set to any
value but "0", that device is not initialized by libinput. For a context
created with **libinput_udev_create_context()**, the device is silently ignored
and never shows up. If the device is added with **libinput_path_add_device()**
to a context created with **libinput_path_create_context()**, adding the device
will fail and return NULL (see that function's documentation for more
information).
If the property value is exactly "0", then the property is considered unset
and libinput initializes the device normally.
This property should be used for devices that are correctly detected as
input devices (see :ref:`udev_device_type`) but that should not be used by
libinput. It is recommended that devices that should not be handled as input
devices at all unset the **ID_INPUT** and related properties instead. The
**LIBINPUT_IGNORE_DEVICE** property signals that only libinput should
ignore this property but other parts of the stack (if any) should continue
treating this device normally.
.. _model_specific_configuration: .. _model_specific_configuration:
@ -129,7 +150,7 @@ 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 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 x220 with a touchpad firmware version 8.1. When this firmware version is
installed, the touchpad is imprecise. The touchpad device does not send installed, the touchpad is imprecise. The touchpad device does not send
continuous x/y axis position updates, a behavior also observed on its 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 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 above property is set, libinput adjusts its behavior to better suit this
particular model. particular model.
@ -242,4 +263,4 @@ Modifying the hwdb
device-specific quirks must go in to the :ref:`device-quirks` system. device-specific quirks must go in to the :ref:`device-quirks` system.
For information about older libinput versions, please see the documentation For information about older libinput versions, please see the documentation
for your version available in: https://wayland.freedesktop.org/libinput/doc/ for your version avaialable in: https://wayland.freedesktop.org/libinput/doc/

View file

@ -6,14 +6,14 @@ Device quirks
libinput requires extra information from devices that is not always readily libinput requires extra information from devices that is not always readily
available. For example, some touchpads are known to have jumping cursors available. For example, some touchpads are known to have jumping cursors
under specific conditions. libinput ships a set of files containing the under specific conditions. libinput ships a set of files containting the
so-called model quirks to provide that information. Model quirks are usually so-called model quirks to provide that information. Model quirks are usually
installed under ``/usr/share/libinput/<filename>.quirks`` and are standard installed under ``/usr/share/libinput/<filename>.quirks`` and are standard
``.ini`` files. A file may contain multiple section headers (``[some ``.ini`` files. A file may contain multiple section headers (``[some
identifier]``) followed by one or more :ref:`MatchFoo=Bar <device-quirks-matches>` identifier]``) followed by one or more ``MatchFoo=Bar`` directives, followed by
directives, followed by at least one of ``ModelFoo=1`` or ``AttrFoo=bar`` directive. at least one of ``ModelFoo=1`` or ``AttrFoo=bar`` directive. See the
See the ``quirks/README.md`` file in the libinput source repository for more ``quirks/README.md`` file in the libinput source repository for more details on
details on their contents. their contents.
.. warning:: Model quirks are internal API and may change at any time. No .. warning:: Model quirks are internal API and may change at any time. No
backwards-compatibility is guaranteed. backwards-compatibility is guaranteed.
@ -71,7 +71,7 @@ devices. ::
$ libinput quirks list /dev/input/event19 $ libinput quirks list /dev/input/event19
$ libinput quirks list /dev/input/event0 $ libinput quirks list /dev/input/event0
AttrLidSwitchReliability=unreliable AttrLidSwitchReliability=reliable
The device `event19` does not have any quirks assigned. The device `event19` does not have any quirks assigned.
@ -112,11 +112,11 @@ output.
.. _device-quirks-list: .. _device-quirks-list:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
List of currently available device quirks List of supported device quirks
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
This list is a guide for developers to ease the process of submitting This list is a guide for developers to ease the process of submitting
patches upstream. This section shows device quirks currently available in patches upstream. This section shows device quirks supported in
|git_version|. |git_version|.
.. warning:: Quirks are internal API and may change at any time for any reason. .. warning:: Quirks are internal API and may change at any time for any reason.
@ -147,21 +147,6 @@ ModelBouncingKeys
timestamps can not be relied upon. timestamps can not be relied upon.
ModelSynapticsSerialTouchpad ModelSynapticsSerialTouchpad
Reserved for touchpads made by Synaptics on the serial bus Reserved for touchpads made by Synaptics on the serial bus
ModelPressurePad
.. warning:: This quirk is no longer in use. Use
``AttrInputProp=+INPUT_PROP_PRESSUREPAD`` instead.
Unlike in traditional touchpads, whose pressure value equals contact size,
on pressure pads pressure is a real physical axis.
Indicates that the device is a pressure pad.
ModelTouchpadPhantomClicks
Some laptops are prone to registering touchpad clicks when the case is
bent. Indicates that clicks should be ignored if no fingers are on the
touchpad.
ModelScrollOnMiddleClick
Some mice can generate unwanted high-resolution scroll events when the wheel
is pressed. Increases the scroll threshold required to start scrolling to
avoid accidentally scrolling when middle clicking.
AttrSizeHint=NxM, AttrResolutionHint=N AttrSizeHint=NxM, AttrResolutionHint=N
Hints at the width x height of the device in mm, or the resolution Hints at the width x height of the device in mm, or the resolution
of the x/y axis in units/mm. These may only be used where they apply to of the x/y axis in units/mm. These may only be used where they apply to
@ -172,20 +157,15 @@ AttrTouchSizeRange=N:M, AttrPalmSizeThreshold=O
Specifies the touch size required to trigger a press (N) and to trigger Specifies the touch size required to trigger a press (N) and to trigger
a release (M). O > N > M. See :ref:`touchpad_touch_size_hwdb` for more a release (M). O > N > M. See :ref:`touchpad_touch_size_hwdb` for more
details. details.
An AttrPalmSizeThreshold of zero unsets any threshold that has been AttrTouchPressureRange=N:M, AttrPalmPressureThreshold=O, AttrThumbPressureThreshold=P
inherited from another quirk.
AttrPressureRange=N:M, AttrPalmPressureThreshold=O, AttrThumbPressureThreshold=P
Specifies the touch pressure required to trigger a press (N) and to Specifies the touch pressure required to trigger a press (N) and to
trigger a release (M), when a palm touch is triggered (O) and when a trigger a release (M), when a palm touch is triggered (O) and when a
thumb touch is triggered (P). O > P > N > M. See thumb touch is triggered (P). O > P > N > M. See
:ref:`touchpad_pressure_hwdb` for more details. :ref:`touchpad_pressure_hwdb` for more details.
An AttrPalmPressureThreshold of zero unsets any threshold that has been AttrLidSwitchReliability=reliable|write_open
inherited from another quirk. Indicates the reliability of the lid switch. This is a string enum. Do not
AttrLidSwitchReliability=reliable|unreliable|write_open use "reliable" for any specific device. Very few devices need this, if in
Indicates the reliability of the lid switch. This is a string enum. doubt do not set. See :ref:`switches_lid` for details.
Very few devices need this, if in doubt do not set. See :ref:`switches_lid`
for details. libinput 1.21.0 changed the default from unreliable to
reliable, which may be removed from local overrides.
AttrKeyboardIntegration=internal|external AttrKeyboardIntegration=internal|external
Indicates the integration of the keyboard. This is a string enum. Indicates the integration of the keyboard. This is a string enum.
Generally only needed for USB keyboards. Generally only needed for USB keyboards.
@ -193,52 +173,10 @@ AttrTPKComboLayout=below
Indicates the position of the touchpad on an external touchpad+keyboard Indicates the position of the touchpad on an external touchpad+keyboard
combination device. This is a string enum. Don't specify it unless the combination device. This is a string enum. Don't specify it unless the
touchpad is below. touchpad is below.
AttrEventCode=+EV_ABS;-BTN_STYLUS;+EV_KEY:0x123; AttrEventCodeDisable=EV_ABS;BTN_STYLUS;EV_KEY:0x123;
Enables or disables the evdev event type/code tuples on the device. The prefix Disables the evdev event type/code tuples on the device. Entries may be
for each entry is either '+' (enable) or '-' (disable). Entries may be
a named event type, or a named event code, or a named event type with a a named event type, or a named event code, or a named event type with a
hexadecimal event code, separated by a single colon. hexadecimal event code, separated by a single colon.
AttrInputProp=+INPUT_PROP_BUTTONPAD;-INPUT_PROP_POINTER;
Enables or disables the evdev input property on the device. The prefix
for each entry is either '+' (enable) or '-' (disable). Entries may be
a named input property or the hexadecimal value of that property.
The most common use of this is ``AttrInputProp=+INPUT_PROP_PRESSUREPAD``
which marks a touchpad as a :ref:`forcepad or pressurepad <touchpads_buttons_forcepads>`.
AttrPointingStickIntegration=internal|external AttrPointingStickIntegration=internal|external
Indicates the integration of the pointing stick. This is a string enum. Indicates the integration of the pointing stick. This is a string enum.
Only needed for external pointing sticks. These are rare. Only needed for external pointing sticks. These are rare.
AttrTabletSmoothing=1|0
Enables (1) or disables (0) input smoothing for tablet devices. Smoothing is enabled
by default, except on AES devices.
.. _device-quirks-matches:
------------------------------------------------------------------------------
List of currently available matches
------------------------------------------------------------------------------
``Match*`` statements are how quirks are assigned to a device. Quirks with multiple
match statements must match all of those to apply.
.. warning:: Quirks are internal API and may change at any time for any reason.
No guarantee is given that any ``Match`` statement below works on
your version of libinput.
MatchName, MatchUniq
Match on the ``NAME`` or ``UNIQ`` udev property on this device. These properties
are typically derived from the device's kernel name or uniq but may be overridden
by a udev rule. These matches use ``fnmatch()`` globs.
MatchBus
A lower-case bus name. Currently supported are ``usb``, ``bluetooth``, ``ps2``,
``rmi``, ``i2c``, and ``spi``.
MatchVendor, MatchProduct, MatchVersion
The hexadecimal 4-digit vendor ID, product ID or driver version as
exported, uppercase with a ``0x`` prefix, e.g. ``0x12AB```.
MatchDMIModalias, MatchDeviceTree
An ``fnmatch()`` glob for the DMI modalias or the DeviceTree ``compatible`` string.
See ``/sys/class/dmi/id/modalias`` and ``/sys/firmware/devicetree/base/compatible``.
MatchUdevType
One of ``touchpad``, ``mouse``, ``pointingstick``, ``keyboard``, ``joystick``,
``tablet``, ``tablet-pad``. Matches the corresponding ``ID_INPUT_*`` udev
property.

View file

@ -1,36 +0,0 @@
digraph stack
{
compound=true;
splines=line;
rankdir="LR";
node [
shape="box";
]
subgraph cluster_2 {
label="Kernel";
event0 [label="/dev/input/event0"];
event1 [label="/dev/input/event1"];
}
subgraph cluster_0 {
label="Compositor process";
libinput [label="libinput context 1"];
}
subgraph cluster_1 {
label="libinput debug-events";
libinput2 [label="libinput context 2"];
}
stdout;
client [label="Wayland client"];
event0:e -> libinput:w;
event1:e -> libinput:w;
event0:e -> libinput2:w;
event1:e -> libinput2:w;
libinput -> client [ltail=cluster_0 label="Wayland protocol"];
libinput2 -> stdout [ltail=cluster_1];
}

View file

@ -1,31 +0,0 @@
digraph stack
{
compound=true;
rankdir="LR";
node [
shape="box";
]
subgraph cluster_2 {
label="Kernel";
event0 [label="/dev/input/event0"]
}
subgraph cluster_1 {
label="libinput";
subgraph cluster_0 {
label="Plugin pipeline";
p1 [label="00-foo.lua"];
p2 [label="10-bar.lua"];
}
libinput [label="libinput core"];
}
compositor [label="Compositor"];
event0 -> p1;
p1 -> p2;
p2 -> libinput;
libinput -> compositor [ltail=cluster_1 label="libinput API"];
}

View file

@ -1,40 +0,0 @@
.. _drag_3fg:
==============================================================================
Three-finger drag
==============================================================================
Three-finger drag is a feature available on touchpads that emulates logical
button presses if three fingers are moving on the touchpad.
Three-finger drag is independent from :ref:`tapping` though some specific
behaviors may change when both features are enabled. For example, with
tapping *disabled* a three-finger gesture will virtually always be a three-finger
drag. With tapping *enabled* a three finger gesture may be a three finger drag
and a short delay is required to disambiguate between the two.
The exact behavior of three-finger drag is implementation defined and may
subtly change. As a general rule, the following constraints can be expected:
- three fingers down and movement trigger a button down and subsequent motion
events (i.e. a drag)
- releasing one finger while keeping two fingers down will keep the drag
and *not* switch to :ref:`twofinger_scrolling`.
- releasing two fingers while keeping one finger down will end the drag
(and thus release the button) and switch to normal pointer motion
- releasing all three fingers and putting three fingers back on the touchpad
immediately will keep the drag (i.e. behave as if the fingers were
never lifted)
- if tapping is enabled: a three finger tap immediately after a three-finger
drag will *not* tap, the user needs to wait past the timeout to
three-finger tap
- releasing all three fingers and putting one or two fingers back on
the touchpad will end the drag (and thus release the button)
and proceed with pointer motion or two-finger scrolling, if applicable
- if tapping is enabled: a one or two finger tap immediately after a
three-finger drag will trigger a one or two finger tap. The user does
not have to wait past the drag release timeout

View file

@ -42,18 +42,6 @@ This is a symptom of an invalid trackpoint multiplier. These devices need
pointer acceleration accordingly. See :ref:`trackpoint_range` for a detailed pointer acceleration accordingly. See :ref:`trackpoint_range` for a detailed
explanation. explanation.
.. _faq_pointer_acceleration:
------------------------------------------------------------------------------
Why is libinput's pointer acceleration worse than synaptics/evdev
------------------------------------------------------------------------------
This is a known problem affecting some devices and/or use-case but the exact
cause is still unknown. It may be a device-specific issue, it may be a bug
in libinput's acceleration code, it may be a disagreement about how pointer
acceleration should feel. Unfortunately this is something that affected
users need to investigate and analyze.
.. _faq_enable_tapping: .. _faq_enable_tapping:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -218,7 +206,7 @@ Why don't synclient and syndaemon work with libinput?
Synclient and syndaemon rely on X input device properties that are specific Synclient and syndaemon rely on X input device properties that are specific
to the xf86-input-synaptics X.Org input driver. Both were written when the to the xf86-input-synaptics X.Org input driver. Both were written when the
synaptics driver was the only common touchpad driver in existence. They synaptics driver was the only commmon touchpad driver in existence. They
assume that if the properties aren't available, no touchpad is available assume that if the properties aren't available, no touchpad is available
either. The xf86-input-libinput X.Org input driver does not export these either. The xf86-input-libinput X.Org input driver does not export these
driver-specific properties, synclient/syndaemon will thus not detect the driver-specific properties, synclient/syndaemon will thus not detect the
@ -287,28 +275,28 @@ details on the hwdb and how to modify it locally.
.. _faq_timer_offset: .. _faq_timer_offset:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
What causes the "your system is too slow" warning? What causes the "timer offset negative" warning?
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
libinput relies on the caller to call **libinput_dispatch()** whenever data is libinput relies on the caller to call **libinput_dispatch()** whenever data is
available. **libinput_dispatch()** will process the state of all devices, available on the epoll-fd. Doing so will process the state of all devices
including some time-sensitive features (e.g. palm detection, tap-to-click, and can trigger some timers to be set (e.g. palm detection, tap-to-click,
disable-while-typing, etc.). disable-while-typing, etc.). Internally, libinput's time offsets are always
based on the event time of the triggering event.
If the time between the event and the call to **libinput_dispatch()** For example, a touch event with time T may trigger a timer for the time T +
is excessive, those features may not work correctly. For example, a delay in 180ms. When setting a timer, libinput checks the wall clock time to ensure
touch event processing may cause wrong or missing tap-to-click events or that this time T + offset is still in the future. If not, the warning is
a palm may not be detected correctly. logged.
When this warning appears, it simply means that too much time has passed When this warning appears, it simply means that too much time has passed
between the event occurring and the current time. In almost all cases this between the event occurring (and the epoll-fd triggering) and the current
is an indication of the caller being overloaded and not handling events as time. In almost all cases this is an indication of the caller being
speedily as required. overloaded and not handling events as speedily as required.
The warning has no immediate effect on libinput's behavior but some of the The warning has no immediate effect on libinput's behavior but some of the
functionality that relies on the timer may be impeded. This is not a bug in functionality that relies on the timer may be impeded (e.g. palms are not
libinput. libinput does not control how quickly **libinput_dispatch()** is detected as they should be).
called.
.. _faq_wayland: .. _faq_wayland:
@ -324,67 +312,15 @@ direct connection. As a technical analogy, the question is similar to "is
glibc required for HTTP", or (stretching the analogy a bit further) "Is a glibc required for HTTP", or (stretching the analogy a bit further) "Is a
pen required to write English". No, it isn't. pen required to write English". No, it isn't.
You can use libinput without a Wayland compositor, you can write a Wayland You can use libinput without a Wayland compositor, you can
compositor without libinput. On most major distributions, libinput is the write a Wayland compositor without libinput. Until 2018 the most common use
standard input stack used with the X.Org X server through the of libinput is with the X.Org X server through the xf86-input-libinput
xf86-input-libinput driver. driver. As Wayland compositors become more commonplace they will eventually
overtake X.
So why "for your use-case - probably"? All general-purpose Wayland So why "for your use-case - probably"? All general-purpose Wayland
compositors use libinput for their input stack. Wayland compositors that compositors use libinput for their input stack. Wayland compositors that
are more specialized (e.g. in-vehicle infotainment or IVI) can handle input are more specialized (e.g. in-vehicle infotainment or IVI) can handle input
devices directly but the compositor you want to use devices directly but the compositor you want to use
on your desktop needs an input stack that is more complex. And right now, on your desktop needs an input stack that is more complex. And right now,
libinput is the only input stack that exists for this use-case. libinput is the only input stack that exists for this use-case.
.. _faq_separate_contexts:
------------------------------------------------------------------------------
Can I write a program to make libinput do $FOO
------------------------------------------------------------------------------
A common question is whether it's possible to write a program that can change
libinput's behavior - specifically the libinput that is used inside the
compositor. This indicates a misunderstanding of how libinput works:
libinput is a library that converts kernel events into libinput events, much
like ``sed`` reads data in, modifies it, and provides it to stdout.
.. graphviz:: libinput-contexts.gv
A libinput context is private to the process and cannot be modified from the
outside. To use the ``sed`` analogy again: if ``sed`` is used by a
shell-script, that script has full control over how ``sed`` processes data. In
this analogy, ``sed`` is libinput and the shell script is the compositor. It is
not possible to write a program to modify the behavior of the ``sed`` instance
used inside that shell script.
Writing a program that uses libinput is akin to writing a new script that
invoke ``sed``. It will not have any effect on the original ``sed`` instance.
The only way to modify libinput's behavior is to use the configuration options
exposed by the respective compositor. Those affect the libinput context inside
the compositor and thus have an effect on the input device behavior.
.. _faq_debug_events_not_showing_configuration:
------------------------------------------------------------------------------
Why doesn't libinput debug-events show my configuration
------------------------------------------------------------------------------
See :ref:`faq_separate_contexts`.
------------------------------------------------------------------------------
Can I configure scroll speed?
------------------------------------------------------------------------------
No, or at least, not as a libinput option.
When using a mouse, libinput notifies callers about physical scroll wheel
movement. When using another device, libinput notifies scroll in scroll units.
It is up to the caller to transform those events into a number of pixels to
scroll and, if desired, provide a way to adjust scroll speed.
This transformation cannot be done in libinput because it may depend on context
only known by the caller. For example, a caller may want to scroll faster
depending on how many pages a document has or depending on the widget that
receives the scroll events.

View file

@ -5,7 +5,7 @@ libinput Features
============================================================================== ==============================================================================
Below is a list of features supported by libinput. The availability of Below is a list of features supported by libinput. The availability of
features usually depends on the device type and a device's capabilities. features usually depends on the device type and a device's capabilties.
Not all features are user-configurable, some rely on :ref:`device-quirks` Not all features are user-configurable, some rely on :ref:`device-quirks`
to be useful. to be useful.
@ -22,7 +22,6 @@ to be useful.
scrolling.rst scrolling.rst
t440-support.rst t440-support.rst
tapping.rst tapping.rst
drag-3fg.rst
tablet-support.rst tablet-support.rst
switches.rst switches.rst
touchpad-pressure.rst touchpad-pressure.rst

View file

@ -20,10 +20,9 @@ finger belonging to this gesture is lifted.
A single gesture cannot change the finger count. For example, if a user A single gesture cannot change the finger count. For example, if a user
puts down a fourth finger during a three-finger swipe gesture, libinput will puts down a fourth finger during a three-finger swipe gesture, libinput will
end (cancel) the three-finger gesture and, if applicable, start a end the three-finger gesture and, if applicable, start a four-finger swipe
four-finger swipe gesture. A caller may however decide that those gestures gesture. A caller may however decide that those gestures are semantically
are semantically identical and continue the two gestures as one single identical and continue the two gestures as one single gesture.
gesture.
.. _gestures_pinch: .. _gestures_pinch:
@ -74,227 +73,6 @@ gesture into an action or limit a gesture to specific directions only.
The illustration above shows a vertical three-finger swipe. The coordinates The illustration above shows a vertical three-finger swipe. The coordinates
provided during the gesture are the movements of the logical center. provided during the gesture are the movements of the logical center.
.. _gestures_hold:
------------------------------------------------------------------------------
Hold gestures
------------------------------------------------------------------------------
A hold gesture is one where the user places one or more fingers on the
device without significant movement. The exact conditions when a hold gesture
transitions to pointer motion, scrolling or other gestures
are implementation-defined.
The hold gesture is intended to allow for the implementation of two specific
features:
- where a two-finger scrolling starts kinetic scrolling in the caller, a
subsequent hold gesture can be used to stop that kinetic scroll motion,
and
- hold-to-trigger interactions where the interaction could be a click, a
context menu, or some other context-specific interaction.
Hold gestures have three potential logical states:
- **begin**: one or more fingers are placed on the device at the same time
- **end**: all fingers are removed and the device enters a neutral logical state
- **end(cancelled)**: all fingers are part of a known interaction and the
currenthold gesture is no longer active. This may also occurs when
switching between hold gestures with different finger counts.
.. note:: By definition, a hold gesture does not move and thus no coordinate
updates are available.
For example, a user that puts one finger, then a second finger down and
releases them later may trigger the following event sequence:
============= ============ ============
Action Event Finger count
============= ============ ============
Finger 1 down <no event>
Finger 2 down **begin** 2
Finger 2 up **end** 2
Finger 1 up <no event>
============= ============ ============
A hold gesture may by be **cancelled**. This occurs
when the hold gesture changes into some other interaction and should no
longer be considered the current hold gesture. A **end(cancelled)** event
applies to the whole gesture (all fingers). For example, a pointer motion on
a touchpad may trigger this sequence:
+-------------------+-----------------------+
| Action | Event |
+===================+=======================+
| | Finger 1 down | | **hold begin** |
+-------------------+-----------------------+
| | Finger 1 motion | | **hold cancel** |
| | | | **pointer motion** |
+-------------------+-----------------------+
| | Finger 1 motion | | **pointer motion** |
+-------------------+-----------------------+
| | Finger 1 up | | *no event* |
+-------------------+-----------------------+
.. note:: Many interactions with a touchpad will start with a hold
gesture that is then cancelled as that gesture turns into e.g.
pointer motion. A caller **must** handle hold gesture
cancellations correctly.
A two-finger scroll motion on a touchpad may trigger this sequence:
+------------------------+---------------------+--------------+
| Action | Event | Finger count |
+========================+=====================+==============+
| | Finger 1 down | | **hold begin** | | 1 |
+------------------------+---------------------+--------------+
| | Finger 2 down | | **hold cancel** | | 1 |
| | | | **hold begin** | | 2 |
+------------------------+---------------------+--------------+
| | Finger 1+2 motion | | **hold cancel** | | 2 |
| | | | **pointer axis** | | |
+------------------------+---------------------+--------------+
| | Finger 1+2 motion | | **pointer axis** | |
+------------------------+---------------------+--------------+
| | Finger 1 up | | **pointer axis** | |
| | Finger 2 up | | (scroll stop) | |
+------------------------+---------------------+--------------+
A three-finger-swipe on a touchpad may trigger this sequence:
+---------------------+---------------------+--------------+
| Action | Event | Finger count |
+=====================+=====================+==============+
| | Finger 1 down | | **hold begin** | | 1 |
+---------------------+---------------------+--------------+
| | Finger 2 down | | **hold cancel** | | 1 |
| | | | **hold begin** | | 2 |
+---------------------+---------------------+--------------+
| | Finger 3 down | | **hold cancel** | | 2 |
| | | | **hold begin** | | 3 |
+---------------------+---------------------+--------------+
| | Finger motion | | **hold cancel** | | 3 |
| | | | **swipe begin** | | 3 |
+---------------------+---------------------+--------------+
| | Finger motion | | **swipe update** | | 3 |
+---------------------+---------------------+--------------+
| | Finger 1 up | | **swipe end** | | 3 |
| | Finger 2 up | | | | |
| | Finger 3 up | | | | |
+---------------------+---------------------+--------------+
Single-finger hold gestures
...........................
libinput uses implementation-defined timeouts based on other interactions
to determine whether a single-finger hold gestures should start. In other
words, a caller **must not** rely on a hold gesture always being triggered
as soon as a single finger is placed on the touchpad. This is true for any
hold gesture but especially so for single-finger hold gestures.
Hold gestures with a single finger are prone to being extremely short-lived.
On many devices it is impossible to hold a finger still enough for there to
be no pointer motion events, even if those deltas are miniscule. Changing
movement thresholds to rely on hold gestures would reduce device
responsiveness.
It is thus the responsibility of the caller to determine where hold gestures
transition in and out of other interactions. For example, a two-finger hold
may produce a cancelled single-finger hold gesture first:
+--------------------+----------------------+--------------+--------------+
| Action | Event | Finger count | Notes |
+====================+======================+==============+==============+
| | Finger 1 down | | **hold begin** | | 1 | |
+--------------------+----------------------+--------------+--------------+
| | Finger 1 motion | | **hold cancel** | | 1 | | tiny deltas|
| | | | **pointer motion** | | | | |
+--------------------+----------------------+--------------+--------------+
| | Finger 2 down | | **hold begin** | | 2 | |
+--------------------+----------------------+--------------+--------------+
| | Finger 1 up | | **hold end** | | | |
| | Finger 2 up | | | | | |
+--------------------+----------------------+--------------+--------------+
Note how the second hold gesture started with a finger count of 2 - without
the user ever lifting the first finger. Cancellation of hold gesture does
not imply the user has lifted a finger.
A hold gesture may start after a previous gesture completed. For example, a
single finger move-and-hold may trigger different sequences for the same
user interaction:
+--------------------+---------------------+-------------------+--------------+
| Action | Device 1 | Device 2 | Notes |
+====================+=====================+===================+==============+
| | Finger 1 down | | **hold begin** | | **hold begin** | |
+--------------------+---------------------+-------------------+--------------+
| | Finger 1 motion | | **hold cancel** | | | tiny deltas|
| | | **pointer motion**| | | |
+--------------------+---------------------+-------------------+--------------+
| | | **hold begin** | | |
+--------------------+---------------------+-------------------+--------------+
| | Finger 1 up | | **hold end** | | **hold end** | |
+--------------------+---------------------+-------------------+--------------+
A caller that wants to use hold gestures must thus be able to infer the same
interaction based on a stream of pointer motion events with small deltas.
libinput may start a new hold begin gesture once the pointer stops moving.
The time between the last pointer motion event and the hold begin event is
implementation-defined.
Hold gestures and thumb/palm detection
......................................
Thumb and palm detection effectively remove touches from being counted
towards an interaction, see :ref:`thumb_detection` and
:ref:`palm_detection` for details.
In the context of hold gestures, thumbs and palms are treated by libinput as
if the finger was removed from the device. Where other non-thumb/non-palm
fingers remain on the device, an **hold update** event is sent. Otherwise,
the hold gesture terminates with a **hold cancel** event.
Notably, libinput's thumb and palm detection is not a simple boolean per
touch but specific to the state of that touch in the overall context. For
example, a touch may be a thumb for tapping but not for clickfinger
interactions. A caller must not infer the number of physical fingers from
the hold gesture.
Likewise, libinput may classify a finger as thumb in the same hardware event
as a new finger is placed on the touchpad. In that case, the hold gesture
**may** continue as one-finger gesture despite there being two physical
touch points.
Information to determine whether a touch is a thumb or a palm may not be
available until some time into an interaction. Thus very short brushes
of the touchpad by a palm may trigger a **hold begin** followed by an
immediate **hold end** as libinput lacks sufficient information to identify
the touch as thumb/palm and send the corresponding **hold cancel**
event. A caller must not assume that a hold gesture always represents a
valid finger down.
Hold gestures and tap-to-click
..............................
:ref:`tapping` is the feature that enables short-lived touches to trigger
button presses.
.. warning:: Summary: do not use hold gestures to do your own tap-to-click
implementation
In the context of hold gestures, tap-to-click cancels current hold gestures
and a finger dragging (see :ref:`tapndrag`) does not begin a hold
gesture. Where tap-to-click is disabled a tap-like gesture may create
**hold begin** followed by a **hold end** event. Callers **must not** use
hold gestures for their own tap-to-click implementation as the data is not
reliable enough. libinput may change internal timeouts and thresholds
depending on whether tap-to-click is enabled and the hold gesture event may
not match touch sequences that a user would expect to be a tap-to-click
interaction.
.. _gestures_touchscreens: .. _gestures_touchscreens:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------

View file

@ -1,36 +0,0 @@
.. _ignoring_devices:
==============================================================================
Ignoring specific devices
==============================================================================
If a device has the **LIBINPUT_IGNORE_DEVICE** udev property set to any
value but "0", that device is not initialized by libinput.
For a context created with **libinput_udev_create_context()**, the device is
silently ignored and never shows up. If the device is added with
**libinput_path_add_device()** to a context created with
**libinput_path_create_context()**, adding the device will fail and return NULL
(see that function's documentation for more
information).
If the property value is exactly "0", then the property is considered unset
and libinput initializes the device normally.
This property should be used for devices that are correctly detected as
input devices (see :ref:`udev_device_type`) but that should not be used by
libinput. It is recommended that devices that should not be handled as input
devices at all unset the **ID_INPUT** and related properties instead. The
**LIBINPUT_IGNORE_DEVICE** property signals that only libinput should
ignore this property but other parts of the stack (if any) should continue
treating this device normally.
Below is an example udev rule to assign **LIBINPUT_IGNORE_DEVICE** to the
device with the vendor/model ID of ``012a``/``034b``. ::
$ cat /etc/udev/rules.d/99-ignore-my-device.rules
ACTION!="remove", KERNEL=="event[0-9]*", \
ENV{ID_VENDOR_ID}=="012a", \
ENV{ID_MODEL_ID}=="034b", \
ENV{LIBINPUT_IGNORE_DEVICE}="1"
See :ref:`udev_config` for more details on libinput's udev properties.

View file

@ -1,62 +0,0 @@
.. _incorrectly_enabled_hires:
==============================================================================
Incorrectly enabled high-resolution scroll
==============================================================================
Some devices might announce support for high-resolution scroll wheel by enabling
``REL_WHEEL_HI_RES`` and/or ``REL_HWHEEL_HI_RES`` but never send a
high-resolution scroll event.
When the first low-resolution scroll event is received without any previous
high-resolution event, libinput prints a bug warning with the text **"device
supports high-resolution scroll but only low-resolution events have been
received"** and a link to this page.
.. note:: This warning will be printed only once
In most cases this is a bug on the device firmware, the kernel driver or in a
software used to create user-space devices through uinput.
Once the bug is detected, libinput will start emulating high-resolution scroll
events.
------------------------------------------------------------------------------
Detecting and fixing the issue
------------------------------------------------------------------------------
Events sent by a buggy device can be shown in the
:ref:`libinput record <libinput-record>` output for the device. Notice that
``REL_WHEEL_HI_RES`` and ``REL_HWHEEL_HI_RES`` are set but only ``REL_WHEEL``
events are sent: ::
# Supported Events:
# Event type 0 (EV_SYN)
# Event type 1 (EV_KEY)
# Event code 272 (BTN_LEFT)
# Event type 2 (EV_REL)
# Event code 0 (REL_X)
# Event code 1 (REL_Y)
# Event code 6 (REL_HWHEEL)
# Event code 8 (REL_WHEEL)
# Event code 11 (REL_WHEEL_HI_RES)
# Event code 12 (REL_HWHEEL_HI_RES)
[...]
quirks:
events:
- evdev:
- [ 0, 0, 2, 8, 1] # EV_REL / REL_WHEEL 1
- [ 0, 0, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +0ms
- evdev:
- [ 0, 15126, 2, 8, 1] # EV_REL / REL_WHEEL 1
- [ 0, 15126, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +15ms
- evdev:
- [ 0, 30250, 2, 8, 1] # EV_REL / REL_WHEEL 1
- [ 0, 30250, 0, 0, 0] # ------------ SYN_REPORT (0) ---------- +15ms
The issue can be fixed by adding a quirk to unset the ``REL_WHEEL_HI_RES`` and
``REL_HWHEEL_HI_RES`` event codes: ::
AttrEventCode=-REL_WHEEL_HI_RES;-REL_HWHEEL_HI_RES;
Please see :ref:`device-quirks` for details.

View file

@ -10,10 +10,7 @@
faqs faqs
reporting-bugs reporting-bugs
troubleshooting troubleshooting
contributing
development development
lua-plugins
API documentation <@HTTP_DOC_LINK@/api/>
++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++
@ -24,7 +21,7 @@ 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 and other applications that need to handle input devices provided by the
kernel. kernel.
libinput provides device detection, event handling and abstraction to libinput provides device detection, event handling and abstraction so
minimize the amount of custom input code the user of libinput need to minimize the amount of custom input code the user of libinput need to
provide the common set of functionality that users expect. Input event provide the common set of functionality that users expect. Input event
processing includes scaling touch coordinates, generating processing includes scaling touch coordinates, generating
@ -37,14 +34,14 @@ driver than an application library. See :ref:`what_is_libinput` for more details
Users and Developers Users and Developers
-------------------- --------------------
Please use the side-bar to navigate through the various documentation items. Please use the side-bar to nagivate through the various documentation items.
----------------- -----------------
API documentation API documentation
----------------- -----------------
The API documentation is available here: The API documentation is available here:
https://wayland.freedesktop.org/libinput/doc/latest/api/ http://wayland.freedesktop.org/libinput/doc/latest/api/
.. note:: This documentation is generally only needed by authors of Wayland .. note:: This documentation is generally only needed by authors of Wayland
compositors or other developers dealing with input events directly. compositors or other developers dealing with input events directly.

View file

@ -1,661 +0,0 @@
.. _lua_plugins:
==============================================================================
Lua Plugins
==============================================================================
libinput provides a plugin system that allows users to modify the behavior
of devices. For example, a plugin may add or remove axes and/or buttons on a
device and/or modify the event stream seen by this device before it is passed
to libinput.
Plugins are implemented in `Lua <https://www.lua.org/>`_ (version 5.4)
and are typically loaded from the following paths:
- ``/etc/libinput/plugins/*.lua``, and
- ``/usr/lib{64}/libinput/plugins/*.lua``
Plugins are loaded in alphabetical order and where
multiple plugins share the same file name, the one in the highest precedence
directory is used. Plugins in ``/etc`` take precedence over
plugins in ``/usr``.
.. note:: Plugins lookup paths and their order are decided by the compositor.
Some compositors may support more/fewer/other lookup paths than the
above defaults.
Plugins are run sequentially in ascending sort-order (i.e. ``00-foo.lua`` runs
before ``10-bar.lua``) and each plugin sees the state left by any previous
plugins. For example if ``00-foo.lua`` changes all left button events to right
button events, ``10-bar.lua`` only ever sees right button events.
See the `Lua Reference manual <https://www.lua.org/manual/5.4/manual.html>`_ for
details on the Lua language.
.. note:: Plugins are **not** loaded by default, it is up to the compositor
whether to allow plugins. An explicit call to
``libinput_plugin_system_load_plugins()`` is required.
------------------------------------------------------------------------------
Limitations
------------------------------------------------------------------------------
Each script runs in its own sandbox and cannot communicate or share state with
other scripts.
Tables that hold API methods are not writable, i.e. it is not possible
to overwrite the default functionality of those APIs.
The Lua API available to plugins is limited to the following calls::
assert error ipairs next pairs tonumber
pcall select print tostring type xpcall
table string math _VERSION
It is not possible to e.g. use the ``io`` module from a script.
To use methods on instantiated objects, the ``object:method`` method call
syntax must be used. For example:
.. code-block:: lua
libinput:register()
libinput.register() -- this will fail
------------------------------------------------------------------------------
When to use plugins
------------------------------------------------------------------------------
libinput plugins are a relatively niche use-case that typically need to
address either once-off issues (e.g. those caused by worn-out hardware) or
user preferences that libinput does not and will not cater for.
Plugins should not be used for issues that can be fixed generically, for
example via :ref:`device-quirks`.
As a rule of thumb: a plugin should be a once-off that only works for one
user's hardware. If a plugin can be shared with many users then the plugin
implements functionality that should be integrated into libinput proper.
------------------------------------------------------------------------------
Testing plugins
------------------------------------------------------------------------------
Our :ref:`tools` support plugins if passed the ``--enable-plugins`` commandline
option. For implementing and testing plugins the easiest commands to test are
- ``libinput debug-events --enable-plugins`` (see :ref:`libinput-debug-events` docs)
- ``libinput debug-gui --enable-plugins`` (see :ref:`libinput-debug-gui` docs)
Where libinput is built and run from git, the tools will also look for plugins
in the meson build directory. See the ``plugins/meson.build`` file for details.
.. _plugins_api_lua:
--------------------------------------------------------------------------------
Lua Plugin API
--------------------------------------------------------------------------------
Lua plugins sit effectively below libinput and the API is not a
representation of the libinput API. Plugins modify the evdev event stream
received from the kernel.
.. graphviz:: plugin-stack.gv
The API revolves around two types: ``libinput`` and ``EvdevDevice``. The
``libinput`` type is used to register a plugin from a script, the
``EvdevDevice`` represents one device that is present in the system (but may
not have yet been added by libinput).
Typically a script does the following steps:
- register with libinput via ``libinput:register({versions})``
- connect to the ``"new-evdev-device"`` event
- receive an ``EvdevDevice`` object in the ``"new-evdev-device"`` callback
- check and/or modify the evdev event codes on the device
- connect to the device's ``"evdev-frame"`` event
- receive an :ref:`evdev frame <plugins_api_evdev_frame>` in the device's
``"evdev-frame"`` callback
- check and/or modify the events in that frame
Where multiple plugins are active, the evdev frame passed to the callback is
the combined frame as processed by all previous plugins in ascending sort order.
For example, if one plugin discards all button events subsequent plugins will
never see those button events in the frame.
.. _plugins_api_version_stability:
..............................................................................
Plugin version stability
..............................................................................
Plugin API version stability is provided on a best effort basis. We aim to provide
stable plugin versions for as long as feasible but may need to retire some older
versions over time. For this reason a plugin can select multiple versions it
implements, libinput will pick one supported version and adjust the plugin
behavior to match that version. See the ``libinput:register()`` call for details.
--------------------------------------------------------------------------------
Lua Plugin API Reference
--------------------------------------------------------------------------------
libinput provides the following globals and types:
.. _plugins_api_evdev_usage:
................................................................................
Evdev Usages
................................................................................
Evdev usages are a libinput-specific wrapper around the ``linux/input-event-codes.h``
evdev types and codes. They are used by libinput internally and are a 32-bit
combination of ``type << 16 | code``. Each usage carries the type and code and
is thus simpler to pass around and less prone to type confusion.
The :ref:`evdev global <plugins_api_evdev_global>` attempts to provide all
available usages but for the niche cases where it does not provide a named constant
the value can be crafted manually:
.. code-block:: lua
evdev_type = 0x3 -- EV_REL
evdev_code = 0x1 -- REL_Y
evdev_usage = (evdev_type << 16) | evdev_code
assert(usage == evdev.REL_Y)
.. _plugins_api_evdev_global:
................................................................................
The ``evdev`` global
................................................................................
The ``evdev`` global represents all known :ref:`plugins_api_evdev_usage`,
effectively in the form:
.. code-block:: lua
evdev = {
ABS_X = (3 << 16) | 0,
ABS_Y = (3 << 16) | 1,
...
REL_X = (2 << 16) | 0,
REL_Y = (2 << 16) | 1,
...
}
This global is provided for convenience to improve readability in the code.
Note that the name uses the event code name only (e.g. ``evdev.ABS_Y``) but the
value is an :ref:`Evdev Usage <plugins_api_evdev_usage>` (type and code).
See the ``linux/input-event-codes.h`` header file provided by your kernel
for a list of all evdev types and codes.
The evdev global also provides the bus type constants, e.g. ``evdev.BUS_USB``.
See the ``linux/input.h`` header file provided by your kernel
for a list of bus types.
.. _plugins_api_evdev_frame:
................................................................................
Evdev frames
................................................................................
Evdev frames represent a single frame of evdev events for a device. A frame
is a group of events that occurred at the same time. The frame usually only
contains state that has changed compared to the previous frame.
In our API a frame is exposed as a nested table with the following structure:
.. code-block:: lua
frame1 = {
{ usage = evdev.ABS_X, value = 123 },
{ usage = evdev.ABS_Y, value = 456 },
{ usage = evdev.BTN_LEFT, value = 1 },
}
frame2 = {
{ usage = evdev.ABS_Y, value = 457 },
}
frame3 = {
{ usage = evdev.ABS_X, value = 124 },
{ usage = evdev.BTN_LEFT, value = 0 },
}
.. note:: This API does not use ``SYN_REPORT`` events, it is implied at the
end of the table. Where a plugin writes a ``SYN_REPORT`` into the
list of events, that ``SYN_REPORT`` terminates the event frame
(similar to writing a ``\0`` into the middle of a C string).
A frame containing only a ``SYN_REPORT`` is functionally equivalent
to an empty frame.
Events or frames do not have a timestamp. Where a timestamp is required, that
timestamp is passed as additional argument to the function or return value.
See :ref:`plugins_api_evdev_global` for a list of known usages.
.. warning:: Evdev frames have an implementation-defined size limit of how many
events can be added to a single frame. This limit should never be
hit by valid plugins.
.. _plugins_api_libinputglobal:
................................................................................
The ``libinput`` global object
................................................................................
The core of our plugin API is the ``libinput`` global object. A script must
immediately ``register()`` to be active, otherwise it is unloaded immediately.
All libinput-specific APIs can be accessed through the ``libinput`` object.
.. function:: libinput:register({1, 2, ...})
Register this plugin with the given table of supported version numbers and
returns the version number selected by libinput for this plugin. See
:ref:`plugins_api_version_stability` for details.
.. code-block:: lua
-- this plugin can support versions 1, 4 and 5
version = libinput:register({1, 4, 5})
if version == 1 then
...
This function must be the first function called.
If the plugin calls any other functions before ``register()``, those functions
return the default zero value for the return type (``nil``, ``0``, an empty
table, etc.).
If the plugin does not call ``register()`` it will be removed immediately.
Once registered, any connected callbacks will be invoked whenever libinput
detects new devices, removes devices, etc.
This function must only be called once.
.. function:: libinput:unregister()
Unregister this plugin. This removes the plugin from libinput and releases
any resources associated with this plugin. This call must be the last call
in your plugin, it is effectively equivalent to Lua's
`os.exit() <https://www.lua.org/manual/5.4/manual.html#pdf-os.exit>`_.
.. function:: libinput:log_debug(message)
Log a message at the libinput debug log priority. See
``libinput:log_error()`` for details.
.. function:: libinput:log_info(message)
Log a message at the libinput info log priority. See
``libinput:log_error()`` for details.
.. function:: libinput:log_error(message)
Log a message at the libinput error log priority. Whether a message is
displayed in the log depends on libinput's log priority, set by the caller.
A compositor may disable stdout and stderr. Log messages should be preferred
over Lua's ``print()`` function to ensure the messages end up in the same
location as other libinput log messages and are not discarded.
.. function:: libinput:now()
Returns the current time in microseconds in ``CLOCK_MONOTONIC``. This is
the timestamp libinput uses internally. This timestamp cannot be mapped
to any particular time of day, see the
`clock_gettime() man page <https://man7.org/linux/man-pages/man3/clock_gettime.3.html>`_
for details.
.. function:: libinput:version()
Returns the agreed-on version of the plugin, see ``libinput:register()``.
If called before ``libinput:register()`` this function returns ``0``.
.. function:: libinput:connect(name, function)
Set the callback to the given event name. Only one callback
may be set for an event name at any time, subsequent callbacks
will replace any earlier callbacks for the same name.
Version 1 of the plugin API supports the following events and callback arguments:
- ``"new-evdev-device"``: A new :ref:`EvdevDevice <plugins_api_evdevdevice>`
has been seen by libinput but not yet added.
.. code-block:: lua
libinput:connect("new-evdev-device", function (device) ... end)
- ``"timer-expired"``: The timer for this plugin has expired. This event is
only sent if the plugin has set a timer with ``timer_set()``.
.. code-block:: lua
libinput:connect("timer-expired", function (now) ... end)
The ``now`` argument is the current time in microseconds in
``CLOCK_MONOTONIC`` (see ``libinput:now()``).
.. function:: libinput:timer_cancel()
Cancel the timer for this plugin. This is a no-op if the timer
has not been set or has already expired.
.. function:: libinput:timer_set_absolute(time)
Set a timer for this plugin, with the given time in microseconds.
The timeout specifies an absolute time in microseconds (see
``libinput:now()``) The timer will expire once and then call the
``"timer-expired"`` event handler (if any).
See ``libinput:timer_set_relative()`` for a relative timer.
The following two lines of code are equivalent:
.. code-block:: lua
libinput:timer_set_relative(1000000) -- 1 second from now
libinput:timer_set_absolute(libinput:now() + 1000000) -- 1 second from now
Calling this function will cancel any existing (relative or absolute) timer.
.. function:: libinput:timer_set_relative(timeout)
Set a timer for this plugin, with the given timeout in microseconds from
the current time. The timer will expire once and then call the
``"timer-expired"`` event handler (if any).
See ``libinput:timer_set_absolute()`` for an absolute timer.
The following two lines of code are equivalent:
.. code-block:: lua
libinput:timer_set_relative(1000000) -- 1 second from now
libinput:timer_set_absolute(libinput:now() + 1000000) -- 1 second from now
Calling this function will cancel any existing (relative or absolute) timer.
.. _plugins_api_evdevdevice:
................................................................................
The ``EvdevDevice`` type
................................................................................
The ``EvdevDevice`` type represents a device available in the system
but not (yet) added by libinput. This device may be used to modify
a device's capabilities before the device is processed by libinput.
A plugin should always ``connect()`` to the ``"device-removed"`` callback
to be notified when a device is removed. If the plugin keeps a reference
to this device but the device is discarded by libinput, the device's query
methods will return zero values (e.g. ``nil``, ``0``, an empty table) and
methods will be noops.
.. function:: EvdevDevice:info()
A table containing static information about the device, e.g.
.. code-block:: lua
{
bustype = evdev.BUS_USB,
vid = 0x1234,
pid = 0x5678,
}
A plugin must ignore keys it does not know about.
Version 1 of the plugin API supports the following keys and values:
- ``bustype``: The numeric bustype of the device. See the
``BUS_*`` defines in ``linux/input.h`` for the list of possible values.
- ``vid``: The 16-bit vendor ID of the device
- ``pid``: The 16-bit product ID of the device
If the device has since been discarded by libinput, this function returns an
empty table.
.. function:: EvdevDevice:name()
The device name as set by the kernel
.. function:: EvdevDevice:usages()
Returns a table of all usages that are currently enabled for this
device. Any type that exists on the device has a table assigned and in this
table any code that exists on the device is a boolean true.
For example:
.. code-block:: lua
{
evdev.REL_X = true,
evdev.REL_Y = true,
evdev.BTN_LEFT = true,
}
All other usages are ``nil``, so that the following code is possible:
.. code-block:: lua
local usages = device:usages()
if usages[evdev.REL_X] then
-- do something
end
If the device has since been discarded by libinput, this function returns an
empty table.
.. function:: EvdevDevice:absinfos()
Returns a table of all ``EV_ABS`` codes that are currently enabled for this device.
The event code is the key, each value is a table containing the following keys:
``minimum``, ``maximum``, ``fuzz``, ``flat``, ``resolution``.
.. code-block:: lua
{
evdev.ABS_X = {
minimum = 0,
maximum = 1234,
fuzz = 0,
flat = 0,
resolution = 45,
},
}
If the device has since been discarded by libinput, this function returns an
empty table.
.. function:: EvdevDevice:udev_properties()
Returns a table containing a filtered list of udev properties available on this device
in the form ``{ property_name = property_value, ... }``.
udev properties used as a boolean (e.g. ``ID_INPUT``) are only present if their
value is a logical true.
Version 1 of the plugin API supports the following udev properties:
- ``ID_INPUT`` and all of ``ID_INPUT_*`` that denote the device type as assigned
by udev. This information is usually used by libinput to determine a
device type. Note that for historical reasons these properties have
varying rules - some properties may be mutually exclusive, others are
independent, others may only be set if another property is set. Refer to
the udev documentation (if any) for details. ``ID_INPUT_WIDTH_MM`` and
``ID_INPUT_HEIGHT_MM`` are excluded from this set.
If the device has since been discarded by libinput, this function returns an
empty table.
.. function:: EvdevDevice:enable_evdev_usage(usage)
Enable the given :ref:`evdev usage <plugins_api_evdev_usage>` for this device.
Use :ref:`plugins_api_evdev_global` for better readability,
e.g. ``device:enable_evdev_usage(evdev.REL_X)``.
This function must not be used for ``ABS_*`` events, use ``set_absinfo()``
instead.
Once a usage is enabled, events for that usage may be added to a device's
frame.
If the device has since been discarded by libinput, this function does nothing.
.. function:: EvdevDevice:disable_evdev_usage(usage)
Disable the given :ref:`evdev usage <plugins_api_evdev_usage>` for this device.
Use :ref:`plugins_api_evdev_global` for better readability,
e.g. ``device:disable_evdev_usage(evdev.REL_X)``.
Once a usage is disabled, events for that usage are discarded from any
device frame.
If the device has since been discarded by libinput, this function does nothing.
.. function:: EvdevDevice:set_absinfo(usage, absinfo)
Set the absolute axis information for the given :ref:`evdev usage <plugins_api_evdev_usage>`
and enable it if it does not yet exist on the device. The ``absinfo`` argument is a table
containing zero or more of the following keys: ``minimum``, ``maximum``, ``fuzz``,
``flat``, ``resolution``. Any missing key defaults the corresponding
value from the device if the device already has this event usage or zero otherwise.
For example, the following code changes the resolution but leaves everything
else as-is:
.. code-block:: lua
local absinfo = {
resolution = 40,
}
device:set_absinfo(evdev.ABS_X, absinfo)
device:set_absinfo(evdev.ABS_Y, absinfo)
Use :ref:`plugins_api_evdev_global` for better readability as shown in the
example above.
If the device has since been discarded by libinput, this function does nothing.
.. note:: Overriding the absinfo values often indicates buggy firmware. This should
typically be fixed with an entry in the
`60-evdev.hwdb <https://github.com/systemd/systemd/blob/main/hwdb.d/60-evdev.hwdb>`_
or :ref:`device-quirks` instead of a plugin so all users of that
device can benefit from the fix.
.. function:: EvdevDevice:connect(name, function)
Set the callback to the given event name. Only one callback
may be set for an event name at any time, subsequent callbacks
will overwrite any earlier callbacks for the same name.
If the device has since been discarded by libinput, this function does nothing.
Version 1 of the plugin API supports the following events and callback arguments:
- ``"evdev-frame"``: A new :ref:`evdev frame <plugins_api_evdev_frame>` has
started for this device. If the callback returns a value other than
``nil``, that value is the frame with any modified events.
An empty frame (``{}``) causes libinput to drop the current event frame.
.. code-block:: lua
device:connect("evdev-frame", function (device, frame, timestamp)
-- change any event into a movement left by 1 pixel
move_left = {
{ usage = evdev.REL_X, value = -1, },
}
return move_left
end
The timestamp of an event frame is in microseconds in ``CLOCK_MONOTONIC``, see
``libinput:now()`` for details.
For performance reasons plugins that do not modify the event frame should
return ``nil`` (or nothing) instead of the event frame that was passed
as argument.
- ``"device-removed"``: This device was removed by libinput. This may happen
without the device ever becoming a libinput device as seen by libinput's
public API (e.g. if the device does not meet the requirements to be
added). Once this callback is invoked, the plugin should remove any
references to this device and stop using it.
.. code-block:: lua
device:connect("device-removed", function (device) ... end)
Functions to query the device's capabilities (e.g. ``usages()``) will
return an empty table.
.. function:: EvdevDevice:disconnect(name)
Disconnect the existing callback (if any) for the given event name. See
``EvdevDevice:connect()`` for a list of supported names.
.. function:: EvdevDevice:prepend_frame(frame)
Prepend an :ref:`evdev frame <plugins_api_evdev_frame>` for this device
**before** the current frame (if any). The **next** plugin will see the
prepended frame first followed by the current frame.
This function can only be called from within a device's ``"evdev-frame"``
handler or from within the plugin's timer callback function.
For example, to change a single event into a drag, prepend a button
down and append a button up before each event:
.. code:: lua
function frame_handler(device, frame, timestamp)
device:prepend_frame({
{ usage = evdev.BTN_LEFT, value = 1}
})
device:append_frame({
{ usage = evdev.BTN_LEFT, value = 0}
})
return nil -- return the current frame unmodified
-- The next plugin sees the event sequence:
-- button down, frame, button up
end
If called from within the plugin's timer there is no current frame and this
function is identical to ``append_frame()``.
.. function:: EvdevDevice:append_frame(frame)
Appends an :ref:`evdev frame <plugins_api_evdev_frame>` for this device
**after** the current frame (if any). This function can only be called from
within a device's ``"evdev-frame"`` handler or from within the plugin's timer
callback function.
If called from within the plugin's timer there is no current frame and this
function is identical to ``prepend_frame()``.
See ``prepend_frame()`` for more details.
.. function:: EvdevDevice:disable_feature(feature_name)
Disable the given libinput-internal feature for this device. This should be used
by plugins that replace that feature with a custom implementation for this device.
libinput may have multiple internal implementations for any given feature, disabling
it via this API disables any and all of those implementations, causing the feature to
no longer work at all. It is up to the plugin implementation to re-implement that
feature to match the user's expectation.
Version 1 of the plugin API supports the following features:
- ``"button-debouncing"``: see :ref:`button_debouncing`
- ``"touchpad-hysteresis"``: see :ref:`touchpad_jitter`
- ``"touchpad-jump-detection"``: see :ref:`touchpad_jumping_cursor`
- ``"touchpad-palm-detection"``: see :ref:`palm_detection`
- ``"wheel-debouncing"``: some high-resolution mouse wheel movements inside libinput
are delayed and/or modified

View file

@ -4,16 +4,10 @@ if not sphinx.found()
error('Program "sphinx-build" not found or not executable. Try building with -Ddocumentation=false') error('Program "sphinx-build" not found or not executable. Try building with -Ddocumentation=false')
endif endif
yq = find_program('yq', required : false)
if not yq.found()
warning('Program "yq" not found or not executable. Dependency list will not be built.')
endif
sphinx_config = configuration_data() sphinx_config = configuration_data()
sphinx_config.set('PROJECT_NAME', meson.project_name()) sphinx_config.set('PROJECT_NAME', meson.project_name())
sphinx_config.set('PROJECT_VERSION', meson.project_version()) sphinx_config.set('PROJECT_VERSION', meson.project_version())
sphinx_config.set('BUILDDIR', meson.current_build_dir()) sphinx_config.set('BUILDDIR', meson.current_build_dir())
sphinx_config.set('HTTP_DOC_LINK', doc_url)
git_version_page = vcs_tag(command : ['git', 'log', '-1', '--format=%H'], git_version_page = vcs_tag(command : ['git', 'log', '-1', '--format=%H'],
fallback : 'unknown', fallback : 'unknown',
@ -50,7 +44,6 @@ src_404s = [
[ 'faqs.rst', 'faq.html'], [ 'faqs.rst', 'faq.html'],
[ 'features.rst', 'features.html'], [ 'features.rst', 'features.html'],
[ 'gestures.rst', 'gestures.html'], [ 'gestures.rst', 'gestures.html'],
[ 'incorrectly-enabled-hires.rst', 'incorrectly-enabled-hires.html'],
[ 'middle-button-emulation.rst', 'middle_button_emulation.html'], [ 'middle-button-emulation.rst', 'middle_button_emulation.html'],
[ 'normalization-of-relative-motion.rst', 'motion_normalization.html'], [ 'normalization-of-relative-motion.rst', 'motion_normalization.html'],
[ 'palm-detection.rst', 'palm_detection.html'], [ 'palm-detection.rst', 'palm_detection.html'],
@ -95,13 +88,11 @@ src_rst = files(
# dot drawings # dot drawings
'dot/seats-sketch.gv', 'dot/seats-sketch.gv',
'dot/seats-sketch-libinput.gv', 'dot/seats-sketch-libinput.gv',
'dot/libinput-contexts.gv',
'dot/libinput-stack-wayland.gv', 'dot/libinput-stack-wayland.gv',
'dot/libinput-stack-xorg.gv', 'dot/libinput-stack-xorg.gv',
'dot/libinput-stack-gnome.gv', 'dot/libinput-stack-gnome.gv',
'dot/evemu.gv', 'dot/evemu.gv',
'dot/libinput-record.gv', 'dot/libinput-record.gv',
'dot/plugin-stack.gv',
# svgs # svgs
'svg/button-debouncing-wave-diagram.svg', 'svg/button-debouncing-wave-diagram.svg',
'svg/button-scrolling.svg', 'svg/button-scrolling.svg',
@ -112,7 +103,6 @@ src_rst = files(
'svg/palm-detection.svg', 'svg/palm-detection.svg',
'svg/pinch-gestures.svg', 'svg/pinch-gestures.svg',
'svg/pinch-gestures-softbuttons.svg', 'svg/pinch-gestures-softbuttons.svg',
'svg/ptraccel-custom.svg',
'svg/ptraccel-linear.svg', 'svg/ptraccel-linear.svg',
'svg/ptraccel-low-dpi.svg', 'svg/ptraccel-low-dpi.svg',
'svg/ptraccel-touchpad.svg', 'svg/ptraccel-touchpad.svg',
@ -122,11 +112,8 @@ src_rst = files(
'svg/software-buttons-thumbpress.svg', 'svg/software-buttons-thumbpress.svg',
'svg/software-buttons-visualized.svg', 'svg/software-buttons-visualized.svg',
'svg/swipe-gestures.svg', 'svg/swipe-gestures.svg',
'svg/tablet-area.svg',
'svg/tablet-axes.svg', 'svg/tablet-axes.svg',
'svg/tablet-cintiq24hd-modes.svg', 'svg/tablet-cintiq24hd-modes.svg',
'svg/tablet-eraser-invert.svg',
'svg/tablet-eraser-button.svg',
'svg/tablet-interfaces.svg', 'svg/tablet-interfaces.svg',
'svg/tablet-intuos-modes.svg', 'svg/tablet-intuos-modes.svg',
'svg/tablet-left-handed.svg', 'svg/tablet-left-handed.svg',
@ -145,19 +132,15 @@ src_rst = files(
'building.rst', 'building.rst',
'button-debouncing.rst', 'button-debouncing.rst',
'clickpad-softbuttons.rst', 'clickpad-softbuttons.rst',
'clickpad-with-right-button.rst',
'contributing.rst', 'contributing.rst',
'device-configuration-via-udev.rst', 'device-configuration-via-udev.rst',
'device-quirks.rst', 'device-quirks.rst',
'drag-3fg.rst',
'faqs.rst', 'faqs.rst',
'gestures.rst', 'gestures.rst',
'incorrectly-enabled-hires.rst', 'index.rst',
'ignoring-devices.rst',
'middle-button-emulation.rst', 'middle-button-emulation.rst',
'normalization-of-relative-motion.rst', 'normalization-of-relative-motion.rst',
'palm-detection.rst', 'palm-detection.rst',
'lua-plugins.rst',
'pointer-acceleration.rst', 'pointer-acceleration.rst',
'reporting-bugs.rst', 'reporting-bugs.rst',
'scrolling.rst', 'scrolling.rst',
@ -179,39 +162,27 @@ src_rst = files(
'trackpoints.rst', 'trackpoints.rst',
'trackpoint-configuration.rst', 'trackpoint-configuration.rst',
'what-is-libinput.rst', 'what-is-libinput.rst',
'wheel-api.rst',
'features.rst', 'features.rst',
'development.rst', 'development.rst',
'troubleshooting.rst', 'troubleshooting.rst',
'configuration.rst', 'configuration.rst',
) )
config_noop = configuration_data()
# Set a dummy replacement to silence meson warnings:
# meson.build:487: WARNING: Got an empty configuration_data() object and
# found no substitutions in the input file 'foo'. If you
# want to copy a file to the build dir, use the 'copy:'
# keyword argument added in 0.47.0
config_noop.set('dummy', 'dummy')
src_sphinx = [] src_sphinx = []
foreach f : src_rst foreach f : src_rst
sf = configure_file(input: f, sf = configure_file(input: f,
output: '@PLAINNAME@', output: '@PLAINNAME@',
copy : true) configuration : config_noop)
src_sphinx += [ sf ] src_sphinx += [ sf ]
endforeach endforeach
configure_file(input: 'index.rst',
output: 'index.rst',
configuration: sphinx_config)
dependencies_config = configuration_data()
if yq.found()
distributions = ['fedora', 'ubuntu', 'debian', 'arch', 'alpine']
foreach distro : distributions
yq_filter = '.distributions[] | select(.name == "@0@") | .packages | join(" ")'.format(distro)
deps = run_command(yq, '-r', yq_filter,
dir_gitlab_ci / 'config.yml',
check: true).stdout()
dependencies_config.set('@0@_PACKAGES'.format(distro.to_upper()), deps)
endforeach
endif
configure_file(input: 'dependencies.rst',
output: 'dependencies.rst',
configuration: dependencies_config)
# do not use -j, it breaks on Ubuntu # do not use -j, it breaks on Ubuntu
sphinx_output_dir = 'Documentation' sphinx_output_dir = 'Documentation'
@ -219,6 +190,5 @@ custom_target('sphinx',
input : [ sphinx_conf_py, git_version_page ] + src_sphinx + dst_404s, input : [ sphinx_conf_py, git_version_page ] + src_sphinx + dst_404s,
output : [ sphinx_output_dir ], output : [ sphinx_output_dir ],
command : [ sphinx, '-q', '-b', 'html', command : [ sphinx, '-q', '-b', 'html',
'-d', meson.current_build_dir() / 'doctrees',
meson.current_build_dir(), sphinx_output_dir], meson.current_build_dir(), sphinx_output_dir],
build_by_default : true) build_by_default : true)

View file

@ -27,11 +27,6 @@ libinput applies a dpi-dependent acceleration function. At low speeds, a
movement speed increases, acceleration is applied - at high speeds a low-dpi movement speed increases, acceleration is applied - at high speeds a low-dpi
device will roughly feel the same as a higher-dpi mouse. 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 This normalization only applies to accelerated coordinates, unaccelerated
coordinates are left in device-units. It is up to the caller to interpret coordinates are left in device-units. It is up to the caller to interpret
those coordinates correctly. those coordinates correctly.

View file

@ -27,7 +27,6 @@ hardware-specific capabilities.
- :ref:`palm_exclusion_zones` - :ref:`palm_exclusion_zones`
- :ref:`trackpoint-disabling` - :ref:`trackpoint-disabling`
- :ref:`disable-while-typing` - :ref:`disable-while-typing`
- :ref:`disable-while-trackpointing`
- :ref:`stylus-touch-arbitration` - :ref:`stylus-touch-arbitration`
Palm detection is always enabled, with the exception of Palm detection is always enabled, with the exception of
@ -92,8 +91,9 @@ Another exclusion zone is defined on the top edge of the touchpad. As with
the edge zones, libinput detects vertical movements out of the edge zone and the edge zones, libinput detects vertical movements out of the edge zone and
avoids palm detection on such touch sequences. avoids palm detection on such touch sequences.
A touch starting in the exclusion zone does not trigger a tap (see Each side edge exclusion zone is divided into a top part and a bottom part.
:ref:`tapping`). 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. In the diagram below, the exclusion zones are painted red.
Touch 'A' starts inside the exclusion zone and moves Touch 'A' starts inside the exclusion zone and moves
@ -103,8 +103,10 @@ despite moving out of the exclusion zone.
Touch 'B' starts inside the exclusion zone but moves horizontally out of the Touch 'B' starts inside the exclusion zone but moves horizontally out of the
zone. It is considered a valid touch and controls the cursor. zone. It is considered a valid touch and controls the cursor.
Touch 'C' occurs in the exclusion zone. Despite being a tapping motion, it does Touch 'C' occurs in the top part of the exclusion zone. Despite being a
not generate an emulated button event. 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.
.. figure:: palm-detection.svg .. figure:: palm-detection.svg
:align: center :align: center
@ -155,29 +157,10 @@ Notable behaviors of libinput's disable-while-typing feature:
typing. typing.
- Physical buttons work even while the touchpad is disabled. This includes - Physical buttons work even while the touchpad is disabled. This includes
:ref:`software-emulated buttons <t440_support>`. :ref:`software-emulated buttons <t440_support>`.
- libinput pairs touchpads and keyboards for the disable-while-typing
feature. In the most common case, the internal touchpad is paired only
with the internal keyboard. Typing on an external keyboard will thus not
disable the touchpad. Some devices require a :ref:`quirk <device-quirks>`
to be correctly paired.
Disable-while-typing can be enabled and disabled by calling Disable-while-typing can be enabled and disabled by calling
**libinput_device_config_dwt_set_enabled()**. **libinput_device_config_dwt_set_enabled()**.
.. _disable-while-trackpointing:
------------------------------------------------------------------------------
Disable-while-trackpointing
------------------------------------------------------------------------------
libinput automatically disables the touchpad for a timeout after the trackpoint
is moved, a feature referred to as "disable while trackpointing". libinput does
not require an external command and the feature is currently enabled for all
touchpads.
Disable-while-trackpointing can be enabled and disabled by calling
**libinput_device_config_dwtp_set_enabled()**.
.. _stylus-touch-arbitration: .. _stylus-touch-arbitration:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------

View file

@ -19,18 +19,12 @@ Pointer acceleration profiles
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
The profile decides the general method of pointer acceleration. The profile decides the general method of pointer acceleration.
libinput currently supports three profiles: **"adaptive"**, **"flat"** and libinput currently supports two profiles: "adaptive" and "flat". The adaptive
**"custom"**. 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
- The **adaptive** profile is the default profile for all devices and takes the is simply a constant factor applied to all device deltas, regardless of the
current speed of the device into account when deciding on acceleration. speed of motion (see :ref:`ptraccel-profile-flat`). Most of this document
- The **flat** profile is simply a constant factor applied to all device deltas, describes the adaptive pointer acceleration.
regardless of the speed of motion (see :ref:`ptraccel-profile-flat`).
- The **custom** profile allows the user to define a custom acceleration
function, giving full control over accelerations behavior at different speed
(see :ref:`ptraccel-profile-custom`).
Most of this document describes the adaptive pointer acceleration.
.. _ptraccel-velocity: .. _ptraccel-velocity:
@ -172,7 +166,7 @@ what is a unit again.
libinput attempts to normalize unit data to the best of its abilities, see libinput attempts to normalize unit data to the best of its abilities, see
:ref:`trackpoint_multiplier`. Beyond this, it is not possible to have :ref:`trackpoint_multiplier`. Beyond this, it is not possible to have
consistent behavior across different trackpoint devices. consistent behavior across different touchpad devices.
.. figure:: ptraccel-trackpoint.svg .. figure:: ptraccel-trackpoint.svg
:align: center :align: center
@ -202,95 +196,3 @@ Pointer acceleration on tablets
Pointer acceleration for relative motion on tablet devices is a flat Pointer acceleration for relative motion on tablet devices is a flat
acceleration, with the speed setting slowing down or speeding up the pointer acceleration, with the speed setting slowing down or speeding up the pointer
motion by a constant factor. Tablets do not allow for switchable profiles. motion by a constant factor. Tablets do not allow for switchable profiles.
.. _ptraccel-profile-custom:
------------------------------------------------------------------------------
The custom acceleration profile
------------------------------------------------------------------------------
libinput supports a user-defined custom acceleration profile, which can be
adjusted for different movement types supported by a device. Movement types
include pointer movement, scrolling, etc. but the set of supported
movement types depends on the device.
The custom pointer acceleration profile gives users full control over the
acceleration behavior at different speeds. libinput exposes
an acceleration function ``f(x)`` where the x axis is the device speed in
device units per millisecond and the y axis is the pointer speed. By
supplying the y axis values for this function, users can control the
behavior of the device.
The user should take into account the native device dpi and screen dpi in
order to achieve the desired behavior/feel.
The custom acceleration function is defined using ``n`` points which are spaced
uniformly along the x axis, starting from 0 and continuing in constant steps.
At least two points must be defined and there is an implementation-defined
limit on how many points may be added.
Thus the points defining the custom function are:
``(0 * step, f[0]), (1 * step, f[1]), ..., ((n-1) * step, f[n-1])``
where ``f`` is a list of ``n`` values defining the output velocity for each
input velocity.
The acceleration factor is defined by the ratio of the output velocity to the
input velocity.
When a velocity value does not lie exactly on those points, a linear
interpolation of the two closest points will be calculated.
When a velocity value is greater than the max point defined, a linear
extrapolation of the two biggest points will be calculated.
the calculation made by libinput: ::
input_delta = device delta units
delta_time = time in ms since last input_delta
input_speed = hypot(input_delta) / delta_time
output_speed = user_custom_function(input_speed)
acceleration_factor = output_speed / input_speed
output_delta = input_delta * acceleration_factor
An example is the curve of ``0.0, 1.0`` with a step of ``1.0``. This curve
is the equivalent of the flat acceleration profile with any input speed ``N``
mapped to the same pointer speed ``N``. The curve ``1.0, 1.0`` neutralizes
any input speed differences and results in a fixed pointer speed.
Another example is the custom acceleration function ``x**2``,
sampling the function at ``4`` points up to
a maximum input speed of ``9`` will give us a custom function with
a step of ``3`` and points ``[0.0, 9.0, 36.0, 81.0]``:
.. figure:: ptraccel-custom.svg
:align: center
More sampled points can be added to improve the accuracy of the user custom
function.
Supported Movement types:
+---------------+---------------------------------+----------------------+
| Movement type | Uses | supported by |
+===============+=================================+======================+
| Fallback | Catch-all default movement type | All devices |
+---------------+---------------------------------+----------------------+
| Motion | Used for pointer motion | All devices |
+---------------+---------------------------------+----------------------+
| Scroll | Used for scroll movement | Mouse, Touchpad |
+---------------+---------------------------------+----------------------+
If a user does not provide the fallback custom acceleration function, a
flat acceleration function is used, i.e. no acceleration.
The fallback acceleration may be used for different types of movements, it is
strongly recommended that this acceleration function is a constant function.
For example, a touchpad has multiple movement types: pointer
movement, scroll movement, zoom movement (pinch), etc. As there is no separate
movement type for zoom yet, zoom movement is accelerated using the Fallback
acceleration function. Pointer movement is accelerated using the Motion
acceleration function, and Scroll movement is accelerated using the Scroll
acceleration function. If no Motion/Scroll acceleration function is set, the
Fallback acceleration function is used.
When using custom acceleration profile, any calls to set the speed have no
effect on the behavior of the custom acceleration function, but any future calls to
get the speed will reflect the requested speed setting.

View file

@ -64,11 +64,7 @@ For the vast majority of bugs you should not take longer than 5 seconds or
three interactions (clicks, touches, taps, ...) with the device to three interactions (clicks, touches, taps, ...) with the device to
reproduce. If it takes longer than that, you can narrow it down further. reproduce. If it takes longer than that, you can narrow it down further.
Once you can reproduce it, use the :ref:`libinput-debug-events` helper Once you can reproduce it, use the :ref:`libinput-debug-events` helper tool.
tool::
$> libinput debug-events --verbose
The output is textual and can help identify whether the bug is in libinput The output is textual and can help identify whether the bug is in libinput
at all. Note that any configuration options you have set must be specified at all. Note that any configuration options you have set must be specified
on the commandline, see the :ref:`libinput-debug-events` on the commandline, see the :ref:`libinput-debug-events`
@ -113,8 +109,8 @@ When you file a bug, please attach the following information:
- the output from udevadm info, see :ref:`udev_info`. - the output from udevadm info, see :ref:`udev_info`.
- the vendor model number of your laptop (e.g. "Lenovo Thinkpad T440s") - the vendor model number of your laptop (e.g. "Lenovo Thinkpad T440s")
- and the content of ``/sys/class/dmi/id/modalias``. - and the content of ``/sys/class/dmi/id/modalias``.
- run ``libinput measure touchpad-size`` tool (see :ref:`absolute_coordinate_ranges_fix`) - run the ``touchpad-edge-detector`` tool (provided by libevdev) and verify
and verify that the ranges and sizes it prints match the touchpad (up to 5mm that the ranges and sizes it prints match the touchpad (up to 5mm
difference is ok) difference is ok)
If you are reporting a bug related to button event generation: If you are reporting a bug related to button event generation:
@ -170,7 +166,8 @@ When you file a bug, please attach the following information:
This is the most important piece of information, do not forget it! This is the most important piece of information, do not forget it!
- the vendor model number of the device (e.g. "Logitech M325") - the vendor model number of the device (e.g. "Logitech M325")
- the output from udevadm info, see :ref:`udev_info`. - the output from udevadm info, see :ref:`udev_info`.
- the sensitivity of the trackpoint if it exists (adjust the event node number as needed): :: - the output of ``libinput measure trackpoint-range``
- the sensitivity of the trackpoint (adjust the event node number as needed): ::
$ cat /sys/class/input/event17/device/device/sensitivity $ cat /sys/class/input/event17/device/device/sensitivity
@ -304,7 +301,7 @@ updated its package accordingly.
Whether the bug fix ends up in your distribution depends on a number of Whether the bug fix ends up in your distribution depends on a number of
things. Any given bug fix **may** be cherry-picked into the current stable things. Any given bug fix **may** be cherry-picked into the current stable
branch, depending on its severity, impact, and likelihood to cause branch, depending on its severity, impact, and likelyhood to cause
regressions. Once cherry-picked it will land in the next stable branch regressions. Once cherry-picked it will land in the next stable branch
release. These are usually a few weeks apart. release. These are usually a few weeks apart.
@ -345,51 +342,3 @@ However, if the regression is in behavior unrelated to the fix itself it is
usually better to file a new bug to reduce the noise. For example, if a fix usually better to file a new bug to reduce the noise. For example, if a fix
to improve tapping breaks two-finger scrolling behavior, you should file a to improve tapping breaks two-finger scrolling behavior, you should file a
new bug but reference the original bug. new bug but reference the original bug.
.. _reporting_bugs_tags:
------------------------------------------------------------------------------
Gitlab issue tracker tags
------------------------------------------------------------------------------
The gitlab issue tracker allows developers to add tags to bugs to classify
them.
- **being worked on**: someone is currently working on this feature. This
tag is used for features that will take a long time to implement fully and
prevents others from having to duplicate the work. Do reach out and ask if
help and/or further testing is needed.
- **bug**: issue is confirmed to be a bug
- **cantfix**: for technical reasons, this bug cannot be fixed, or at least
it cannot be fixed in libinput.
- **enhancement**: this issue describes a future feature, not a bug.
- **help needed**: this issue requires someone outside the libinput core
developer team to implement it. It is unlikely to be implemented
without someone stepping up to do the work. If you do see this tag, do ask
for guidance on how to implement it.
- **hw issue**: an issue that affects a specific device and is a hardware
bug, not a software bug. Often these needs to be worked around in libinput
but there are cases where a hw issue ends up as *cantfix*.
- **janitor**: a cleanup task that does not substantially affect how
libinput works. These are usually good bugs for newcomers to start on.
- **kernel**: this issue is a kernel bug, not a libinput bug. Often closed
as *cantfix* of *wontfix* as we wait for the kernel to address the issue
instead.
- **needs triage**: bug has not yet been confirmed by a core developer.
- **not our bug**: the issue is in some other component of the stack and
needs to be addressed there.
- **please test**: a fix is available but not yet merged and should be
tested by the reporter or others affected by the issue.
- **quirk**: this is issue needs :ref:`device-quirks` to be fixed
- **regression**: the issue is a regression to previous versions of
libinput. These issues get priorities.
- **waiting on reporter**: some more information is required from the
reporter and the issue cannot be fixed until the issue has been provided.
Where a bug is left in this state for too long, the bug will be closed as
*cantfix*.
- **wontfix**: this issue will not get fixed. This tag is usually assigned
to feature requests that are outside the scope of libinput or would put an
unreasonable maintenance burdern on the maintainers.
These tags are high-level categories only, always look for the comments in
the issue to get further details.

View file

@ -52,9 +52,9 @@ vertically or horizontally.
Vertical and horizontal two-finger scrolling Vertical and horizontal two-finger scrolling
For scrolling to trigger, a built-in distance threshold has to be met, but once 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 engaged any movement will scroll. In other words, to start scrolling a
sufficiently large movement is required; once scrolling, tiny amounts of sufficiently large movement is required, once scrolling tiny amounts of
movements will translate into tiny scroll movements. movements will translate into tiny scroll movements.
Scrolling in both directions at once is possible by meeting the required Scrolling in both directions at once is possible by meeting the required
distance thresholds to enable each direction separately. distance thresholds to enable each direction separately.
@ -117,28 +117,12 @@ the motion events. Cross-device scrolling is not supported but
for one exception: libinput's :ref:`t440_support` enables the use of the middle for one exception: libinput's :ref:`t440_support` enables the use of the middle
button for button scrolling (even when the touchpad is disabled). button for button scrolling (even when the touchpad is disabled).
If the scroll button lock is enabled (see
**libinput_device_config_scroll_set_button_lock()**), the button does not
need to be held down. Pressing and releasing the button once enables the
button lock, the button is now considered logically held down. Pressing and
releasing the button a second time logically releases the button. While the
button is logically held down, motion events are converted to scroll events.
If the button is held and used to scroll for longer than a short grace
period, releasing the button does not engage the lock. This allows
hold-to-scroll for short, precise adjustments without accidentally toggling
the lock. A quick click or a brief scroll within the grace period still
engages the lock as normal.
.. _scroll_sources: .. _scroll_sources:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
Scroll sources Scroll sources
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
.. note:: Scroll sources are deprecated with libinput 1.19. The scroll
source is now encoded in the event type.
libinput provides a pointer axis *source* for each scroll event. The libinput provides a pointer axis *source* for each scroll event. The
source can be obtained with the **libinput_event_pointer_get_axis_source()** source can be obtained with the **libinput_event_pointer_get_axis_source()**
function and is one of **wheel**, **finger**, or **continuous**. The source function and is one of **wheel**, **finger**, or **continuous**. The source
@ -156,23 +140,3 @@ See the **libinput_event_pointer_get_axis_source()** for details on the
behavior of each scroll source. behavior of each scroll source.
See also http://who-t.blogspot.com.au/2015/03/libinput-scroll-sources.html See also http://who-t.blogspot.com.au/2015/03/libinput-scroll-sources.html
.. _natural_scrolling:
------------------------------------------------------------------------------
Natural scrolling vs. traditional scrolling
------------------------------------------------------------------------------
Natural scrolling is the term (probably) coined by Apple for matching
the motion of the scroll device with the direction of the **content**.
In traditional scrolling, moving the wheel down causes the scroll bar
indicators to move down and the content to move up. In natural scrolling,
moving the wheel down causes the content to move down and the scroll bar
indicators to move up. This method of scrolling matches the interaction
with content on touch screens where a movement down also moves the content
down.
libinput supports natural scrolling for all its scroll methods; it can
be enabled with the
**libinput_device_config_scroll_set_natural_scroll_enabled()** function.

View file

@ -138,6 +138,13 @@
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)" 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" 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" /> 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.30510259px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3490"
width="65.310997"
height="136.12065"
x="7.0411549"
y="7.1355872" />
<text <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" 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"
xml:space="preserve" xml:space="preserve"
@ -148,6 +155,13 @@
id="tspan13876" id="tspan13876"
y="63.628628" y="63.628628"
x="33.214291">A</tspan></text> 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.22849"
y="6.8830237" />
<text <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" 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"
xml:space="preserve" xml:space="preserve"
@ -177,6 +191,16 @@
id="tspan13876-7-9" id="tspan13876-7-9"
y="46.009491" y="46.009491"
x="342.27759">C</tspan></text> x="342.27759">C</tspan></text>
<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"
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 <circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1" style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1"
id="path4401" id="path4401"
@ -184,6 +208,13 @@
cy="24.53549" cy="24.53549"
r="4.0658817" r="4.0658817"
transform="scale(-1,1)" /> transform="scale(-1,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)" />
<rect <rect
width="248.87633" width="248.87633"
height="6.8111157" height="6.8111157"

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 27 KiB

View file

@ -208,3 +208,4 @@
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -1,228 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="229.5488mm"
height="86.66362mm"
viewBox="0 0 813.36188 307.07582"
id="svg2"
version="1.1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
sodipodi:docname="tablet-area.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4">
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4294"
id="linearGradient4300"
x1="465.81339"
y1="666.13727"
x2="454.82117"
y2="658.65521"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
id="linearGradient4294">
<stop
style="stop-color:#1a1a1a;stop-opacity:1;"
offset="0"
id="stop4296" />
<stop
style="stop-color:#808080;stop-opacity:1"
offset="1"
id="stop4298" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8"
inkscape:cx="410.53571"
inkscape:cy="188.39286"
inkscape:document-units="px"
inkscape:current-layer="layer3"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="3072"
inkscape:window-height="1659"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="tablet"
inkscape:groupmode="layer"
id="layer1"
style="display:inline"
transform="translate(67.109152,-133.63374)">
<g
id="g4309"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
transform="translate(0,1.0715222)">
<rect
y="134.15933"
x="75.787216"
height="306.02466"
width="522.19733"
id="rect4136"
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:1.05118;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:4.20473, 1.05118;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.748138;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:2.99255, 0.748138;stroke-dashoffset:0;stroke-opacity:1"
id="rect4140"
width="357.34042"
height="226.52563"
x="199.33878"
y="175.42407" />
<rect
y="175.72914"
x="103.10225"
height="22.142857"
width="65"
id="rect4142"
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.989;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.989;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1"
id="rect4148"
width="65"
height="22.142857"
x="103.10225"
y="203.72914" />
<rect
y="231.72913"
x="103.10225"
height="22.142857"
width="65"
id="rect4150"
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.989;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" />
<rect
y="323.72913"
x="103.10225"
height="22.142857"
width="65"
id="rect4154"
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.989;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.989;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1"
id="rect4156"
width="65"
height="22.142857"
x="103.10225"
y="351.72913" />
<circle
r="22.98097"
cy="287.06125"
cx="135.61298"
id="path4158"
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.989;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" />
<ellipse
ry="12.608653"
rx="11.5985"
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.520431;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:2.08172, 0.520431;stroke-dashoffset:0;stroke-opacity:1"
id="circle4160"
cx="135.61298"
cy="287.06125" />
<rect
y="379.72913"
x="103.10225"
height="22.142857"
width="65"
id="rect4162"
style="opacity:0.92;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.989;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="area">
<rect
style="display:inline;fill:#a44d4d;fill-opacity:1;stroke:none;stroke-width:0.675728"
id="rect1"
width="131.51813"
height="126.57689"
x="326.15009"
y="97.775696" />
<text
xml:space="preserve"
style="display:inline;font-size:11.25px;fill:#a44d4d;fill-opacity:1;stroke:none;stroke-width:0.9375"
x="261.92404"
y="244.01244"
id="text1"
transform="translate(67.109152,-133.63374)"><tspan
sodipodi:role="line"
id="tspan1"
style="fill:#000000;stroke-width:0.9375"
x="261.92404"
y="244.01244">0/0</tspan></text>
<path
style="display:inline;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.9375;stroke-linecap:round;stroke-dasharray:none"
d="m 259.17629,227.63135 v 7.63349"
id="path1"
transform="translate(67.109152,-133.63374)" />
<path
style="display:inline;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.9375;stroke-linecap:round;stroke-dasharray:none"
d="m 262.99304,231.44809 h -7.63349"
id="path2"
transform="translate(67.109152,-133.63374)" />
</g>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="stylus"
style="display:inline"
transform="translate(67.109152,-133.63374)">
<g
id="g4304"
transform="matrix(0.37129971,0.09948946,-0.09618892,0.35898192,319.19555,24.123239)"
style="display:inline">
<path
sodipodi:nodetypes="czcc"
inkscape:connector-curvature="0"
id="path4286"
d="m 387.83544,799.76093 c -1.1128,3.61694 -3.2211,13.05163 -1.08543,14.07769 2.13567,1.02606 7.81039,-3.72162 10.99756,-6.69095 z"
style="display:inline;fill:#cccccc;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
sodipodi:nodetypes="ssssccssscsssssssssssssssssss"
inkscape:connector-curvature="0"
id="path4283"
d="m 392.64431,804.79039 c -8.52094,-5.90399 -8.49394,-11.01546 0.22879,-43.30647 1.03999,-3.85 2.46829,-9.67602 3.17399,-12.9467 0.99731,-4.62219 2.39455,-7.29497 6.27321,-12 2.74456,-3.32932 5.25157,-6.2783 5.57113,-6.5533 40.78433,-60.97488 80.48307,-125.1652 118.27253,-184 9.86283,-15.675 26.59424,-42.225 37.18089,-59 10.58666,-16.775 34.01422,-53.9 52.06125,-82.5 18.04703,-28.6 35.04505,-55.31677 37.77338,-59.37059 l 4.9606,-7.3706 4.1828,0.57332 c 4.16371,0.5707 4.19706,0.54958 7.30887,-4.62941 3.75631,-6.2516 8.82067,-11.57582 12.2516,-12.88026 5.99391,-2.27888 14.03303,2.9506 14.03303,9.12854 0,3.90203 -2.51704,10.62127 -6.02878,16.09385 -1.63417,2.54664 -2.97122,4.85949 -2.97122,5.13969 0,0.28019 0.9,1.54715 2,2.81546 2.28453,2.63408 2.47267,4.21918 0.86833,7.31574 -1.28218,2.47476 -26.61383,45.18798 -55.85724,94.18426 -10.83283,18.15 -25.72943,43.1137 -33.10357,55.47489 -7.37413,12.3612 -13.69273,23.17153 -14.04131,24.02297 -0.34859,0.85144 -7.50972,12.78774 -15.91363,26.52511 -15.54138,25.40455 -32.24417,52.9052 -70.74345,116.47703 -40.26028,66.47968 -43.66308,72.46026 -49.21634,86.5 -1.74036,4.4 -3.92035,8.675 -4.8444,9.5 -0.92405,0.825 -4.36246,3.75 -7.6409,6.5 -3.27845,2.75 -9.57132,8.3067 -13.98415,12.34823 -10.62726,9.73304 -16.99729,13.87361 -22.52334,14.64034 -3.99187,0.55386 -5.03885,0.251 -9.27207,-2.6821 z"
style="display:inline;fill:#000000" />
<path
sodipodi:nodetypes="scccs"
inkscape:connector-curvature="0"
id="path4292"
d="m 450.89044,688.88586 c 8.71518,5.62513 45.74035,-59.18436 43.57923,-75.43494 l -7.07107,-6.56599 c -29.93081,25.86352 -47.78438,74.72281 -47.78438,74.72281 z"
style="fill:url(#linearGradient4300);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.8 KiB

View file

@ -1,198 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="104.05109mm"
height="64.88131mm"
viewBox="0 0 368.68495 229.89441"
id="svg4321"
version="1.1"
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
sodipodi:docname="tablet-eraser-button.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4323">
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4294"
id="linearGradient4300"
x1="465.81339"
y1="666.13727"
x2="454.82117"
y2="658.65521"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
id="linearGradient4294">
<stop
style="stop-color:#1a1a1a;stop-opacity:1;"
offset="0"
id="stop4296" />
<stop
style="stop-color:#808080;stop-opacity:1"
offset="1"
id="stop4298" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4294"
id="linearGradient3"
gradientUnits="userSpaceOnUse"
x1="465.81339"
y1="666.13727"
x2="454.82117"
y2="658.65521" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8"
inkscape:cx="330.71429"
inkscape:cy="144.28571"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="3072"
inkscape:window-height="1659"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" />
<metadata
id="metadata4326">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-67.741956,-463.35919)">
<g
transform="matrix(0.35596319,-0.1450925,0.14027908,0.34415419,-98.897559,452.82709)"
id="g4304"
style="display:inline">
<path
style="display:inline;fill:#cccccc;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 387.83544,799.76093 c -1.1128,3.61694 -3.2211,13.05163 -1.08543,14.07769 2.13567,1.02606 7.81039,-3.72162 10.99756,-6.69095 z"
id="path4286"
inkscape:connector-curvature="0"
sodipodi:nodetypes="czcc" />
<path
style="display:inline;fill:#000000"
d="m 392.64431,804.79039 c -8.52094,-5.90399 -8.49394,-11.01546 0.22879,-43.30647 1.03999,-3.85 2.46829,-9.67602 3.17399,-12.9467 0.99731,-4.62219 2.39455,-7.29497 6.27321,-12 2.74456,-3.32932 5.25157,-6.2783 5.57113,-6.5533 40.78433,-60.97488 80.48307,-125.1652 118.27253,-184 9.86283,-15.675 26.59424,-42.225 37.18089,-59 10.58666,-16.775 34.01422,-53.9 52.06125,-82.5 18.04703,-28.6 35.04505,-55.31677 37.77338,-59.37059 l 4.9606,-7.3706 4.1828,0.57332 c 4.16371,0.5707 4.19706,0.54958 7.30887,-4.62941 3.75631,-6.2516 8.82067,-11.57582 12.2516,-12.88026 5.99391,-2.27888 14.03303,2.9506 14.03303,9.12854 0,3.90203 -2.51704,10.62127 -6.02878,16.09385 -1.63417,2.54664 -2.97122,4.85949 -2.97122,5.13969 0,0.28019 0.9,1.54715 2,2.81546 2.28453,2.63408 2.47267,4.21918 0.86833,7.31574 -1.28218,2.47476 -26.61383,45.18798 -55.85724,94.18426 -10.83283,18.15 -25.72943,43.1137 -33.10357,55.47489 -7.37413,12.3612 -13.69273,23.17153 -14.04131,24.02297 -0.34859,0.85144 -7.50972,12.78774 -15.91363,26.52511 -15.54138,25.40455 -32.24417,52.9052 -70.74345,116.47703 -40.26028,66.47968 -43.66308,72.46026 -49.21634,86.5 -1.74036,4.4 -3.92035,8.675 -4.8444,9.5 -0.92405,0.825 -4.36246,3.75 -7.6409,6.5 -3.27845,2.75 -9.57132,8.3067 -13.98415,12.34823 -10.62726,9.73304 -16.99729,13.87361 -22.52334,14.64034 -3.99187,0.55386 -5.03885,0.251 -9.27207,-2.6821 z"
id="path4283"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ssssccssscsssssssssssssssssss" />
<path
style="fill:url(#linearGradient4300);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 450.89044,688.88586 c 8.71518,5.62513 45.74035,-59.18436 43.57923,-75.43494 l -7.07107,-6.56599 c -29.93081,25.86352 -47.78438,74.72281 -47.78438,74.72281 z"
id="path4292"
inkscape:connector-curvature="0"
sodipodi:nodetypes="scccs" />
</g>
<rect
transform="scale(1,-1)"
y="-693.18524"
x="67.81031"
height="16.036251"
width="168.54825"
id="rect4136"
style="fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.136709;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:0.546834, 0.136709;stroke-dashoffset:0;stroke-opacity:1" />
<rect
transform="scale(1,-1)"
y="-693.18524"
x="267.8103"
height="16.036251"
width="168.54825"
id="rect5709"
style="opacity:1;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.136709;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:0.546834, 0.136709;stroke-dashoffset:0;stroke-opacity:1" />
<text
id="text5713"
y="559.10828"
x="296.20877"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="559.10828"
x="296.20877"
id="tspan5715"
sodipodi:role="line"
style="font-size:15px;line-height:1.25;font-family:sans-serif">Eraser</tspan></text>
<text
id="text1"
y="559.10828"
x="109.0436"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="559.10828"
x="109.0436"
id="tspan1"
sodipodi:role="line"
style="font-size:15px;line-height:1.25;font-family:sans-serif">Pen</tspan></text>
<g
transform="matrix(0.35596319,-0.1450925,0.14027908,0.34415419,117.39708,452.82709)"
id="g3"
style="display:inline">
<path
style="display:inline;fill:#cccccc;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 387.83544,799.76093 c -1.1128,3.61694 -3.2211,13.05163 -1.08543,14.07769 2.13567,1.02606 7.81039,-3.72162 10.99756,-6.69095 z"
id="path1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="czcc" />
<path
style="display:inline;fill:#000000"
d="m 392.64431,804.79039 c -8.52094,-5.90399 -8.49394,-11.01546 0.22879,-43.30647 1.03999,-3.85 2.46829,-9.67602 3.17399,-12.9467 0.99731,-4.62219 2.39455,-7.29497 6.27321,-12 2.74456,-3.32932 5.25157,-6.2783 5.57113,-6.5533 40.78433,-60.97488 80.48307,-125.1652 118.27253,-184 9.86283,-15.675 26.59424,-42.225 37.18089,-59 10.58666,-16.775 34.01422,-53.9 52.06125,-82.5 18.04703,-28.6 35.04505,-55.31677 37.77338,-59.37059 l 4.9606,-7.3706 4.1828,0.57332 c 4.16371,0.5707 4.19706,0.54958 7.30887,-4.62941 3.75631,-6.2516 8.82067,-11.57582 12.2516,-12.88026 5.99391,-2.27888 14.03303,2.9506 14.03303,9.12854 0,3.90203 -2.51704,10.62127 -6.02878,16.09385 -1.63417,2.54664 -2.97122,4.85949 -2.97122,5.13969 0,0.28019 0.9,1.54715 2,2.81546 2.28453,2.63408 2.47267,4.21918 0.86833,7.31574 -1.28218,2.47476 -26.61383,45.18798 -55.85724,94.18426 -10.83283,18.15 -25.72943,43.1137 -33.10357,55.47489 -7.37413,12.3612 -13.69273,23.17153 -14.04131,24.02297 -0.34859,0.85144 -7.50972,12.78774 -15.91363,26.52511 -15.54138,25.40455 -32.24417,52.9052 -70.74345,116.47703 -40.26028,66.47968 -43.66308,72.46026 -49.21634,86.5 -1.74036,4.4 -3.92035,8.675 -4.8444,9.5 -0.92405,0.825 -4.36246,3.75 -7.6409,6.5 -3.27845,2.75 -9.57132,8.3067 -13.98415,12.34823 -10.62726,9.73304 -16.99729,13.87361 -22.52334,14.64034 -3.99187,0.55386 -5.03885,0.251 -9.27207,-2.6821 z"
id="path2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ssssccssscsssssssssssssssssss" />
<path
style="fill:url(#linearGradient3);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 450.89044,688.88586 c 8.71518,5.62513 45.74035,-59.18436 43.57923,-75.43494 l -7.07107,-6.56599 c -29.93081,25.86352 -47.78438,74.72281 -47.78438,74.72281 z"
id="path3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="scccs" />
</g>
<g
transform="matrix(-0.21797128,-0.07136846,0.05329769,-0.25512499,403.9107,823.07273)"
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 h -0.71428 z"
id="path2820-6-7"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
d="m 360.32021,827.78041 c -15.74169,-35.7991 -29.44655,-66.92657 -30.45523,-69.17214 -7.08929,-15.78239 -10.8761,-32.88254 -9.6176,-43.43026 1.39575,-11.69796 7.19746,-18.50389 18.22574,-21.38044 5.18218,-1.35169 8.54724,-1.76827 12.41155,-1.53649 4.43642,0.26609 6.95929,0.93715 11.03011,2.93391 3.93491,1.9301 8.0085,5.56248 10.68932,9.53159 3.68818,5.46055 26.56068,50.9623 49.57778,98.62829 16.60192,34.38082 37.06388,77.41994 36.89013,77.59369 -0.13286,0.13286 -69.01932,11.92114 -69.66286,11.92114 -0.27909,0 -12.00972,-26.24842 -29.08894,-65.08929 z"
id="path2824-1-6"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
inkscape:connector-curvature="0" />
<path
d="m 334.75785,756.75053 c -7.08929,-15.78239 -10.28437,-26.89033 -9.02587,-37.43805 1.39575,-11.69796 5.8085,-16.73613 16.83678,-19.61268 12.44766,-3.59459 20.03902,-1.91353 27.39013,8.75815 11.42622,25.66382 13.40166,29.05484 15.06365,35.48866 -0.13286,0.13286 -42.89663,15.49027 -44.57776,16.18518 -1.72922,0.71479 -4.94789,-2.09377 -5.68693,-3.38126 z"
id="path2824-7-1-7"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.92;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>
</svg>

Before

Width:  |  Height:  |  Size: 12 KiB

View file

@ -1,179 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="104.05109mm"
height="64.88131mm"
viewBox="0 0 368.68495 229.89441"
id="svg4321"
version="1.1"
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
sodipodi:docname="tablet-eraser-invert.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs4323">
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4294"
id="linearGradient4300"
x1="465.81339"
y1="666.13727"
x2="454.82117"
y2="658.65521"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
id="linearGradient4294">
<stop
style="stop-color:#1a1a1a;stop-opacity:1;"
offset="0"
id="stop4296" />
<stop
style="stop-color:#808080;stop-opacity:1"
offset="1"
id="stop4298" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4294"
id="linearGradient5721"
gradientUnits="userSpaceOnUse"
x1="465.81339"
y1="666.13727"
x2="454.82117"
y2="658.65521" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8"
inkscape:cx="330.71429"
inkscape:cy="144.28571"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="3072"
inkscape:window-height="1659"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" />
<metadata
id="metadata4326">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-67.741956,-463.35919)">
<g
transform="matrix(0.35596319,-0.1450925,0.14027908,0.34415419,-98.897559,452.82709)"
id="g4304"
style="display:inline">
<path
style="display:inline;fill:#cccccc;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 387.83544,799.76093 c -1.1128,3.61694 -3.2211,13.05163 -1.08543,14.07769 2.13567,1.02606 7.81039,-3.72162 10.99756,-6.69095 z"
id="path4286"
inkscape:connector-curvature="0"
sodipodi:nodetypes="czcc" />
<path
style="display:inline;fill:#000000"
d="m 392.64431,804.79039 c -8.52094,-5.90399 -8.49394,-11.01546 0.22879,-43.30647 1.03999,-3.85 2.46829,-9.67602 3.17399,-12.9467 0.99731,-4.62219 2.39455,-7.29497 6.27321,-12 2.74456,-3.32932 5.25157,-6.2783 5.57113,-6.5533 40.78433,-60.97488 80.48307,-125.1652 118.27253,-184 9.86283,-15.675 26.59424,-42.225 37.18089,-59 10.58666,-16.775 34.01422,-53.9 52.06125,-82.5 18.04703,-28.6 35.04505,-55.31677 37.77338,-59.37059 l 4.9606,-7.3706 4.1828,0.57332 c 4.16371,0.5707 4.19706,0.54958 7.30887,-4.62941 3.75631,-6.2516 8.82067,-11.57582 12.2516,-12.88026 5.99391,-2.27888 14.03303,2.9506 14.03303,9.12854 0,3.90203 -2.51704,10.62127 -6.02878,16.09385 -1.63417,2.54664 -2.97122,4.85949 -2.97122,5.13969 0,0.28019 0.9,1.54715 2,2.81546 2.28453,2.63408 2.47267,4.21918 0.86833,7.31574 -1.28218,2.47476 -26.61383,45.18798 -55.85724,94.18426 -10.83283,18.15 -25.72943,43.1137 -33.10357,55.47489 -7.37413,12.3612 -13.69273,23.17153 -14.04131,24.02297 -0.34859,0.85144 -7.50972,12.78774 -15.91363,26.52511 -15.54138,25.40455 -32.24417,52.9052 -70.74345,116.47703 -40.26028,66.47968 -43.66308,72.46026 -49.21634,86.5 -1.74036,4.4 -3.92035,8.675 -4.8444,9.5 -0.92405,0.825 -4.36246,3.75 -7.6409,6.5 -3.27845,2.75 -9.57132,8.3067 -13.98415,12.34823 -10.62726,9.73304 -16.99729,13.87361 -22.52334,14.64034 -3.99187,0.55386 -5.03885,0.251 -9.27207,-2.6821 z"
id="path4283"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ssssccssscsssssssssssssssssss" />
<path
style="fill:url(#linearGradient4300);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 450.89044,688.88586 c 8.71518,5.62513 45.74035,-59.18436 43.57923,-75.43494 l -7.07107,-6.56599 c -29.93081,25.86352 -47.78438,74.72281 -47.78438,74.72281 z"
id="path4292"
inkscape:connector-curvature="0"
sodipodi:nodetypes="scccs" />
</g>
<rect
transform="scale(1,-1)"
y="-693.18524"
x="67.81031"
height="16.036251"
width="168.54825"
id="rect4136"
style="fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.136709;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:0.546834, 0.136709;stroke-dashoffset:0;stroke-opacity:1" />
<g
transform="matrix(-0.36104723,0.13193379,-0.12755691,-0.34906957,644.73068,698.04111)"
id="g5701"
style="display:inline">
<path
style="display:inline;fill:#cccccc;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 387.83544,799.76093 c -1.1128,3.61694 -3.2211,13.05163 -1.08543,14.07769 2.13567,1.02606 7.81039,-3.72162 10.99756,-6.69095 z"
id="path5703"
inkscape:connector-curvature="0"
sodipodi:nodetypes="czcc" />
<path
style="display:inline;fill:#000000"
d="m 392.64431,804.79039 c -8.52094,-5.90399 -8.49394,-11.01546 0.22879,-43.30647 1.03999,-3.85 2.46829,-9.67602 3.17399,-12.9467 0.99731,-4.62219 2.39455,-7.29497 6.27321,-12 2.74456,-3.32932 5.25157,-6.2783 5.57113,-6.5533 40.78433,-60.97488 80.48307,-125.1652 118.27253,-184 9.86283,-15.675 26.59424,-42.225 37.18089,-59 10.58666,-16.775 34.01422,-53.9 52.06125,-82.5 18.04703,-28.6 35.04505,-55.31677 37.77338,-59.37059 l 4.9606,-7.3706 4.1828,0.57332 c 4.16371,0.5707 4.19706,0.54958 7.30887,-4.62941 3.75631,-6.2516 8.82067,-11.57582 12.2516,-12.88026 5.99391,-2.27888 14.03303,2.9506 14.03303,9.12854 0,3.90203 -2.51704,10.62127 -6.02878,16.09385 -1.63417,2.54664 -2.97122,4.85949 -2.97122,5.13969 0,0.28019 0.9,1.54715 2,2.81546 2.28453,2.63408 2.47267,4.21918 0.86833,7.31574 -1.28218,2.47476 -26.61383,45.18798 -55.85724,94.18426 -10.83283,18.15 -25.72943,43.1137 -33.10357,55.47489 -7.37413,12.3612 -13.69273,23.17153 -14.04131,24.02297 -0.34859,0.85144 -7.50972,12.78774 -15.91363,26.52511 -15.54138,25.40455 -32.24417,52.9052 -70.74345,116.47703 -40.26028,66.47968 -43.66308,72.46026 -49.21634,86.5 -1.74036,4.4 -3.92035,8.675 -4.8444,9.5 -0.92405,0.825 -4.36246,3.75 -7.6409,6.5 -3.27845,2.75 -9.57132,8.3067 -13.98415,12.34823 -10.62726,9.73304 -16.99729,13.87361 -22.52334,14.64034 -3.99187,0.55386 -5.03885,0.251 -9.27207,-2.6821 z"
id="path5705"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ssssccssscsssssssssssssssssss" />
<path
style="fill:url(#linearGradient5721);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 450.89044,688.88586 c 8.71518,5.62513 45.74035,-59.18436 43.57923,-75.43494 l -7.07107,-6.56599 c -29.93081,25.86352 -47.78438,74.72281 -47.78438,74.72281 z"
id="path5707"
inkscape:connector-curvature="0"
sodipodi:nodetypes="scccs" />
</g>
<rect
transform="scale(1,-1)"
y="-693.18524"
x="267.8103"
height="16.036251"
width="168.54825"
id="rect5709"
style="opacity:1;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.136709;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:0.546834, 0.136709;stroke-dashoffset:0;stroke-opacity:1" />
<text
id="text5713"
y="559.10828"
x="296.20877"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="559.10828"
x="296.20877"
id="tspan5715"
sodipodi:role="line"
style="font-size:15px;line-height:1.25;font-family:sans-serif">Eraser</tspan></text>
<text
id="text1"
y="559.10828"
x="109.0436"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="559.10828"
x="109.0436"
id="tspan1"
sodipodi:role="line"
style="font-size:15px;line-height:1.25;font-family:sans-serif">Pen</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.4 KiB

View file

@ -4,9 +4,9 @@
Switches Switches
============================================================================== ==============================================================================
libinput supports the lid, tablet-mode, and keypad slide switches. Unlike libinput supports the lid and tablet-mode switches. Unlike button events
button events that come in press and release pairs, switches are usually that come in press and release pairs, switches are usually toggled once and
toggled once and left at the setting for an extended period of time. left at the setting for an extended period of time.
Only some switches are handled by libinput, see **libinput_switch** for a Only some switches are handled by libinput, see **libinput_switch** for a
list of supported switches. Switch events are exposed to the caller, but list of supported switches. Switch events are exposed to the caller, but
@ -28,17 +28,15 @@ The evdev event code ``EV_SW`` ``SW_LID`` is provided as
the device is disabled while the lid is logically closed. This is to avoid the device is disabled while the lid is logically closed. This is to avoid
ghost touches that can be caused by interference with touchpads and the ghost touches that can be caused by interference with touchpads and the
closed lid. The touchpad is automatically re-enabled whenever the lid is closed lid. The touchpad is automatically re-enabled whenever the lid is
opened. openend.
This handling of lid switches is transparent to the user, no notifications This handling of lid switches is transparent to the user, no notifications
are sent and the device appears as enabled at all times. are sent and the device appears as enabled at all times.
On some devices, the device's lid state does not always reflect the physical On some devices, the device's lid state does not always reflect the physical
state and the lid state may report as closed even when the lid is physically state and the lid state may report as closed even when the lid is physicall
open. libinput employs some heuristics to detect user input (specifically open. libinput employs some heuristics to detect user input (specificially
typing) to re-enable the touchpad on those devices. Where input is detected, typing) to re-enable the touchpad on those devices.
libinput updates the lid status of the kernel device so other consumers of
the kernel events also get the accurate state.
.. _switches_tablet_mode: .. _switches_tablet_mode:
@ -59,20 +57,3 @@ tablet mode is disengaged.
This handling of tablet mode switches is transparent to the user, no This handling of tablet mode switches is transparent to the user, no
notifications are sent and the device appears as enabled at all times. notifications are sent and the device appears as enabled at all times.
.. _switches_keypad_slide:
------------------------------------------------------------------------------
Keypad slide switch handling
------------------------------------------------------------------------------
Where available, libinput listens to devices providing a keypad slide switch.
This is usually available on devices that have an always-attached physical
keyboard which can slide under the screen. An example of such a device is the
Nokia N900.
The event sent by the kernel is ``EV_SW`` ``SW_KEYPAD_SLIDE`` and is provided
as **LIBINPUT_SWITCH_KEYPAD_SLIDE**. The keypad slide switch does not cause any
other input devices to be enabled nor disabled in response, since on some
devices the kernel event is sent while the keyboard is partially visible and
thus usable.

View file

@ -39,6 +39,6 @@ the ``libinput record`` tool.
- **resolution** indicates that the device does not have a resolution set - **resolution** indicates that the device does not have a resolution set
for the x and y axes. This can be fixed with a hwdb entry, locate and read for the x and y axes. This can be fixed with a hwdb entry, locate and read
the `60-evdev.hwdb the `60-evdev.hwdb
<https://github.com/systemd/systemd/blob/main/hwdb.d/60-evdev.hwdb>`__ file <https://github.com/systemd/systemd/tree/master/hwdb/60-evdev.hwdb>`__ file
on your machine and file a pull request with the fixes against on your machine and file a pull request with the fixes against
`systemd <https://github.com/systemd/systemd/>`__. `systemd <https://github.com/systemd/systemd/>`__.

View file

@ -180,8 +180,8 @@ specifically:
capable of detection distances, capable of detection distances,
- pressure offset is only detected if the distance between the tool and the - pressure offset is only detected if the distance between the tool and the
tablet is high enough, tablet is high enough,
- pressure offset is only used if it is 50% or less of the pressure range - pressure offset is only used if it is 20% or less of the pressure range
available to the tool. A pressure offset higher than 50% indicates either available to the tool. A pressure offset higher than 20% indicates either
a misdetection or a tool that should be replaced, and a misdetection or a tool that should be replaced, and
- if a pressure value less than the current pressure offset is seen, the - if a pressure value less than the current pressure offset is seen, the
offset resets to that value. offset resets to that value.
@ -189,52 +189,6 @@ specifically:
Pressure offsets are not detected on **LIBINPUT_TABLET_TOOL_TYPE_MOUSE** Pressure offsets are not detected on **LIBINPUT_TABLET_TOOL_TYPE_MOUSE**
and **LIBINPUT_TABLET_TOOL_TYPE_LENS** tools. and **LIBINPUT_TABLET_TOOL_TYPE_LENS** tools.
.. _tablet-pressure-range:
------------------------------------------------------------------------------
Custom tablet tool pressure ranges
------------------------------------------------------------------------------
On tablets supporting pressure, libinput provides that hardware pressure as
a logical range of ``0.0`` up to ``1.0`` for the maximum supported pressure.
By default, the hardware range thus maps into the following logical range::
hw minimum hw maximum
hw range: |------|-----------------------------------|
logical range: |----|-----------------------------------|
0.0 | 1.0
Tip
Note that libinput always has some built-in thresholds to filter out erroneous
touches with near-zero pressure but otherwise the hardware range maps as-is
into the logical range. The :ref:`tip event <tablet-tip>` threshold is defined
within this range.
For some use-cases the full hardware range is not suitable, it may require either
too light a pressure for the user to interact or it may require too hard a
pressure before the logical maximum is reached. libinput provides
the **libinput_tablet_tool_config_pressure_range_set()** function that allows
reducing the usable range of the tablet::
hw minimum hw maximum
hw range: |----------|-------------------------------|
adjusted range: |------|---------------------|
logical range: |----|---------------------|
0.0 | 1.0
Tip
A reduced range as shown above will result in
- all hw pressure below the new minimum to register as logical pressure ``0.0``
- all hw pressure above the new maximum to register as logical pressure ``1.0``
- the tip event threshold to be relative to the new minimum
In other words, adjusting the pressure range of a tablet tool is equivalent to
reducing the hardware range of said tool. Note that where a custom pressure
range is set, detection of :ref:`tablet-pressure-offset` is disabled.
.. _tablet-serial-numbers: .. _tablet-serial-numbers:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -468,77 +422,3 @@ libinput uses the **libinput_device_group** to decide on touch arbitration
and automatically discards touch events whenever a tool is in proximity. and automatically discards touch events whenever a tool is in proximity.
The exact behavior is device-dependent. The exact behavior is device-dependent.
.. _tablet-area:
------------------------------------------------------------------------------
Tablet area
------------------------------------------------------------------------------
External tablet devices such as e.g. the Wacom Intuos series can be configured
to reduce the available logical input area. Typically the logical input area
is equivalent to the physical input area but it can be reduced with the
**libinput_device_config_area_set_rectangle()** call. Once reduced, input
events outside the logical input area are ignored and the logical input area
acts as if it represented the extents of the physical tablet.
.. figure:: tablet-area.svg
:align: center
Tablet area configuration example
In the image above, the area is set to the rectangle 0.25/0.25 to 0.5/0.75.
Even though the tool is roughly at the physical position ``0.5 * width`` and
``0.75 * height``, the return values of
**libinput_event_tablet_tool_get_x_transformed()** and
**libinput_event_tablet_tool_get_y_transformed()** would be close to the
maximum provided in this call.
The size of the tablet reported by **libinput_device_get_size()** always reflects
the physical area, not the logical area.
.. _tablet-eraser-button:
------------------------------------------------------------------------------
Tablet eraser buttons
------------------------------------------------------------------------------
Tablet tools come in a variety of forms but the most common one is a
pen-like tool. Some of these pen-like tools have a virtual eraser at the
tip of the tool - inverting the tool brings the eraser into proximity.
.. figure:: tablet-eraser-invert.svg
:align: center
An pen-like tool used as pen and as eraser by inverting it
Having an eraser as a separate tool is beneficial in many applications as the
eraser tool can be assigned different functionality (colors, paint tools, etc.)
that is easily available.
However, a large proportion of tablet pens have an "eraser button". By
pressing the button the pen switches to be an eraser tool.
On the data level this is not done via a button event, instead the firmware
will pretend the pen tool going out of proximity and the eraser coming
into proximity immediately after - as if the tool was physically inverted.
.. figure:: tablet-eraser-button.svg
:align: center
An pen-like tool used as pen and as eraser by pressing the eraser button
Microsoft mandates this behavior (see
`Windows Pen States <https://learn.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-pen-states>`_
for details) and thus the overwhelming majority of devices will have
an eraser button that virtually inverts the pen.
Enforcing an eraser button means that users have one button less on the
stylus that they would have otherwise. For some users the eraser button
is in an inconvenient location, others don't want an eraser button at all.
libinput provides an eraser button configuration that allows disabling the
eraser button and turning it into a normal button event. If the eraser button
is disabled, pressing that button will generate a normal tablet tool button
event.
This configuration is only available on pens with an eraser button, not on
with an invert-type eraser.

View file

@ -8,13 +8,12 @@ Tap-to-click behaviour
finger touch down/up sequence maps into a button click. This is most finger touch down/up sequence maps into a button click. This is most
commonly used on touchpads, but may be available on other devices. commonly used on touchpads, but may be available on other devices.
libinput implements tapping for one, two, and three fingers, where supported by libinput implements tapping for one, two, and three fingers, where supported
the hardware, and maps those taps into a left, right, and middle button click, by the hardware, and maps those taps into a left, right, and middle button
respectively. This mapping can be switched to left, middle and right through click, respectively. Not all devices support three fingers, libinput will
configuration. Not all devices support three fingers, libinput will support support tapping up to whatever is supported by the hardware. libinput does
tapping up to whatever is supported by the hardware. libinput does not support not support four-finger taps or any tapping with more than four fingers,
four-finger taps or any tapping with more than four fingers, even though some even though some hardware can distinguish between that many fingers.
hardware can distinguish between that many fingers.
.. _tapping_default: .. _tapping_default:
@ -34,10 +33,6 @@ Tapping is **enabled** by default on devices where tapping is the only
method to trigger button clicks. This includes devices without physical method to trigger button clicks. This includes devices without physical
buttons such as touch-capable graphics tablets. buttons such as touch-capable graphics tablets.
.. note:: Unfortunately due to the current API design, devices that require
tapping effectively prevent us from changing this default. For details see
`this comment <https://gitlab.freedesktop.org/libinput/libinput/-/issues/926#note_2056476>`_.
Tapping can be enabled/disabled on a per-device basis. See Tapping can be enabled/disabled on a per-device basis. See
**libinput_device_config_tap_set_enabled()** for details. **libinput_device_config_tap_set_enabled()** for details.
@ -54,19 +49,12 @@ Tap-and-drag is optional and can be enabled or disabled with
**libinput_device_config_tap_set_drag_enabled()**. Most devices have **libinput_device_config_tap_set_drag_enabled()**. Most devices have
tap-and-drag enabled by default. tap-and-drag enabled by default.
.. note:: Dragging is always done with one finger. The number of fingers on
the initial tap decide the type of button click. For example, to
middle-click drag, tap with three fingers followed by a
single-finger drag.
Also optional is a feature called "drag lock". With drag lock disabled, lifting Also optional is a feature called "drag lock". With drag lock disabled, lifting
the finger will stop any drag process. When enabled, the drag the finger will stop any drag process. When enabled, libinput will ignore a
process continues even after lifting a finger but can be ended finger up event during a drag process, provided the finger is set down again
with an additional tap. If timeout-based drag-locks are enabled within a implementation-specific timeout. Drag lock can be enabled and
the drag process will also automatically end once the finger has disabled with **libinput_device_config_tap_set_drag_lock_enabled()**.
been lifted for an implementation-specific timeout. Drag lock can be Note that drag lock only applies if tap-and-drag is be enabled.
enabled and disabled with **libinput_device_config_tap_set_drag_lock_enabled()**.
Note that drag lock only applies if tap-and-drag is enabled.
.. figure:: tap-n-drag.svg .. figure:: tap-n-drag.svg
:align: center :align: center
@ -84,9 +72,6 @@ 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, release (e) is triggered by a timeout. To release the button immediately,
simply tap again (f). simply tap again (f).
If drag lock is enabled in sticky mode there is no timeout after
releasing a finger and an extra tap is required to release the button.
If two fingers are supported by the hardware, a second finger can be used to If two fingers are supported by the hardware, a second finger can be used to
drag while the first is held in-place. drag while the first is held in-place.

View file

@ -27,7 +27,8 @@ must pass for any merge request. These tests are invoked by calling
``meson test -C builddir`` (or ``ninja test``). The ``libinput-test-suite`` is ``meson test -C builddir`` (or ``ninja test``). The ``libinput-test-suite`` is
part of that test set by default. part of that test set by default.
The upstream CI runs all these tests and is run for every merge request. The upstream CI runs all these tests but not the ``libinput-test-suite``.
This CI is run for every merge request.
.. _test-job-control: .. _test-job-control:
@ -207,7 +208,7 @@ verification of distribution composes.
To configure libinput to install the tests, use the ``-Dinstall-tests=true`` To configure libinput to install the tests, use the ``-Dinstall-tests=true``
meson option:: meson option::
$ meson setup builddir -Dtests=true -Dinstall-tests=true <other options> $ meson builddir -Dtests=true -Dinstall-tests=true <other options>
.. _test-meson-suites: .. _test-meson-suites:

View file

@ -42,5 +42,3 @@ Once the timeout expires at t4, libinput generates an event of
Thus, the caller gets events with timestamps in the order t3, t1, t2, Thus, the caller gets events with timestamps in the order t3, t1, t2,
despite t3 > t2 > t1. despite t3 > t2 > t1.
libinput timestamps use **CLOCK_MONOTONIC**.

View file

@ -11,10 +11,8 @@ available in the **libinput(1)** man page.
The most common tools used are: The most common tools used are:
- ``libinput list-devices``: to list locally available devices as seen by libinput, - ``libinput list-devices``: to list locally available devices,
see :ref:`here <libinput-list-devices>` see :ref:`here <libinput-list-devices>`
- ``libinput list-kernel-devices``: to list locally available devices as seen by the kernel,
see :ref:`here <libinput-list-kernel-devices>`
- ``libinput debug-events``: to monitor and debug events, - ``libinput debug-events``: to monitor and debug events,
see :ref:`here <libinput-debug-events>` see :ref:`here <libinput-debug-events>`
- ``libinput debug-gui``: to visualize events, - ``libinput debug-gui``: to visualize events,
@ -23,8 +21,6 @@ The most common tools used are:
see :ref:`here <libinput-record>` see :ref:`here <libinput-record>`
- ``libinput measure``: measure properties on a kernel device, - ``libinput measure``: measure properties on a kernel device,
see :ref:`here <libinput-measure>` see :ref:`here <libinput-measure>`
- ``libinput analyze``: analyse event recordings from a kernel device,
see :ref:`here <libinput-analyze>`
- ``libinput quirks``: show quirks assigned to a device, see - ``libinput quirks``: show quirks assigned to a device, see
:ref:`here <libinput-quirks>` :ref:`here <libinput-quirks>`
@ -75,55 +71,6 @@ binary state all available options are listed, with the default one prefixed
with an asterisk (``*``). In the example above, the default click method is with an asterisk (``*``). In the example above, the default click method is
button-areas but clickfinger is available. button-areas but clickfinger is available.
.. note:: This tool is intended for human-consumption and may change its output
at any time.
.. _libinput-list-kernel-devices:
------------------------------------------------------------------------------
libinput list-kernel-devices
------------------------------------------------------------------------------
The ``libinput list-kernel-devices`` command shows the devices known by **the
kernel**. This command can help identify issues when a device is not handled by
libinput.
::
$ libinput list-kernel-devices
/dev/input/event0: Sleep Button
/dev/input/event1: Power Button
/dev/input/event2: Power Button
/dev/input/event3: Microsoft Microsoft® 2.4GHz Transceiver v9.0
/dev/input/event4: Microsoft Microsoft® 2.4GHz Transceiver v9.0 Mouse
[...]
In some cases, knowing about the HID devices behind the kernel's event nodes
can be useful. To list HID devices, supply the ``--hid`` commandline flag:
::
$ libinput list-kernel-devices --hid
hid:
- name: 'Logitech Gaming Mouse G303'
id: '046d:c080'
driver: 'hid-generic'
hidraw: ['/dev/hidraw6']
evdev: ['/dev/input/event13']
- name: 'Logitech Gaming Mouse G303'
id: '046d:c080'
driver: 'hid-generic'
hidraw: ['/dev/hidraw7']
evdev: ['/dev/input/event14']
- name: 'Microsoft Microsoft® 2.4GHz Transceiver v9.0'
id: '045e:07a5'
driver: 'hid-generic'
hidraw: ['/dev/hidraw0']
evdev: ['/dev/input/event3']
.. note:: This tool is intended for human-consumption and may change its output .. note:: This tool is intended for human-consumption and may change its output
at any time. at any time.
@ -355,19 +302,6 @@ thing and one thing only and their usage is highly specific to the tool.
Please see the **libinput-measure(1)** man page for information about what Please see the **libinput-measure(1)** man page for information about what
tools are available and the man page for each respective tool. tools are available and the man page for each respective tool.
.. _libinput-analyze:
------------------------------------------------------------------------------
Analyzing device events with libinput analyze
------------------------------------------------------------------------------
The ``libinput analyze`` tool is a multiplexer for various sub-tools that
can analyze input events previously recorded from a device.
Please see the **libinput-analyze(1)** man page for information about what
tools are available and the man page for each respective too.
.. _libinput-quirks: .. _libinput-quirks:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -377,7 +311,7 @@ Listing quirks assigned to a device
The ``libinput quirks`` tool can show quirks applied for any given device. :: The ``libinput quirks`` tool can show quirks applied for any given device. ::
$ libinput quirks list /dev/input/event0 $ libinput quirks list /dev/input/event0
AttrLidSwitchReliability=unreliable AttrLidSwitchReliability=reliable
If the tool's output is empty, no quirk is applied. See :ref:`device-quirks` If the tool's output is empty, no quirk is applied. See :ref:`device-quirks`
for more information. for more information.

View file

@ -14,13 +14,10 @@ position.
When libinput detects a cursor jump it prints a bug warning to the log with When libinput detects a cursor jump it prints a bug warning to the log with
the text **"Touch jump detected and discarded."** and a link to this page. the text **"Touch jump detected and discarded."** and a link to this page.
.. note:: This warning is ratelimited and will stop appearing after a few In most cases, this is a bug in the kernel driver and to libinput it appears
times, even if the touchpad jumps continue. that the touch point moves from its previous position. The pointer jump can
usually be seen in the :ref:`libinput record <libinput-record>` output for the device:
In most cases, this is a bug in the firmware (or kernel driver) and to
libinput it appears that the touch point moves from its previous position.
The pointer jump can usually be seen in the :ref:`libinput record
<libinput-record>` output for the device:
:: ::
@ -53,28 +50,9 @@ The pointer jump can usually be seen in the :ref:`libinput record
In this recording, the pointer jumps from its position 3752/2216 to In this recording, the pointer jumps from its position 3752/2216 to
1640/4681 within a single frame. On this particular touchpad, this would 1640/4681 within a single frame. On this particular touchpad, this would
represent a physical move of almost 50mm. libinput detects some of these represent a physical move of almost 50mm. libinput detects some of these
jumps and discards the movement but otherwise continues as usual. jumps and discards the movement but otherwise continues as usual. However,
If your only encounter with these jumps is the warning printed to the log, the bug should be fixed at the kernel level.
libinput functions as intended.
When you encounter the warning in the log, please generate a recording of When you encounter the warning in the log, please generate a recording of
your touchpad with :ref:`libinput record <libinput-record>` and file a bug. your touchpad with :ref:`libinput record <libinput-record>` and file a bug.
See :ref:`reporting_bugs` for more details. See :ref:`reporting_bugs` for more details.
Note that it most cases, libinput cannot actually fix the issue. Filing a
bug is useful to figure out if there are other factors at play or whether
there are heuristics we can employ to reduce the impact.
------------------------------------------------------------------------------
AlpsPS/2 ALPS DualPoint TouchPad jumping to 4095/0
------------------------------------------------------------------------------
A special case of pointer jumps happens on ``AlpsPS/2 ALPS DualPoint TouchPad``
devices found in the Lenovo ThinkPad E465 and E550 and likely others with
the same touchpad hardware. On those devices, the touchpad occasionally
sends an event for the second finger to move to position 4095/0 before
moving back to the original position. libinput detects this movement and
removes it but depending on the interaction this may cause a smaller jump
later when the coordinates reset to the new position of the finger.
Some more information is available in `Gitlab Issue #492 <https://gitlab.freedesktop.org/libinput/libinput/-/issues/492>`__.

View file

@ -38,53 +38,30 @@ statistics, including whether a touch is/was considered logically down.
Example output of the tool is below: :: Example output of the tool is below: ::
$ sudo libinput measure touchpad-pressure $ sudo libinput measure touchpad-pressure
Using Synaptics TM2668-002: /dev/input/event21 Ready for recording data.
Pressure range used: 8:10
This is an interactive tool Palm pressure range used: 65535
Place a single finger on the touchpad to measure pressure values.
Place a single finger on the touchpad to measure pressure values. Ctrl+C to exit
Check that: &nbsp;
- touches subjectively perceived as down are tagged as down Sequence 1190 pressure: min: 39 max: 48 avg: 43 median: 44 tags: down
- touches with a thumb are tagged as thumb Sequence 1191 pressure: min: 49 max: 65 avg: 62 median: 64 tags: down
- touches with a palm are tagged as palm Sequence 1192 pressure: min: 40 max: 78 avg: 64 median: 66 tags: down
Sequence 1193 pressure: min: 36 max: 83 avg: 70 median: 73 tags: down
If the touch states do not match the interaction, re-run Sequence 1194 pressure: min: 43 max: 76 avg: 72 median: 74 tags: down
with --touch-thresholds=down:up using observed pressure values. Touchpad pressure: 47 min: 47 max: 86 tags: down
See --help for more options.
Interactive keys:
q/a - decrease/increase down threshold
w/s - decrease/increase up threshold
e/d - decrease/increase palm threshold
r/f - decrease/increase thumb threshold
Press Ctrl+C to exit
┌───────────────────────────────────────────────────────────────────────────────┐
│ Touch │ down │ up │ palm │ thumb │ min │ max │ p │ avg │ median │
├───────────────────────────────────────────────────────────────────────────────┤
│ 178 │ x │ x │ │ │ 75 │ 75 │ 0 │ 75 │ 75 │
│ 179 │ x │ x │ │ │ 35 │ 88 │ 0 │ 77 │ 81 │
│ 180 │ x │ x │ │ x │ 65 │ 113 │ 0 │ 98 │ 98 │
│ 181 │ x │ x │ │ x │ 50 │ 101 │ 0 │ 86 │ 90 │
│ 182 │ x │ x │ │ │ 40 │ 80 │ 0 │ 66 │ 70 │
│ 183 │ x │ │ │ │ 43 │ 78 │ 78 │ │
│ Thresh │ 70 │ 60 │ 130 │ 100 │
...
The example output shows five completed touch sequences and one ongoing one. The example output shows five completed touch sequences and one ongoing one.
For each, the respective minimum and maximum pressure values are printed as For each, the respective minimum and maximum pressure values are printed as
well as some statistics. The ``down`` column show that each sequence was well as some statistics. The ``tags`` show that sequence was considered
considered logically down at some point (see the threholds in the last line), logically down at some point. This is an interactive tool and its output may
two of the sequences were considered thumbs. This is an interactive tool and change frequently. Refer to the <i>libinput-measure-touchpad-pressure(1)</i> man
its output may change frequently. Refer to the page for more details.
**libinput-measure-touchpad-pressure(1)** man page for more details.
By default, this tool uses the :ref:`device-quirks` for the pressure range. To By default, this tool uses the :ref:`device-quirks` for the pressure range. To
narrow down on the best values for your device, adjust the thresholds using narrow down on the best values for your device, specify the 'logically down'
the keys q/a, w/s, e/d and r/f or specify the 'logically down'
and 'logically up' pressure thresholds with the ``--touch-thresholds`` and 'logically up' pressure thresholds with the ``--touch-thresholds``
argument: :: argument: ::
@ -107,10 +84,8 @@ Once the thresholds are decided on (e.g. 10 and 8), they can be enabled with
[Touchpad pressure override] [Touchpad pressure override]
MatchUdevType=touchpad MatchUdevType=touchpad
MatchName=*SynPS/2 Synaptics TouchPad MatchName=*SynPS/2 Synaptics TouchPad
MatchDMIModalias=dmi:*:svnLENOVO:*:pvrThinkPadX230:* MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadX230*
AttrPressureRange=10:8 AttrPressureRange=10:8
AttrPalmPressureThreshold=150
AttrThumbPressureThreshold=100
The file name **must** be ``/etc/libinput/local-overrides.quirks``. The The file name **must** be ``/etc/libinput/local-overrides.quirks``. The
The first line is the section name and can be free-form. The ``Match`` The first line is the section name and can be free-form. The ``Match``
@ -124,7 +99,7 @@ and product name (pn).
Once in place, run the following command to verify the quirk is valid and Once in place, run the following command to verify the quirk is valid and
works for your device: :: works for your device: ::
$ sudo libinput quirks list /dev/input/event10 $ sudo libinput list-quirks /dev/input/event10
AttrPressureRange=10:8 AttrPressureRange=10:8
Replace the event node with the one from your device. If the Replace the event node with the one from your device. If the
@ -182,7 +157,7 @@ The example output shows five completed touch sequences. For each, the
respective minimum and maximum pressure values are printed as well as some respective minimum and maximum pressure values are printed as well as some
statistics. The ``down`` and ``palm`` tags show that sequence was considered statistics. The ``down`` and ``palm`` tags show that sequence was considered
logically down or a palm at some point. This is an interactive tool and its logically down or a palm at some point. This is an interactive tool and its
output may change frequently. Refer to the **libinput-measure-touch-size(1)** man output may change frequently. Refer to the <i>libinput-measure-touch-size(1)</i> man
page for more details. page for more details.
By default, this tool uses the :ref:`device-quirks` for the touch size range. To By default, this tool uses the :ref:`device-quirks` for the touch size range. To
@ -206,7 +181,7 @@ Once the thresholds are decided on (e.g. 10 and 8), they can be enabled with
[Touchpad touch size override] [Touchpad touch size override]
MatchUdevType=touchpad MatchUdevType=touchpad
MatchName=*SynPS/2 Synaptics TouchPad MatchName=*SynPS/2 Synaptics TouchPad
MatchDMIModalias=dmi:*:svnLENOVO:*:pvrThinkPadX230:* MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadX230*
AttrTouchSizeRange=10:8 AttrTouchSizeRange=10:8
The first line is the match line and should be adjusted for the device name The first line is the match line and should be adjusted for the device name
@ -218,7 +193,7 @@ and product name (pn).
Once in place, run the following command to verify the quirk is valid and Once in place, run the following command to verify the quirk is valid and
works for your device: :: works for your device: ::
$ sudo libinput quirks list /dev/input/event10 $ sudo libinput list-quirks /dev/input/event10
AttrTouchSizeRange=10:8 AttrTouchSizeRange=10:8
Replace the event node with the one from your device. If the Replace the event node with the one from your device. If the
@ -232,3 +207,4 @@ the need for a restart.
Once the touch size ranges are deemed correct, :ref:`reporting_bugs` "report a Once the touch size ranges are deemed correct, :ref:`reporting_bugs` "report a
bug" to get the thresholds into the repository. bug" to get the thresholds into the repository.

View file

@ -56,3 +56,4 @@ these axes are supposed to be mapped, few devices forward reliable
information. libinput uses these values together with a device-specific information. libinput uses these values together with a device-specific
:ref:`device-quirks` entry. In other words, touch size detection does not work :ref:`device-quirks` entry. In other words, touch size detection does not work
unless a device quirk is present for the device. unless a device quirk is present for the device.

View file

@ -17,7 +17,7 @@ other properties.
Number of buttons Number of buttons
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
.. _touchpads_buttons_phys: .. _touchapds_buttons_phys:
.............................................................................. ..............................................................................
Physically separate buttons Physically separate buttons
@ -57,7 +57,7 @@ property.
.. _touchpads_buttons_forcepads: .. _touchpads_buttons_forcepads:
.............................................................................. ..............................................................................
Forcepads/Pressurepads Forcepads
.............................................................................. ..............................................................................
Forcepads are Clickpads without a physical button underneath the hardware. Forcepads are Clickpads without a physical button underneath the hardware.
@ -65,7 +65,6 @@ They provide pressure and may have a vibration element that is
software-controlled. This element can simulate the feel of a physical software-controlled. This element can simulate the feel of a physical
click or be co-opted for other tasks. click or be co-opted for other tasks.
Forcepads are also called pressurepads or haptic touchpads.
.. _touchpads_touch: .. _touchpads_touch:
@ -80,7 +79,7 @@ device can **track**, i.e. provide reliable positional information for.
In the kernel each finger is tracked in a so-called "slot", the number of 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. slots thus equals the number of simultaneous touches a device can track.
.. _touchpads_touch_st: .. _touchapds_touch_st:
.............................................................................. ..............................................................................
Single-touch touchpads Single-touch touchpads

View file

@ -20,7 +20,7 @@ User-specific preferences can be adjusted with the
The magic trackpoint multiplier The magic trackpoint multiplier
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
To accommodate for the wildly different input data on trackpoint, libinput To accomodate for the wildly different input data on trackpoint, libinput
uses a multiplier that is applied to input deltas. Trackpoints that send uses a multiplier that is applied to input deltas. Trackpoints that send
comparatively high deltas can be "slowed down", trackpoints that send low comparatively high deltas can be "slowed down", trackpoints that send low
deltas can be "sped up" to match the expected range. The actual acceleration deltas can be "sped up" to match the expected range. The actual acceleration
@ -78,7 +78,7 @@ installed.
$ cd path/to/libinput.git $ cd path/to/libinput.git
# Use an approximate multiplier in the quirks file # Use an approximate multiplier in the quirks file
$ cat > quirks/99-trackpoint-override.quirks <<EOF $ cat > quirks/99-trackpont-override.quirks <<EOF
[Trackpoint Override] [Trackpoint Override]
MatchUdevType=pointingstick MatchUdevType=pointingstick
AttrTrackpointMultiplier=1.0 AttrTrackpointMultiplier=1.0
@ -131,7 +131,7 @@ variation of the following is sufficient:
[Trackpoint Override] [Trackpoint Override]
MatchUdevType=pointingstick MatchUdevType=pointingstick
MatchName=*TPPS/2 IBM TrackPoint* MatchName=*TPPS/2 IBM TrackPoint*
MatchDMIModalias=dmi:*:svnLENOVO:*:pvrThinkPadT440p:* MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadT440p*
AttrTrackpointMultiplier=1.0 AttrTrackpointMultiplier=1.0
@ -152,3 +152,4 @@ has been removed. See :ref:`trackpoint_multiplier` for versions 1.12.x and later
If using libinput version 1.11.x or earlier, please see If using libinput version 1.11.x or earlier, please see
`the 1.11.0 documentation <https://wayland.freedesktop.org/libinput/doc/1.11.0/trackpoints.html#trackpoint_range_measure>`_ `the 1.11.0 documentation <https://wayland.freedesktop.org/libinput/doc/1.11.0/trackpoints.html#trackpoint_range_measure>`_

View file

@ -5,7 +5,7 @@ Trackpoints and Pointing Sticks
============================================================================== ==============================================================================
This page provides an overview of trackpoint handling in libinput, also This page provides an overview of trackpoint handling in libinput, also
referred to as Pointing Stick or Trackstick. The device itself is usually a refered to as Pointing Stick or Trackstick. The device itself is usually a
round plastic stick between the G, H and B keys with a set of buttons below round plastic stick between the G, H and B keys with a set of buttons below
the space bar. the space bar.
@ -50,7 +50,7 @@ decreases, the delta decrease first, then the reporting rate until the
trackpoint is in a neutral state and no events are reported. Trackpoint data trackpoint is in a neutral state and no events are reported. Trackpoint data
is hard to generalize, see is hard to generalize, see
`Observations on trackpoint input data `Observations on trackpoint input data
<https://who-t.blogspot.com/2018/06/observations-on-trackpoint-input-data.html>`_ <a href="https://who-t.blogspot.com/2018/06/observations-on-trackpoint-input-data.html">`_
for more details. for more details.
.. figure:: trackpoint-delta-illustration.svg .. figure:: trackpoint-delta-illustration.svg
@ -65,3 +65,4 @@ sufficient pressure to even get close to the maximum ranges.
libinput provides a :ref:`Magic Trackpoint Multiplier libinput provides a :ref:`Magic Trackpoint Multiplier
<trackpoint_multiplier>` to normalize the trackpoint input data. <trackpoint_multiplier>` to normalize the trackpoint input data.

View file

@ -14,6 +14,3 @@ Troubleshooting
touchpad-pressure-debugging.rst touchpad-pressure-debugging.rst
trackpoint-configuration.rst trackpoint-configuration.rst
tablet-debugging.rst tablet-debugging.rst
incorrectly-enabled-hires.rst
clickpad-with-right-button.rst
ignoring-devices.rst

View file

@ -131,7 +131,7 @@ Handled device types
- Mice - Mice
- Keyboards - Keyboards
- Virtual absolute pointing devices such as those used by QEMU or VirtualBox - Virtual absolute pointing devices such as those used by QEMU or VirtualBox
- Switches (Lid Switch, Tablet Mode switch, and Keypad Slide switch) - Switches (Lid Switch and Tablet Mode switch)
- Graphics tablets - Graphics tablets
- :ref:`Trackpoints` - :ref:`Trackpoints`

View file

@ -1,183 +0,0 @@
.. _wheel_scrolling:
==============================================================================
Wheel scrolling
==============================================================================
libinput provides two events to handle wheel scrolling:
- ``LIBINPUT_EVENT_POINTER_AXIS`` events are sent for regular wheel clicks,
usually those representing one detent on the device. These wheel clicks
usually require a rotation of 15 or 20 degrees.
**This event is deprecated as of libinput 1.19.**
- ``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL`` events are sent for regular and/or
high resolution wheel movements. High-resolution events are often 4 or 8
times more frequent than wheel clicks and require the device to be switched
into high-resolution mode (Linux kernel 5.0 and later). Where
high-resolution wheels are not provided by the kernel, libinput emulates
these events for regular wheel clicks.
**This event is available since libinput 1.19.**
The events are separate for historical reasons. Both events are
generated for the same device but are independent event streams. Callers
must not assume any relation between the two, i.e. there is no guarantee
that an axis event is sent before or after any specific high-resolution
event and vice versa. Callers should not handle both events.
.. warning:: do not handle both ``LIBINPUT_EVENT_POINTER_AXIS`` and
``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL``. Always use the latter where
possible, otherwise only use the former.
Both events have their own set of APIs to access the data within:
- ``LIBINPUT_EVENT_POINTER_AXIS``: Deprecated as of libinput 1.19, where
possible it is recommended to handle **only**
``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL``.
* ``libinput_event_pointer_get_axis_value()`` returns the angle of movement
in degrees.
* ``libinput_event_pointer_get_axis_source()`` returns the source of the
event: wheel, finger or continuous.
* ``libinput_event_pointer_get_axis_value_discrete()`` returns the number of
logical wheel clicks.
- ``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL`` available since libinput 1.19.
* ``libinput_event_pointer_get_scroll_value_v120()`` returns a value
normalized into the 0..120 range, see below. Any multiple of 120 should
be treated as one full wheel click.
.. note:: Where possible, the ``libinput_event_pointer_get_axis_value()``,
``libinput_event_pointer_get_axis_source()`` and
``libinput_event_pointer_get_axis_value_discrete()`` API should be
avoided.
------------------------------------------------------------------------------
The v120 Wheel API
------------------------------------------------------------------------------
The ``v120`` value matches the Windows API for wheel scrolling. Wheel
movements are normalized into multiples (or fractions) of 120 with each
multiple of 120 representing one detent of movement. The ``v120`` API is the
recommended API for callers that do not care about the exact physical
motion and is the simplest API to handle high-resolution scrolling.
Most wheels provide 24 detents per 360 degree rotation (click angle of 15),
others provide 18 detents per 360 degree rotation (click angle 20). Mice
falling outside these two are rare but do exist. Below is a table showing
the various values for a single event, depending on the click angle of the
wheel:
+-------------+------------+---------------+------+
| Click angle | Axis value | Discrete value| v120 |
+=============+============+===============+======+
| 15 | 15 | 1 | 120 |
+-------------+------------+---------------+------+
| 20 | 20 | 1 | 120 |
+-------------+------------+---------------+------+
Fast scrolling may trigger cover than one detent per event and thus each
event may contain multiples of the value, discrete or v120 value:
+-------------+------------+---------------+------+
| Click angle | Axis value | Discrete value| v120 |
+=============+============+===============+======+
| 15 | 30 | 2 | 240 |
+-------------+------------+---------------+------+
| 20 | 60 | 3 | 360 |
+-------------+------------+---------------+------+
Scrolling on high-resolution wheels will produce fractions of 120, depending
on the resolution of the wheel. The example below shows a mouse with click
angle 15 and a resolution of 3 events per wheel click and a mouse with click
angle 20 and a resolution of 2 events per wheel click.
+-------------+------------+---------------+------+
| Click angle | Axis value | Discrete value| v120 |
+=============+============+===============+======+
| 15 | 5 | 0 | 40 |
+-------------+------------+---------------+------+
| 20 | 10 | 0 | 60 |
+-------------+------------+---------------+------+
------------------------------------------------------------------------------
Event sequences for high-resolution wheel mice
------------------------------------------------------------------------------
High-resolution scroll wheels provide multiple events for each detent is
hit. For those mice, an event sequence covering two detents may look like
this:
+--------------+---------+------------+---------------+------+
| Event number | Type | Axis value | Discrete value| v120 |
+==============+=========+============+===============+======+
| 1 | WHEEL | 5 | n/a | 40 |
+--------------+---------+------------+---------------+------+
| 2 | WHEEL | 5 | n/a | 40 |
+--------------+---------+------------+---------------+------+
| 3 | WHEEL | 5 | n/a | 40 |
+--------------+---------+------------+---------------+------+
| 4 | AXIS | 15 | 1 | 120 |
+--------------+---------+------------+---------------+------+
| 5 | WHEEL | 5 | n/a | 40 |
+--------------+---------+------------+---------------+------+
| 6 | WHEEL | 5 | n/a | 40 |
+--------------+---------+------------+---------------+------+
| 7 | AXIS | 15 | 1 | 120 |
+--------------+---------+------------+---------------+------+
The above assumes a click angle of 15 for the physical detents. Note how the
second set of high-resolution events do **not** add up to a multiple of
120 before the low-resolution event. A caller must not assume any relation
between ``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL`` and
``LIBINPUT_EVENT_POINTER_AXIS``.
Fast-scrolling on a high-resolution mouse may trigger multiple fractions per
hardware scanout cycle and result in an event sequence like this:
+---------------+---------+------------+---------------+------+
| Event number | Type | Axis value | Discrete value| v120 |
+===============+=========+============+===============+======+
| 1 | WHEEL | 5 | n/a | 40 |
+---------------+---------+------------+---------------+------+
| 2 | WHEEL | 10 | n/a | 80 |
+---------------+---------+------------+---------------+------+
| 3 | AXIS | 15 | 1 | 120 |
+---------------+---------+------------+---------------+------+
| 4 | WHEEL | 10 | n/a | 80 |
+---------------+---------+------------+---------------+------+
| 5 | WHEEL | 10 | n/a | 80 |
+---------------+---------+------------+---------------+------+
| 6 | AXIS | 15 | 1 | 120 |
+---------------+---------+------------+---------------+------+
| 7 | WHEEL | 5 | n/a | 40 |
+---------------+---------+------------+---------------+------+
Note how the first low-resolution event is sent at an accumulated 15
degrees, the second at an accumulated 20 degrees. The libinput API does not
specify the smallest fraction a wheel supports.
------------------------------------------------------------------------------
Event sequences for regular wheel mice
------------------------------------------------------------------------------
``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL`` for low-resolution mice are virtually
identical to ``LIBINPUT_EVENT_POINTER_AXIS`` events. Note that the discrete
value is always 0 for ``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL``.
+--------------+---------+------------+---------------+------+
| Event number | Type | Axis value | Discrete value| v120 |
+==============+=========+============+===============+======+
| 1 | AXIS | 15 | 1 | 120 |
+--------------+---------+------------+---------------+------+
| 2 | WHEEL | 15 | n/a | 120 |
+--------------+---------+------------+---------------+------+
| 3 | WHEEL | 15 | n/a | 120 |
+--------------+---------+------------+---------------+------+
| 4 | AXIS | 15 | 1 | 120 |
+--------------+---------+------------+---------------+------+
Note that the order of ``LIBINPUT_EVENT_POINTER_AXIS`` vs
``LIBINPUT_EVENT_POINTER_SCROLL_WHEEL`` events is not guaranteed, as shown in
the example above.

View file

@ -1,4 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/* /*
* Input event codes * Input event codes
* *
@ -27,7 +27,6 @@
#define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */ #define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */
#define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */ #define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */
#define INPUT_PROP_ACCELEROMETER 0x06 /* has accelerometer */ #define INPUT_PROP_ACCELEROMETER 0x06 /* has accelerometer */
#define INPUT_PROP_PRESSUREPAD 0x07 /* pressure triggers clicks */
#define INPUT_PROP_MAX 0x1f #define INPUT_PROP_MAX 0x1f
#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1) #define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
@ -279,8 +278,7 @@
#define KEY_PAUSECD 201 #define KEY_PAUSECD 201
#define KEY_PROG3 202 #define KEY_PROG3 202
#define KEY_PROG4 203 #define KEY_PROG4 203
#define KEY_ALL_APPLICATIONS 204 /* AC Desktop Show All Applications */ #define KEY_DASHBOARD 204 /* AL Dashboard */
#define KEY_DASHBOARD KEY_ALL_APPLICATIONS
#define KEY_SUSPEND 205 #define KEY_SUSPEND 205
#define KEY_CLOSE 206 /* AC Close */ #define KEY_CLOSE 206 /* AC Close */
#define KEY_PLAY 207 #define KEY_PLAY 207
@ -441,12 +439,10 @@
#define KEY_TITLE 0x171 #define KEY_TITLE 0x171
#define KEY_SUBTITLE 0x172 #define KEY_SUBTITLE 0x172
#define KEY_ANGLE 0x173 #define KEY_ANGLE 0x173
#define KEY_FULL_SCREEN 0x174 /* AC View Toggle */ #define KEY_ZOOM 0x174
#define KEY_ZOOM KEY_FULL_SCREEN
#define KEY_MODE 0x175 #define KEY_MODE 0x175
#define KEY_KEYBOARD 0x176 #define KEY_KEYBOARD 0x176
#define KEY_ASPECT_RATIO 0x177 /* HUTRR37: Aspect */ #define KEY_SCREEN 0x177
#define KEY_SCREEN KEY_ASPECT_RATIO
#define KEY_PC 0x178 /* Media Select Computer */ #define KEY_PC 0x178 /* Media Select Computer */
#define KEY_TV 0x179 /* Media Select TV */ #define KEY_TV 0x179 /* Media Select TV */
#define KEY_TV2 0x17a /* Media Select Cable */ #define KEY_TV2 0x17a /* Media Select Cable */
@ -517,10 +513,6 @@
#define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */ #define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */
#define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */ #define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */
#define KEY_IMAGES 0x1ba /* AL Image Browser */ #define KEY_IMAGES 0x1ba /* AL Image Browser */
#define KEY_NOTIFICATION_CENTER 0x1bc /* Show/hide the notification center */
#define KEY_PICKUP_PHONE 0x1bd /* Answer incoming call */
#define KEY_HANGUP_PHONE 0x1be /* Decline incoming call */
#define KEY_LINK_PHONE 0x1bf /* AL Phone Syncing */
#define KEY_DEL_EOL 0x1c0 #define KEY_DEL_EOL 0x1c0
#define KEY_DEL_EOS 0x1c1 #define KEY_DEL_EOS 0x1c1
@ -548,7 +540,6 @@
#define KEY_FN_F 0x1e2 #define KEY_FN_F 0x1e2
#define KEY_FN_S 0x1e3 #define KEY_FN_S 0x1e3
#define KEY_FN_B 0x1e4 #define KEY_FN_B 0x1e4
#define KEY_FN_RIGHT_SHIFT 0x1e5
#define KEY_BRL_DOT1 0x1f1 #define KEY_BRL_DOT1 0x1f1
#define KEY_BRL_DOT2 0x1f2 #define KEY_BRL_DOT2 0x1f2
@ -602,14 +593,8 @@
#define BTN_DPAD_LEFT 0x222 #define BTN_DPAD_LEFT 0x222
#define BTN_DPAD_RIGHT 0x223 #define BTN_DPAD_RIGHT 0x223
#define BTN_GRIPL 0x224
#define BTN_GRIPR 0x225
#define BTN_GRIPL2 0x226
#define BTN_GRIPR2 0x227
#define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */ #define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */
#define KEY_ROTATE_LOCK_TOGGLE 0x231 /* Display rotation lock */ #define KEY_ROTATE_LOCK_TOGGLE 0x231 /* Display rotation lock */
#define KEY_REFRESH_RATE_TOGGLE 0x232 /* Display refresh rate toggle */
#define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */ #define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */
#define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */ #define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */
@ -619,30 +604,10 @@
#define KEY_SCREENSAVER 0x245 /* AL Screen Saver */ #define KEY_SCREENSAVER 0x245 /* AL Screen Saver */
#define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */ #define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */
#define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */ #define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */
#define KEY_KBD_LAYOUT_NEXT 0x248 /* AC Next Keyboard Layout Select */
#define KEY_EMOJI_PICKER 0x249 /* Show/hide emoji picker (HUTRR101) */
#define KEY_DICTATE 0x24a /* Start or Stop Voice Dictation Session (HUTRR99) */
#define KEY_CAMERA_ACCESS_ENABLE 0x24b /* Enables programmatic access to camera devices. (HUTRR72) */
#define KEY_CAMERA_ACCESS_DISABLE 0x24c /* Disables programmatic access to camera devices. (HUTRR72) */
#define KEY_CAMERA_ACCESS_TOGGLE 0x24d /* Toggles the current state of the camera access control. (HUTRR72) */
#define KEY_ACCESSIBILITY 0x24e /* Toggles the system bound accessibility UI/command (HUTRR116) */
#define KEY_DO_NOT_DISTURB 0x24f /* Toggles the system-wide "Do Not Disturb" control (HUTRR94)*/
#define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */ #define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */
#define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */ #define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */
/*
* Keycodes for hotkeys toggling the electronic privacy screen found on some
* laptops on/off. Note when the embedded-controller turns on/off the eprivacy
* screen itself then the state should be reported through drm connecter props:
* https://www.kernel.org/doc/html/latest/gpu/drm-kms.html#standard-connector-properties
* Except when implementing the drm connecter properties API is not possible
* because e.g. the firmware does not allow querying the presence and/or status
* of the eprivacy screen at boot.
*/
#define KEY_EPRIVACY_SCREEN_ON 0x252
#define KEY_EPRIVACY_SCREEN_OFF 0x253
#define KEY_KBDINPUTASSIST_PREV 0x260 #define KEY_KBDINPUTASSIST_PREV 0x260
#define KEY_KBDINPUTASSIST_NEXT 0x261 #define KEY_KBDINPUTASSIST_NEXT 0x261
#define KEY_KBDINPUTASSIST_PREVGROUP 0x262 #define KEY_KBDINPUTASSIST_PREVGROUP 0x262
@ -681,110 +646,6 @@
*/ */
#define KEY_DATA 0x277 #define KEY_DATA 0x277
#define KEY_ONSCREEN_KEYBOARD 0x278 #define KEY_ONSCREEN_KEYBOARD 0x278
/* Electronic privacy screen control */
#define KEY_PRIVACY_SCREEN_TOGGLE 0x279
/* Select an area of screen to be copied */
#define KEY_SELECTIVE_SCREENSHOT 0x27a
/* Move the focus to the next or previous user controllable element within a UI container */
#define KEY_NEXT_ELEMENT 0x27b
#define KEY_PREVIOUS_ELEMENT 0x27c
/* Toggle Autopilot engagement */
#define KEY_AUTOPILOT_ENGAGE_TOGGLE 0x27d
/* Shortcut Keys */
#define KEY_MARK_WAYPOINT 0x27e
#define KEY_SOS 0x27f
#define KEY_NAV_CHART 0x280
#define KEY_FISHING_CHART 0x281
#define KEY_SINGLE_RANGE_RADAR 0x282
#define KEY_DUAL_RANGE_RADAR 0x283
#define KEY_RADAR_OVERLAY 0x284
#define KEY_TRADITIONAL_SONAR 0x285
#define KEY_CLEARVU_SONAR 0x286
#define KEY_SIDEVU_SONAR 0x287
#define KEY_NAV_INFO 0x288
#define KEY_BRIGHTNESS_MENU 0x289
/*
* Some keyboards have keys which do not have a defined meaning, these keys
* are intended to be programmed / bound to macros by the user. For most
* keyboards with these macro-keys the key-sequence to inject, or action to
* take, is all handled by software on the host side. So from the kernel's
* point of view these are just normal keys.
*
* The KEY_MACRO# codes below are intended for such keys, which may be labeled
* e.g. G1-G18, or S1 - S30. The KEY_MACRO# codes MUST NOT be used for keys
* where the marking on the key does indicate a defined meaning / purpose.
*
* The KEY_MACRO# codes MUST also NOT be used as fallback for when no existing
* KEY_FOO define matches the marking / purpose. In this case a new KEY_FOO
* define MUST be added.
*/
#define KEY_MACRO1 0x290
#define KEY_MACRO2 0x291
#define KEY_MACRO3 0x292
#define KEY_MACRO4 0x293
#define KEY_MACRO5 0x294
#define KEY_MACRO6 0x295
#define KEY_MACRO7 0x296
#define KEY_MACRO8 0x297
#define KEY_MACRO9 0x298
#define KEY_MACRO10 0x299
#define KEY_MACRO11 0x29a
#define KEY_MACRO12 0x29b
#define KEY_MACRO13 0x29c
#define KEY_MACRO14 0x29d
#define KEY_MACRO15 0x29e
#define KEY_MACRO16 0x29f
#define KEY_MACRO17 0x2a0
#define KEY_MACRO18 0x2a1
#define KEY_MACRO19 0x2a2
#define KEY_MACRO20 0x2a3
#define KEY_MACRO21 0x2a4
#define KEY_MACRO22 0x2a5
#define KEY_MACRO23 0x2a6
#define KEY_MACRO24 0x2a7
#define KEY_MACRO25 0x2a8
#define KEY_MACRO26 0x2a9
#define KEY_MACRO27 0x2aa
#define KEY_MACRO28 0x2ab
#define KEY_MACRO29 0x2ac
#define KEY_MACRO30 0x2ad
/*
* Some keyboards with the macro-keys described above have some extra keys
* for controlling the host-side software responsible for the macro handling:
* -A macro recording start/stop key. Note that not all keyboards which emit
* KEY_MACRO_RECORD_START will also emit KEY_MACRO_RECORD_STOP if
* KEY_MACRO_RECORD_STOP is not advertised, then KEY_MACRO_RECORD_START
* should be interpreted as a recording start/stop toggle;
* -Keys for switching between different macro (pre)sets, either a key for
* cycling through the configured presets or keys to directly select a preset.
*/
#define KEY_MACRO_RECORD_START 0x2b0
#define KEY_MACRO_RECORD_STOP 0x2b1
#define KEY_MACRO_PRESET_CYCLE 0x2b2
#define KEY_MACRO_PRESET1 0x2b3
#define KEY_MACRO_PRESET2 0x2b4
#define KEY_MACRO_PRESET3 0x2b5
/*
* Some keyboards have a buildin LCD panel where the contents are controlled
* by the host. Often these have a number of keys directly below the LCD
* intended for controlling a menu shown on the LCD. These keys often don't
* have any labeling so we just name them KEY_KBD_LCD_MENU#
*/
#define KEY_KBD_LCD_MENU1 0x2b8
#define KEY_KBD_LCD_MENU2 0x2b9
#define KEY_KBD_LCD_MENU3 0x2ba
#define KEY_KBD_LCD_MENU4 0x2bb
#define KEY_KBD_LCD_MENU5 0x2bc
/* Performance Boost key (Alienware)/G-Mode key (Dell) */
#define KEY_PERFORMANCE 0x2bd
#define BTN_TRIGGER_HAPPY 0x2c0 #define BTN_TRIGGER_HAPPY 0x2c0
#define BTN_TRIGGER_HAPPY1 0x2c0 #define BTN_TRIGGER_HAPPY1 0x2c0
@ -890,7 +751,6 @@
#define ABS_TOOL_WIDTH 0x1c #define ABS_TOOL_WIDTH 0x1c
#define ABS_VOLUME 0x20 #define ABS_VOLUME 0x20
#define ABS_PROFILE 0x21
#define ABS_MISC 0x28 #define ABS_MISC 0x28
@ -945,9 +805,7 @@
#define SW_LINEIN_INSERT 0x0d /* set = inserted */ #define SW_LINEIN_INSERT 0x0d /* set = inserted */
#define SW_MUTE_DEVICE 0x0e /* set = device disabled */ #define SW_MUTE_DEVICE 0x0e /* set = device disabled */
#define SW_PEN_INSERTED 0x0f /* set = pen inserted */ #define SW_PEN_INSERTED 0x0f /* set = pen inserted */
#define SW_MACHINE_COVER 0x10 /* set = cover closed */ #define SW_MAX 0x0f
#define SW_USB_INSERT 0x11 /* set = USB audio device connected */
#define SW_MAX 0x11
#define SW_CNT (SW_MAX+1) #define SW_CNT (SW_MAX+1)
/* /*

View file

@ -1,4 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/* /*
* Input event codes * Input event codes
* *
@ -27,7 +27,6 @@
#define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */ #define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */
#define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */ #define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */
#define INPUT_PROP_ACCELEROMETER 0x06 /* has accelerometer */ #define INPUT_PROP_ACCELEROMETER 0x06 /* has accelerometer */
#define INPUT_PROP_PRESSUREPAD 0x07 /* pressure triggers clicks */
#define INPUT_PROP_MAX 0x1f #define INPUT_PROP_MAX 0x1f
#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1) #define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
@ -279,8 +278,7 @@
#define KEY_PAUSECD 201 #define KEY_PAUSECD 201
#define KEY_PROG3 202 #define KEY_PROG3 202
#define KEY_PROG4 203 #define KEY_PROG4 203
#define KEY_ALL_APPLICATIONS 204 /* AC Desktop Show All Applications */ #define KEY_DASHBOARD 204 /* AL Dashboard */
#define KEY_DASHBOARD KEY_ALL_APPLICATIONS
#define KEY_SUSPEND 205 #define KEY_SUSPEND 205
#define KEY_CLOSE 206 /* AC Close */ #define KEY_CLOSE 206 /* AC Close */
#define KEY_PLAY 207 #define KEY_PLAY 207
@ -441,12 +439,10 @@
#define KEY_TITLE 0x171 #define KEY_TITLE 0x171
#define KEY_SUBTITLE 0x172 #define KEY_SUBTITLE 0x172
#define KEY_ANGLE 0x173 #define KEY_ANGLE 0x173
#define KEY_FULL_SCREEN 0x174 /* AC View Toggle */ #define KEY_ZOOM 0x174
#define KEY_ZOOM KEY_FULL_SCREEN
#define KEY_MODE 0x175 #define KEY_MODE 0x175
#define KEY_KEYBOARD 0x176 #define KEY_KEYBOARD 0x176
#define KEY_ASPECT_RATIO 0x177 /* HUTRR37: Aspect */ #define KEY_SCREEN 0x177
#define KEY_SCREEN KEY_ASPECT_RATIO
#define KEY_PC 0x178 /* Media Select Computer */ #define KEY_PC 0x178 /* Media Select Computer */
#define KEY_TV 0x179 /* Media Select TV */ #define KEY_TV 0x179 /* Media Select TV */
#define KEY_TV2 0x17a /* Media Select Cable */ #define KEY_TV2 0x17a /* Media Select Cable */
@ -517,10 +513,6 @@
#define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */ #define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */
#define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */ #define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */
#define KEY_IMAGES 0x1ba /* AL Image Browser */ #define KEY_IMAGES 0x1ba /* AL Image Browser */
#define KEY_NOTIFICATION_CENTER 0x1bc /* Show/hide the notification center */
#define KEY_PICKUP_PHONE 0x1bd /* Answer incoming call */
#define KEY_HANGUP_PHONE 0x1be /* Decline incoming call */
#define KEY_LINK_PHONE 0x1bf /* AL Phone Syncing */
#define KEY_DEL_EOL 0x1c0 #define KEY_DEL_EOL 0x1c0
#define KEY_DEL_EOS 0x1c1 #define KEY_DEL_EOS 0x1c1
@ -548,7 +540,6 @@
#define KEY_FN_F 0x1e2 #define KEY_FN_F 0x1e2
#define KEY_FN_S 0x1e3 #define KEY_FN_S 0x1e3
#define KEY_FN_B 0x1e4 #define KEY_FN_B 0x1e4
#define KEY_FN_RIGHT_SHIFT 0x1e5
#define KEY_BRL_DOT1 0x1f1 #define KEY_BRL_DOT1 0x1f1
#define KEY_BRL_DOT2 0x1f2 #define KEY_BRL_DOT2 0x1f2
@ -602,14 +593,8 @@
#define BTN_DPAD_LEFT 0x222 #define BTN_DPAD_LEFT 0x222
#define BTN_DPAD_RIGHT 0x223 #define BTN_DPAD_RIGHT 0x223
#define BTN_GRIPL 0x224
#define BTN_GRIPR 0x225
#define BTN_GRIPL2 0x226
#define BTN_GRIPR2 0x227
#define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */ #define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */
#define KEY_ROTATE_LOCK_TOGGLE 0x231 /* Display rotation lock */ #define KEY_ROTATE_LOCK_TOGGLE 0x231 /* Display rotation lock */
#define KEY_REFRESH_RATE_TOGGLE 0x232 /* Display refresh rate toggle */
#define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */ #define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */
#define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */ #define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */
@ -619,30 +604,10 @@
#define KEY_SCREENSAVER 0x245 /* AL Screen Saver */ #define KEY_SCREENSAVER 0x245 /* AL Screen Saver */
#define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */ #define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */
#define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */ #define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */
#define KEY_KBD_LAYOUT_NEXT 0x248 /* AC Next Keyboard Layout Select */
#define KEY_EMOJI_PICKER 0x249 /* Show/hide emoji picker (HUTRR101) */
#define KEY_DICTATE 0x24a /* Start or Stop Voice Dictation Session (HUTRR99) */
#define KEY_CAMERA_ACCESS_ENABLE 0x24b /* Enables programmatic access to camera devices. (HUTRR72) */
#define KEY_CAMERA_ACCESS_DISABLE 0x24c /* Disables programmatic access to camera devices. (HUTRR72) */
#define KEY_CAMERA_ACCESS_TOGGLE 0x24d /* Toggles the current state of the camera access control. (HUTRR72) */
#define KEY_ACCESSIBILITY 0x24e /* Toggles the system bound accessibility UI/command (HUTRR116) */
#define KEY_DO_NOT_DISTURB 0x24f /* Toggles the system-wide "Do Not Disturb" control (HUTRR94)*/
#define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */ #define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */
#define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */ #define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */
/*
* Keycodes for hotkeys toggling the electronic privacy screen found on some
* laptops on/off. Note when the embedded-controller turns on/off the eprivacy
* screen itself then the state should be reported through drm connecter props:
* https://www.kernel.org/doc/html/latest/gpu/drm-kms.html#standard-connector-properties
* Except when implementing the drm connecter properties API is not possible
* because e.g. the firmware does not allow querying the presence and/or status
* of the eprivacy screen at boot.
*/
#define KEY_EPRIVACY_SCREEN_ON 0x252
#define KEY_EPRIVACY_SCREEN_OFF 0x253
#define KEY_KBDINPUTASSIST_PREV 0x260 #define KEY_KBDINPUTASSIST_PREV 0x260
#define KEY_KBDINPUTASSIST_NEXT 0x261 #define KEY_KBDINPUTASSIST_NEXT 0x261
#define KEY_KBDINPUTASSIST_PREVGROUP 0x262 #define KEY_KBDINPUTASSIST_PREVGROUP 0x262
@ -681,110 +646,6 @@
*/ */
#define KEY_DATA 0x277 #define KEY_DATA 0x277
#define KEY_ONSCREEN_KEYBOARD 0x278 #define KEY_ONSCREEN_KEYBOARD 0x278
/* Electronic privacy screen control */
#define KEY_PRIVACY_SCREEN_TOGGLE 0x279
/* Select an area of screen to be copied */
#define KEY_SELECTIVE_SCREENSHOT 0x27a
/* Move the focus to the next or previous user controllable element within a UI container */
#define KEY_NEXT_ELEMENT 0x27b
#define KEY_PREVIOUS_ELEMENT 0x27c
/* Toggle Autopilot engagement */
#define KEY_AUTOPILOT_ENGAGE_TOGGLE 0x27d
/* Shortcut Keys */
#define KEY_MARK_WAYPOINT 0x27e
#define KEY_SOS 0x27f
#define KEY_NAV_CHART 0x280
#define KEY_FISHING_CHART 0x281
#define KEY_SINGLE_RANGE_RADAR 0x282
#define KEY_DUAL_RANGE_RADAR 0x283
#define KEY_RADAR_OVERLAY 0x284
#define KEY_TRADITIONAL_SONAR 0x285
#define KEY_CLEARVU_SONAR 0x286
#define KEY_SIDEVU_SONAR 0x287
#define KEY_NAV_INFO 0x288
#define KEY_BRIGHTNESS_MENU 0x289
/*
* Some keyboards have keys which do not have a defined meaning, these keys
* are intended to be programmed / bound to macros by the user. For most
* keyboards with these macro-keys the key-sequence to inject, or action to
* take, is all handled by software on the host side. So from the kernel's
* point of view these are just normal keys.
*
* The KEY_MACRO# codes below are intended for such keys, which may be labeled
* e.g. G1-G18, or S1 - S30. The KEY_MACRO# codes MUST NOT be used for keys
* where the marking on the key does indicate a defined meaning / purpose.
*
* The KEY_MACRO# codes MUST also NOT be used as fallback for when no existing
* KEY_FOO define matches the marking / purpose. In this case a new KEY_FOO
* define MUST be added.
*/
#define KEY_MACRO1 0x290
#define KEY_MACRO2 0x291
#define KEY_MACRO3 0x292
#define KEY_MACRO4 0x293
#define KEY_MACRO5 0x294
#define KEY_MACRO6 0x295
#define KEY_MACRO7 0x296
#define KEY_MACRO8 0x297
#define KEY_MACRO9 0x298
#define KEY_MACRO10 0x299
#define KEY_MACRO11 0x29a
#define KEY_MACRO12 0x29b
#define KEY_MACRO13 0x29c
#define KEY_MACRO14 0x29d
#define KEY_MACRO15 0x29e
#define KEY_MACRO16 0x29f
#define KEY_MACRO17 0x2a0
#define KEY_MACRO18 0x2a1
#define KEY_MACRO19 0x2a2
#define KEY_MACRO20 0x2a3
#define KEY_MACRO21 0x2a4
#define KEY_MACRO22 0x2a5
#define KEY_MACRO23 0x2a6
#define KEY_MACRO24 0x2a7
#define KEY_MACRO25 0x2a8
#define KEY_MACRO26 0x2a9
#define KEY_MACRO27 0x2aa
#define KEY_MACRO28 0x2ab
#define KEY_MACRO29 0x2ac
#define KEY_MACRO30 0x2ad
/*
* Some keyboards with the macro-keys described above have some extra keys
* for controlling the host-side software responsible for the macro handling:
* -A macro recording start/stop key. Note that not all keyboards which emit
* KEY_MACRO_RECORD_START will also emit KEY_MACRO_RECORD_STOP if
* KEY_MACRO_RECORD_STOP is not advertised, then KEY_MACRO_RECORD_START
* should be interpreted as a recording start/stop toggle;
* -Keys for switching between different macro (pre)sets, either a key for
* cycling through the configured presets or keys to directly select a preset.
*/
#define KEY_MACRO_RECORD_START 0x2b0
#define KEY_MACRO_RECORD_STOP 0x2b1
#define KEY_MACRO_PRESET_CYCLE 0x2b2
#define KEY_MACRO_PRESET1 0x2b3
#define KEY_MACRO_PRESET2 0x2b4
#define KEY_MACRO_PRESET3 0x2b5
/*
* Some keyboards have a buildin LCD panel where the contents are controlled
* by the host. Often these have a number of keys directly below the LCD
* intended for controlling a menu shown on the LCD. These keys often don't
* have any labeling so we just name them KEY_KBD_LCD_MENU#
*/
#define KEY_KBD_LCD_MENU1 0x2b8
#define KEY_KBD_LCD_MENU2 0x2b9
#define KEY_KBD_LCD_MENU3 0x2ba
#define KEY_KBD_LCD_MENU4 0x2bb
#define KEY_KBD_LCD_MENU5 0x2bc
/* Performance Boost key (Alienware)/G-Mode key (Dell) */
#define KEY_PERFORMANCE 0x2bd
#define BTN_TRIGGER_HAPPY 0x2c0 #define BTN_TRIGGER_HAPPY 0x2c0
#define BTN_TRIGGER_HAPPY1 0x2c0 #define BTN_TRIGGER_HAPPY1 0x2c0
@ -890,7 +751,6 @@
#define ABS_TOOL_WIDTH 0x1c #define ABS_TOOL_WIDTH 0x1c
#define ABS_VOLUME 0x20 #define ABS_VOLUME 0x20
#define ABS_PROFILE 0x21
#define ABS_MISC 0x28 #define ABS_MISC 0x28
@ -945,9 +805,7 @@
#define SW_LINEIN_INSERT 0x0d /* set = inserted */ #define SW_LINEIN_INSERT 0x0d /* set = inserted */
#define SW_MUTE_DEVICE 0x0e /* set = device disabled */ #define SW_MUTE_DEVICE 0x0e /* set = device disabled */
#define SW_PEN_INSERTED 0x0f /* set = pen inserted */ #define SW_PEN_INSERTED 0x0f /* set = pen inserted */
#define SW_MACHINE_COVER 0x10 /* set = cover closed */ #define SW_MAX 0x0f
#define SW_USB_INSERT 0x11 /* set = USB audio device connected */
#define SW_MAX 0x11
#define SW_CNT (SW_MAX+1) #define SW_CNT (SW_MAX+1)
/* /*

View file

@ -89,7 +89,7 @@
|| (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6)) || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
*/ */
#define __VALGRIND_MAJOR__ 3 #define __VALGRIND_MAJOR__ 3
#define __VALGRIND_MINOR__ 18 #define __VALGRIND_MINOR__ 15
#include <stdarg.h> #include <stdarg.h>
@ -110,8 +110,6 @@
*/ */
#undef PLAT_x86_darwin #undef PLAT_x86_darwin
#undef PLAT_amd64_darwin #undef PLAT_amd64_darwin
#undef PLAT_x86_freebsd
#undef PLAT_amd64_freebsd
#undef PLAT_x86_win32 #undef PLAT_x86_win32
#undef PLAT_amd64_win64 #undef PLAT_amd64_win64
#undef PLAT_x86_linux #undef PLAT_x86_linux
@ -124,7 +122,6 @@
#undef PLAT_s390x_linux #undef PLAT_s390x_linux
#undef PLAT_mips32_linux #undef PLAT_mips32_linux
#undef PLAT_mips64_linux #undef PLAT_mips64_linux
#undef PLAT_nanomips_linux
#undef PLAT_x86_solaris #undef PLAT_x86_solaris
#undef PLAT_amd64_solaris #undef PLAT_amd64_solaris
@ -133,17 +130,12 @@
# define PLAT_x86_darwin 1 # define PLAT_x86_darwin 1
#elif defined(__APPLE__) && defined(__x86_64__) #elif defined(__APPLE__) && defined(__x86_64__)
# define PLAT_amd64_darwin 1 # define PLAT_amd64_darwin 1
#elif defined(__FreeBSD__) && defined(__i386__) #elif (defined(__MINGW32__) && !defined(__MINGW64__)) \
# define PLAT_x86_freebsd 1
#elif defined(__FreeBSD__) && defined(__amd64__)
# define PLAT_amd64_freebsd 1
#elif (defined(__MINGW32__) && defined(__i386__)) \
|| defined(__CYGWIN32__) \ || defined(__CYGWIN32__) \
|| (defined(_WIN32) && defined(_M_IX86)) || (defined(_WIN32) && defined(_M_IX86))
# define PLAT_x86_win32 1 # define PLAT_x86_win32 1
#elif (defined(__MINGW32__) && defined(__x86_64__)) \ #elif defined(__MINGW64__) \
|| (defined(_WIN32) && defined(_M_X64)) || (defined(_WIN64) && defined(_M_X64))
/* __MINGW32__ and _WIN32 are defined in 64 bit mode as well. */
# define PLAT_amd64_win64 1 # define PLAT_amd64_win64 1
#elif defined(__linux__) && defined(__i386__) #elif defined(__linux__) && defined(__i386__)
# define PLAT_x86_linux 1 # define PLAT_x86_linux 1
@ -165,10 +157,8 @@
# define PLAT_s390x_linux 1 # define PLAT_s390x_linux 1
#elif defined(__linux__) && defined(__mips__) && (__mips==64) #elif defined(__linux__) && defined(__mips__) && (__mips==64)
# define PLAT_mips64_linux 1 # define PLAT_mips64_linux 1
#elif defined(__linux__) && defined(__mips__) && (__mips==32) #elif defined(__linux__) && defined(__mips__) && (__mips!=64)
# define PLAT_mips32_linux 1 # define PLAT_mips32_linux 1
#elif defined(__linux__) && defined(__nanomips__)
# define PLAT_nanomips_linux 1
#elif defined(__sun) && defined(__i386__) #elif defined(__sun) && defined(__i386__)
# define PLAT_x86_solaris 1 # define PLAT_x86_solaris 1
#elif defined(__sun) && defined(__x86_64__) #elif defined(__sun) && defined(__x86_64__)
@ -264,7 +254,7 @@
#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \ #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
|| (defined(PLAT_x86_win32) && defined(__GNUC__)) \ || (defined(PLAT_x86_win32) && defined(__GNUC__)) \
|| defined(PLAT_x86_solaris) || defined(PLAT_x86_freebsd) || defined(PLAT_x86_solaris)
typedef typedef
struct { struct {
@ -404,7 +394,6 @@ valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \ #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \
|| defined(PLAT_amd64_solaris) \ || defined(PLAT_amd64_solaris) \
|| defined(PLAT_amd64_freebsd) \
|| (defined(PLAT_amd64_win64) && defined(__GNUC__)) || (defined(PLAT_amd64_win64) && defined(__GNUC__))
typedef typedef
@ -883,8 +872,7 @@ typedef
/* results = r3 */ \ /* results = r3 */ \
"lgr %0, 3\n\t" \ "lgr %0, 3\n\t" \
: "=d" (_zzq_result) \ : "=d" (_zzq_result) \
: "a" (&_zzq_args[0]), \ : "a" (&_zzq_args[0]), "0" (_zzq_default) \
"0" ((unsigned long int)_zzq_default) \
: "cc", "2", "3", "memory" \ : "cc", "2", "3", "memory" \
); \ ); \
_zzq_result; \ _zzq_result; \
@ -1057,75 +1045,6 @@ typedef
#endif /* PLAT_mips64_linux */ #endif /* PLAT_mips64_linux */
#if defined(PLAT_nanomips_linux)
typedef
struct {
unsigned int nraddr; /* where's the code? */
}
OrigFn;
/*
8000 c04d srl zero, zero, 13
8000 c05d srl zero, zero, 29
8000 c043 srl zero, zero, 3
8000 c053 srl zero, zero, 19
*/
#define __SPECIAL_INSTRUCTION_PREAMBLE "srl[32] $zero, $zero, 13 \n\t" \
"srl[32] $zero, $zero, 29 \n\t" \
"srl[32] $zero, $zero, 3 \n\t" \
"srl[32] $zero, $zero, 19 \n\t"
#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
_zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
__extension__ \
({ volatile unsigned int _zzq_args[6]; \
volatile unsigned int _zzq_result; \
_zzq_args[0] = (unsigned int)(_zzq_request); \
_zzq_args[1] = (unsigned int)(_zzq_arg1); \
_zzq_args[2] = (unsigned int)(_zzq_arg2); \
_zzq_args[3] = (unsigned int)(_zzq_arg3); \
_zzq_args[4] = (unsigned int)(_zzq_arg4); \
_zzq_args[5] = (unsigned int)(_zzq_arg5); \
__asm__ volatile("move $a7, %1\n\t" /* default */ \
"move $t0, %2\n\t" /* ptr */ \
__SPECIAL_INSTRUCTION_PREAMBLE \
/* $a7 = client_request( $t0 ) */ \
"or[32] $t0, $t0, $t0\n\t" \
"move %0, $a7\n\t" /* result */ \
: "=r" (_zzq_result) \
: "r" (_zzq_default), "r" (&_zzq_args[0]) \
: "$a7", "$t0", "memory"); \
_zzq_result; \
})
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
{ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
volatile unsigned long int __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
/* $a7 = guest_NRADDR */ \
"or[32] $t1, $t1, $t1\n\t" \
"move %0, $a7" /*result*/ \
: "=r" (__addr) \
: \
: "$a7"); \
_zzq_orig->nraddr = __addr; \
}
#define VALGRIND_CALL_NOREDIR_T9 \
__SPECIAL_INSTRUCTION_PREAMBLE \
/* call-noredir $25 */ \
"or[32] $t2, $t2, $t2\n\t"
#define VALGRIND_VEX_INJECT_IR() \
do { \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
"or[32] $t3, $t3, $t3\n\t" \
); \
} while (0)
#endif
/* Insert assembly code for other platforms here... */ /* Insert assembly code for other platforms here... */
#endif /* NVALGRIND */ #endif /* NVALGRIND */
@ -1226,7 +1145,7 @@ typedef
/* ----------------- x86-{linux,darwin,solaris} ---------------- */ /* ----------------- x86-{linux,darwin,solaris} ---------------- */
#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \ #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
|| defined(PLAT_x86_solaris) || defined(PLAT_x86_freebsd) || defined(PLAT_x86_solaris)
/* These regs are trashed by the hidden call. No need to mention eax /* These regs are trashed by the hidden call. No need to mention eax
as gcc can already see that, plus causes gcc to bomb. */ as gcc can already see that, plus causes gcc to bomb. */
@ -1658,7 +1577,7 @@ typedef
/* ---------------- amd64-{linux,darwin,solaris} --------------- */ /* ---------------- amd64-{linux,darwin,solaris} --------------- */
#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \ #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \
|| defined(PLAT_amd64_solaris) || defined(PLAT_amd64_freebsd) || defined(PLAT_amd64_solaris)
/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
@ -4768,16 +4687,8 @@ typedef
r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
function a proper return address. All others are ABI defined call function a proper return address. All others are ABI defined call
clobbers. */ clobbers. */
#if defined(__VX__) || defined(__S390_VX__) #define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
#define __CALLER_SAVED_REGS "0", "1", "2", "3", "4", "5", "14", \ "f0","f1","f2","f3","f4","f5","f6","f7"
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", \
"v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", \
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", \
"v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
#else
#define __CALLER_SAVED_REGS "0", "1", "2", "3", "4", "5", "14", \
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7"
#endif
/* Nb: Although r11 is modified in the asm snippets below (inside /* Nb: Although r11 is modified in the asm snippets below (inside
VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for
@ -4799,9 +4710,9 @@ typedef
"aghi 15,-160\n\t" \ "aghi 15,-160\n\t" \
"lg 1, 0(1)\n\t" /* target->r1 */ \ "lg 1, 0(1)\n\t" /* target->r1 */ \
VALGRIND_CALL_NOREDIR_R1 \ VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,160\n\t" \ "aghi 15,160\n\t" \
VALGRIND_CFI_EPILOGUE \ VALGRIND_CFI_EPILOGUE \
"lgr %0, 2\n\t" \
: /*out*/ "=d" (_res) \ : /*out*/ "=d" (_res) \
: /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \ : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
@ -4823,9 +4734,9 @@ typedef
"lg 2, 8(1)\n\t" \ "lg 2, 8(1)\n\t" \
"lg 1, 0(1)\n\t" \ "lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \ VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,160\n\t" \ "aghi 15,160\n\t" \
VALGRIND_CFI_EPILOGUE \ VALGRIND_CFI_EPILOGUE \
"lgr %0, 2\n\t" \
: /*out*/ "=d" (_res) \ : /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
@ -4848,9 +4759,9 @@ typedef
"lg 3,16(1)\n\t" \ "lg 3,16(1)\n\t" \
"lg 1, 0(1)\n\t" \ "lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \ VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,160\n\t" \ "aghi 15,160\n\t" \
VALGRIND_CFI_EPILOGUE \ VALGRIND_CFI_EPILOGUE \
"lgr %0, 2\n\t" \
: /*out*/ "=d" (_res) \ : /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
@ -4875,9 +4786,9 @@ typedef
"lg 4,24(1)\n\t" \ "lg 4,24(1)\n\t" \
"lg 1, 0(1)\n\t" \ "lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \ VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,160\n\t" \ "aghi 15,160\n\t" \
VALGRIND_CFI_EPILOGUE \ VALGRIND_CFI_EPILOGUE \
"lgr %0, 2\n\t" \
: /*out*/ "=d" (_res) \ : /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
@ -4904,9 +4815,9 @@ typedef
"lg 5,32(1)\n\t" \ "lg 5,32(1)\n\t" \
"lg 1, 0(1)\n\t" \ "lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \ VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,160\n\t" \ "aghi 15,160\n\t" \
VALGRIND_CFI_EPILOGUE \ VALGRIND_CFI_EPILOGUE \
"lgr %0, 2\n\t" \
: /*out*/ "=d" (_res) \ : /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
@ -4935,9 +4846,9 @@ typedef
"lg 6,40(1)\n\t" \ "lg 6,40(1)\n\t" \
"lg 1, 0(1)\n\t" \ "lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \ VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,160\n\t" \ "aghi 15,160\n\t" \
VALGRIND_CFI_EPILOGUE \ VALGRIND_CFI_EPILOGUE \
"lgr %0, 2\n\t" \
: /*out*/ "=d" (_res) \ : /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
@ -4969,9 +4880,9 @@ typedef
"mvc 160(8,15), 48(1)\n\t" \ "mvc 160(8,15), 48(1)\n\t" \
"lg 1, 0(1)\n\t" \ "lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \ VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,168\n\t" \ "aghi 15,168\n\t" \
VALGRIND_CFI_EPILOGUE \ VALGRIND_CFI_EPILOGUE \
"lgr %0, 2\n\t" \
: /*out*/ "=d" (_res) \ : /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
@ -5005,9 +4916,9 @@ typedef
"mvc 168(8,15), 56(1)\n\t" \ "mvc 168(8,15), 56(1)\n\t" \
"lg 1, 0(1)\n\t" \ "lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \ VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,176\n\t" \ "aghi 15,176\n\t" \
VALGRIND_CFI_EPILOGUE \ VALGRIND_CFI_EPILOGUE \
"lgr %0, 2\n\t" \
: /*out*/ "=d" (_res) \ : /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
@ -5043,9 +4954,9 @@ typedef
"mvc 176(8,15), 64(1)\n\t" \ "mvc 176(8,15), 64(1)\n\t" \
"lg 1, 0(1)\n\t" \ "lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \ VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,184\n\t" \ "aghi 15,184\n\t" \
VALGRIND_CFI_EPILOGUE \ VALGRIND_CFI_EPILOGUE \
"lgr %0, 2\n\t" \
: /*out*/ "=d" (_res) \ : /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
@ -5083,9 +4994,9 @@ typedef
"mvc 184(8,15), 72(1)\n\t" \ "mvc 184(8,15), 72(1)\n\t" \
"lg 1, 0(1)\n\t" \ "lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \ VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,192\n\t" \ "aghi 15,192\n\t" \
VALGRIND_CFI_EPILOGUE \ VALGRIND_CFI_EPILOGUE \
"lgr %0, 2\n\t" \
: /*out*/ "=d" (_res) \ : /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
@ -5125,9 +5036,9 @@ typedef
"mvc 192(8,15), 80(1)\n\t" \ "mvc 192(8,15), 80(1)\n\t" \
"lg 1, 0(1)\n\t" \ "lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \ VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,200\n\t" \ "aghi 15,200\n\t" \
VALGRIND_CFI_EPILOGUE \ VALGRIND_CFI_EPILOGUE \
"lgr %0, 2\n\t" \
: /*out*/ "=d" (_res) \ : /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
@ -5169,9 +5080,9 @@ typedef
"mvc 200(8,15), 88(1)\n\t" \ "mvc 200(8,15), 88(1)\n\t" \
"lg 1, 0(1)\n\t" \ "lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \ VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,208\n\t" \ "aghi 15,208\n\t" \
VALGRIND_CFI_EPILOGUE \ VALGRIND_CFI_EPILOGUE \
"lgr %0, 2\n\t" \
: /*out*/ "=d" (_res) \ : /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
@ -5215,9 +5126,9 @@ typedef
"mvc 208(8,15), 96(1)\n\t" \ "mvc 208(8,15), 96(1)\n\t" \
"lg 1, 0(1)\n\t" \ "lg 1, 0(1)\n\t" \
VALGRIND_CALL_NOREDIR_R1 \ VALGRIND_CALL_NOREDIR_R1 \
"lgr %0, 2\n\t" \
"aghi 15,216\n\t" \ "aghi 15,216\n\t" \
VALGRIND_CFI_EPILOGUE \ VALGRIND_CFI_EPILOGUE \
"lgr %0, 2\n\t" \
: /*out*/ "=d" (_res) \ : /*out*/ "=d" (_res) \
: /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
@ -5767,422 +5678,6 @@ typedef
#endif /* PLAT_mips32_linux */ #endif /* PLAT_mips32_linux */
/* ------------------------- nanomips-linux -------------------- */
#if defined(PLAT_nanomips_linux)
/* These regs are trashed by the hidden call. */
#define __CALLER_SAVED_REGS "$t4", "$t5", "$a0", "$a1", "$a2", \
"$a3", "$a4", "$a5", "$a6", "$a7", "$t0", "$t1", "$t2", "$t3", \
"$t8","$t9", "$at"
/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
long) == 4. */
#define CALL_FN_W_v(lval, orig) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[1]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
__asm__ volatile( \
"lw $t9, 0(%1)\n\t" \
VALGRIND_CALL_NOREDIR_T9 \
"move %0, $a0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_W(lval, orig, arg1) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[2]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
__asm__ volatile( \
"lw $t9, 0(%1)\n\t" \
"lw $a0, 4(%1)\n\t" \
VALGRIND_CALL_NOREDIR_T9 \
"move %0, $a0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[3]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
__asm__ volatile( \
"lw $t9, 0(%1)\n\t" \
"lw $a0, 4(%1)\n\t" \
"lw $a1, 8(%1)\n\t" \
VALGRIND_CALL_NOREDIR_T9 \
"move %0, $a0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[4]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
__asm__ volatile( \
"lw $t9, 0(%1)\n\t" \
"lw $a0, 4(%1)\n\t" \
"lw $a1, 8(%1)\n\t" \
"lw $a2,12(%1)\n\t" \
VALGRIND_CALL_NOREDIR_T9 \
"move %0, $a0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[5]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
__asm__ volatile( \
"lw $t9, 0(%1)\n\t" \
"lw $a0, 4(%1)\n\t" \
"lw $a1, 8(%1)\n\t" \
"lw $a2,12(%1)\n\t" \
"lw $a3,16(%1)\n\t" \
VALGRIND_CALL_NOREDIR_T9 \
"move %0, $a0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[6]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
__asm__ volatile( \
"lw $t9, 0(%1)\n\t" \
"lw $a0, 4(%1)\n\t" \
"lw $a1, 8(%1)\n\t" \
"lw $a2,12(%1)\n\t" \
"lw $a3,16(%1)\n\t" \
"lw $a4,20(%1)\n\t" \
VALGRIND_CALL_NOREDIR_T9 \
"move %0, $a0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[7]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
__asm__ volatile( \
"lw $t9, 0(%1)\n\t" \
"lw $a0, 4(%1)\n\t" \
"lw $a1, 8(%1)\n\t" \
"lw $a2,12(%1)\n\t" \
"lw $a3,16(%1)\n\t" \
"lw $a4,20(%1)\n\t" \
"lw $a5,24(%1)\n\t" \
VALGRIND_CALL_NOREDIR_T9 \
"move %0, $a0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[8]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
__asm__ volatile( \
"lw $t9, 0(%1)\n\t" \
"lw $a0, 4(%1)\n\t" \
"lw $a1, 8(%1)\n\t" \
"lw $a2,12(%1)\n\t" \
"lw $a3,16(%1)\n\t" \
"lw $a4,20(%1)\n\t" \
"lw $a5,24(%1)\n\t" \
"lw $a6,28(%1)\n\t" \
VALGRIND_CALL_NOREDIR_T9 \
"move %0, $a0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[9]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
__asm__ volatile( \
"lw $t9, 0(%1)\n\t" \
"lw $a0, 4(%1)\n\t" \
"lw $a1, 8(%1)\n\t" \
"lw $a2,12(%1)\n\t" \
"lw $a3,16(%1)\n\t" \
"lw $a4,20(%1)\n\t" \
"lw $a5,24(%1)\n\t" \
"lw $a6,28(%1)\n\t" \
"lw $a7,32(%1)\n\t" \
VALGRIND_CALL_NOREDIR_T9 \
"move %0, $a0\n" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[10]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
__asm__ volatile( \
"addiu $sp, $sp, -16 \n\t" \
"lw $t9,36(%1) \n\t" \
"sw $t9, 0($sp) \n\t" \
"lw $t9, 0(%1) \n\t" \
"lw $a0, 4(%1) \n\t" \
"lw $a1, 8(%1) \n\t" \
"lw $a2,12(%1) \n\t" \
"lw $a3,16(%1) \n\t" \
"lw $a4,20(%1) \n\t" \
"lw $a5,24(%1) \n\t" \
"lw $a6,28(%1) \n\t" \
"lw $a7,32(%1) \n\t" \
VALGRIND_CALL_NOREDIR_T9 \
"move %0, $a0 \n\t" \
"addiu $sp, $sp, 16 \n\t" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
arg7,arg8,arg9,arg10) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[11]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
__asm__ volatile( \
"addiu $sp, $sp, -16 \n\t" \
"lw $t9,36(%1) \n\t" \
"sw $t9, 0($sp) \n\t" \
"lw $t9,40(%1) \n\t" \
"sw $t9, 4($sp) \n\t" \
"lw $t9, 0(%1) \n\t" \
"lw $a0, 4(%1) \n\t" \
"lw $a1, 8(%1) \n\t" \
"lw $a2,12(%1) \n\t" \
"lw $a3,16(%1) \n\t" \
"lw $a4,20(%1) \n\t" \
"lw $a5,24(%1) \n\t" \
"lw $a6,28(%1) \n\t" \
"lw $a7,32(%1) \n\t" \
VALGRIND_CALL_NOREDIR_T9 \
"move %0, $a0 \n\t" \
"addiu $sp, $sp, 16 \n\t" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
arg6,arg7,arg8,arg9,arg10, \
arg11) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[12]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
_argvec[11] = (unsigned long)(arg11); \
__asm__ volatile( \
"addiu $sp, $sp, -16 \n\t" \
"lw $t9,36(%1) \n\t" \
"sw $t9, 0($sp) \n\t" \
"lw $t9,40(%1) \n\t" \
"sw $t9, 4($sp) \n\t" \
"lw $t9,44(%1) \n\t" \
"sw $t9, 8($sp) \n\t" \
"lw $t9, 0(%1) \n\t" \
"lw $a0, 4(%1) \n\t" \
"lw $a1, 8(%1) \n\t" \
"lw $a2,12(%1) \n\t" \
"lw $a3,16(%1) \n\t" \
"lw $a4,20(%1) \n\t" \
"lw $a5,24(%1) \n\t" \
"lw $a6,28(%1) \n\t" \
"lw $a7,32(%1) \n\t" \
VALGRIND_CALL_NOREDIR_T9 \
"move %0, $a0 \n\t" \
"addiu $sp, $sp, 16 \n\t" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
arg6,arg7,arg8,arg9,arg10, \
arg11,arg12) \
do { \
volatile OrigFn _orig = (orig); \
volatile unsigned long _argvec[13]; \
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
_argvec[11] = (unsigned long)(arg11); \
_argvec[12] = (unsigned long)(arg12); \
__asm__ volatile( \
"addiu $sp, $sp, -16 \n\t" \
"lw $t9,36(%1) \n\t" \
"sw $t9, 0($sp) \n\t" \
"lw $t9,40(%1) \n\t" \
"sw $t9, 4($sp) \n\t" \
"lw $t9,44(%1) \n\t" \
"sw $t9, 8($sp) \n\t" \
"lw $t9,48(%1) \n\t" \
"sw $t9,12($sp) \n\t" \
"lw $t9, 0(%1) \n\t" \
"lw $a0, 4(%1) \n\t" \
"lw $a1, 8(%1) \n\t" \
"lw $a2,12(%1) \n\t" \
"lw $a3,16(%1) \n\t" \
"lw $a4,20(%1) \n\t" \
"lw $a5,24(%1) \n\t" \
"lw $a6,28(%1) \n\t" \
"lw $a7,32(%1) \n\t" \
VALGRIND_CALL_NOREDIR_T9 \
"move %0, $a0 \n\t" \
"addiu $sp, $sp, 16 \n\t" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
: /*trash*/ "memory", __CALLER_SAVED_REGS \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#endif /* PLAT_nanomips_linux */
/* ------------------------- mips64-linux ------------------------- */ /* ------------------------- mips64-linux ------------------------- */
#if defined(PLAT_mips64_linux) #if defined(PLAT_mips64_linux)
@ -6651,10 +6146,6 @@ typedef
command. */ command. */
VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202, VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
/* Allows the client program to change a dynamic command line
option. */
VG_USERREQ__CLO_CHANGE = 0x1203,
/* These are useful and can be interpreted by any tool that /* These are useful and can be interpreted by any tool that
tracks malloc() et al, by using vg_replace_malloc.c. */ tracks malloc() et al, by using vg_replace_malloc.c. */
VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301, VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
@ -7137,14 +6628,6 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
command, 0, 0, 0, 0) command, 0, 0, 0, 0)
/* Change the value of a dynamic command line option.
Note that unknown or not dynamically changeable options
will cause a warning message to be output. */
#define VALGRIND_CLO_CHANGE(option) \
VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CLO_CHANGE, \
option, 0, 0, 0, 0)
#undef PLAT_x86_darwin #undef PLAT_x86_darwin
#undef PLAT_amd64_darwin #undef PLAT_amd64_darwin
#undef PLAT_x86_win32 #undef PLAT_x86_win32
@ -7158,7 +6641,6 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
#undef PLAT_s390x_linux #undef PLAT_s390x_linux
#undef PLAT_mips32_linux #undef PLAT_mips32_linux
#undef PLAT_mips64_linux #undef PLAT_mips64_linux
#undef PLAT_nanomips_linux
#undef PLAT_x86_solaris #undef PLAT_x86_solaris
#undef PLAT_amd64_solaris #undef PLAT_amd64_solaris

File diff suppressed because it is too large Load diff

View file

@ -10,10 +10,6 @@ option('libwacom',
type: 'boolean', type: 'boolean',
value: true, value: true,
description: 'Use libwacom for tablet identification (default=true)') description: 'Use libwacom for tablet identification (default=true)')
option('mtdev',
type: 'boolean',
value: true,
description: 'Use mtdev for multitouch protocol A devices (default=true)')
option('debug-gui', option('debug-gui',
type: 'boolean', type: 'boolean',
value: true, value: true,
@ -28,8 +24,8 @@ option('install-tests',
description: 'Install the libinput test command [default=false]') description: 'Install the libinput test command [default=false]')
option('documentation', option('documentation',
type: 'boolean', type: 'boolean',
value: false, value: true,
description: 'Build the documentation [default=false]') description: 'Build the documentation [default=true]')
option('coverity', option('coverity',
type: 'boolean', type: 'boolean',
value: false, value: false,
@ -38,15 +34,3 @@ option('zshcompletiondir',
type: 'string', type: 'string',
value: '', value: '',
description: 'Directory for zsh completion scripts ["no" disables]') description: 'Directory for zsh completion scripts ["no" disables]')
option('internal-event-debugging',
type: 'boolean',
value: false,
description: 'Enable additional internal event debug tracing. This will print key values to the logs and thus must never be enabled in a release build')
option('autoload-plugins',
type: 'boolean',
value: false,
description: 'Always load plugins from default plugin paths (only if the caller does not do so)')
option('lua-plugins',
type: 'feature',
value: 'auto',
description: 'Enable support for Lua plugins')

View file

@ -1,71 +0,0 @@
-- SPDX-License-Identifier: MIT
--
-- This is an example libinput plugin
--
-- This plugin detects the Copilot key on the keyboard with
-- the given VID/PID and replaces it with a different key (sequence).
-- UNCOMMENT THIS LINE TO ACTIVATE THE PLUGIN
-- libinput:register({1})
-- Replace this with your keyboard's VID/PID
KEYBOARD_VID = 0x046d
KEYBOARD_PID = 0x4088
meta_is_down = false
shift_is_down = false
-- shift-A, because you can never have enough screaming
replacement_sequence = { evdev.KEY_LEFTSHIFT, evdev.KEY_A }
function frame(device, frame, _)
for _, v in ipairs(frame) do
if v.value ~= 2 then -- ignore key repeats
if v.usage == evdev.KEY_LEFTMETA then
meta_is_down = v.value == 1
elseif v.usage == evdev.KEY_LEFTSHIFT then
shift_is_down = v.value == 1
elseif v.usage == evdev.KEY_F23 and meta_is_down and shift_is_down then
-- We know from the MS requirements that F23 for copilot is
-- either last key (on press) or the first key (on release)
-- of the three-key sequence, and no other keys are
-- within this frame.
if v.value == 1 then
-- Release our modifiers first
device:prepend_frame({
{ usage = evdev.KEY_LEFTSHIFT, value = 0 },
{ usage = evdev.KEY_LEFTMETA, value = 0 },
})
-- Insert our replacement press sequence
local replacement_frame = {}
for _, rv in ipairs(replacement_sequence) do
table.insert(replacement_frame, { usage = rv, value = 1 })
end
device:append_frame(replacement_frame)
else
-- Insert our replacement release sequence
local replacement_frame = {}
for idx = #replacement_sequence, 1, -1 do
table.insert(replacement_frame, { usage = replacement_sequence[idx], value = 0 })
end
device:append_frame(replacement_frame)
-- we don't care about re-pressing shift/meta because the
-- rest of the stack will filter the release for an
-- unpressed key anyway.
end
return {} -- discard this frame
end
end
end
end
function device_new(device)
local info = device:info()
if info.vid == KEYBOARD_VID and info.pid == KEYBOARD_PID then
device:connect("evdev-frame", frame)
end
end
libinput:connect("new-evdev-device", device_new)

View file

@ -1,64 +0,0 @@
-- SPDX-License-Identifier: MIT
--
-- This is an example libinput plugin
--
-- This plugin delays any event with relative motion by the given DELAY
-- by storing it in a table and replaying it via a timer callback later.
-- UNCOMMENT THIS LINE TO ACTIVATE THE PLUGIN
-- libinput:register({1})
DELAY = 1500 * 1000 -- 1.5s
next_timer_expiry = 0
devices = {}
function timer_expired(time_in_microseconds)
next_timer_expiry = 0
for device, frames in pairs(devices) do
while #frames > 0 and frames[1].time <= time_in_microseconds do
--- we don't have a current frame so it doesn't matter
--- whether we prepend or append
device:prepend_frame(frames[1].frame)
table.remove(frames, 1)
end
local next_frame = frames[1]
if next_frame and (next_timer_expiry == 0 or next_frame.time < next_timer_expiry) then
next_timer_expiry = next_frame.time
end
end
if next_timer_expiry ~= 0 then
libinput:timer_set_absolute(next_timer_expiry)
end
end
function frame(device, frame, timestamp)
for _, v in ipairs(frame) do
if v.usage == evdev.REL_X or v.usage == evdev.REL_Y then
local next_time = timestamp + DELAY
table.insert(devices[device], {
time = next_time,
frame = frame
})
if next_timer_expiry == 0 then
next_timer_expiry = next_time
libinput:timer_set_absolute(next_timer_expiry)
end
return {} -- discard frame
end
end
return nil
end
function device_new(device)
local usages = device:usages()
if usages[evdev.REL_X] then
devices[device] = {}
device:connect("evdev-frame", frame)
device:connect("device-removed", function(dev)
devices[dev] = nil
end)
end
end
libinput:connect("new-evdev-device", device_new)
libinput:connect("timer-expired", timer_expired)

View file

@ -1,16 +0,0 @@
-- SPDX-License-Identifier: MIT
--
-- An example plugin to show how to disable an internal feature.
--
-- Typically one would expect the plugin to re-implement the feature
-- in a more device-specific manner but that's not done here.
-- UNCOMMENT THIS LINE TO ACTIVATE THE PLUGIN
-- libinput:register({1})
libinput:connect("new-evdev-device", function(device)
local udev_info = device:udev_properties()
if udev_info["ID_INPUT_TOUCHPAD"] then
libinput:log_info("Disabling palm detection on " .. device:name())
device:disable_feature("touchpad-palm-detection")
end
end)

View file

@ -1,40 +0,0 @@
-- SPDX-License-Identifier: MIT
--
-- This plugin implements a very simple version of disable-while-typing.
-- It monitors all keyboard devices and if any of them send an event,
-- any touchpad device is disabled for 2 seconds.
-- And "disabled" means any event from that touchpad is simply
-- discarded.
--
-- Install this file in /etc/libinput/plugins and
--
-- UNCOMMENT THIS LINE TO ACTIVATE THE PLUGIN
-- libinput:register({1})
tp_enabled = true
libinput:connect("timer-expired", function(now)
libinput:log_debug("touchpad enabled")
tp_enabled = true
end)
libinput:connect("new-evdev-device", function (device)
local props = device:udev_properties()
if props.ID_INPUT_KEYBOARD then
device:connect("evdev-frame", function (device, frame, timestamp)
libinput:timer_set_relative(2000000)
if tp_enabled then
libinput:log_debug("touchpad disabled")
tp_enabled = false
end
end)
elseif props.ID_INPUT_TOUCHPAD then
libinput:log_debug("Touchpad detected: " .. device:name())
device:connect("evdev-frame", function (device, frame, timestamp)
if not tp_enabled then
-- Returning an empty table discards the event.
return {}
end
end)
end
end)

View file

@ -1,87 +0,0 @@
-- SPDX-License-Identifier: MIT
--
-- This is an example libinput plugin
--
-- This plugin swaps left and right buttons on any device that has both buttons.
-- Let's create a plugin. A single Lua script may create more than one
-- plugin instance but that's a bit of a nice use-case. Most scripts
-- should be a single plugin.
-- A plugin needs to be registered to activate. If it isn't, it is
-- cleaned up immediately. In the register call we supply
-- the list of plugin versions we support. Currently we only
-- have version 1.
--
-- UNCOMMENT THIS LINE TO ACTIVATE THE PLUGIN
-- libinput:register({1})
-- Note to the reader: it will be easier to understand this example
-- if you read it bottom-up from here on.
-- The callback for our "evdev-frame" signal.
-- These frames are sent *before* libinput gets to handle them so
-- any modifications will affect libinput.
function frame(device, frame, time_in_microseconds)
-- Frame is a table in the form
-- { { usage: 123, value: 3 }, ... }
-- Let's use the evdev module to make it more readable, evdev.KEY_A
-- is simply the value (0x1 << 16) | 0x1 (see linux/input-event-codes.h)
for _, v in ipairs(frame) do
-- If we get a right button event, change it to left, and
-- vice versa. Because this happens before libinput (or the next
-- plugin in the precedence order) sees the
-- frame it doesn't know that the swap happened.
if v.usage == evdev.BTN_RIGHT then
v.usage = evdev.BTN_LEFT
elseif v.usage == evdev.BTN_LEFT then
v.usage = evdev.BTN_RIGHT
end
end
-- We changed the frame, let's return it. If we return nil
-- the original frame is being used as-is.
return frame
end
-- This is a timer callback. It is invoked after one second
-- (see below) but only once - re-set the timer so
-- it goes off every second.
function timer_expired(time_in_microseconds)
libinput:timer_set_absolute(time_in_microseconds + 1000000)
end
-- Callback for the "new-evdev-device" signal, see below
-- The argument is the EvdevDevice object, see the documentation.
function device_new(device)
-- A table of evdev usages available on our device.
-- Using the evdev module makes it more readable but you can
-- use numbers (which is what evdev.EV_KEY and
-- friends resolve to anyway).
local usages = device:usages()
if usages[evdev.BTN_LEFT] and usages[evdev.BTN_RIGHT] then
-- The "evdev-frame" callback is invoked whenever the device
-- provided us with one evdev frame, i.e. a bunch of events up
-- to excluding EV_SYN SYN_REPORT.
device:connect("evdev-frame", frame)
end
-- The device has udev information, let's print it out. Right
-- now all we get are the ID_INPUT_ bits.
-- If this is empty we know libinput will ignore this device anyway
local udev_info = device:udev_properties()
for k, v in pairs(udev_info) do
libinput:log_debug(k .. "=" .. v)
end
end
-- Let's connect to the "new-evdev-device" signal. This function
-- is invoked when libinput detects a new evdev device (but before
-- that device is actually available to libinput as libinput device).
-- This allows us to e.g. change properties on the device.
libinput:connect("new-evdev-device", device_new)
-- Set our timer to expire 1s from now (in microseconds).
-- Timers are absolute, so they need to be added to the
-- current time
libinput:connect("timer-expired", timer_expired)
libinput:timer_set_relative(1000000)

View file

@ -1,32 +0,0 @@
-- SPDX-License-Identifier: MIT
--
-- This plugin inverts the horizontal scroll direction of
-- the Logitech MX Master mouse. OOTB the mouse scrolls
-- in the opposite direction to all other mice out there.
--
-- This plugin is only needed when the mouse is connected
-- to the Logitech Bolt receiver - on that receiver we cannot
-- tell which device is connected.
--
-- For the Logitech Unifying receiver and Bluetooth please
-- add the ModelInvertHorizontalScrolling=1 quirk
-- in quirks/30-vendor-logitech.quirks.
--
--
-- Install this file in /etc/libinput/plugins and
--
-- UNCOMMENT THIS LINE TO ACTIVATE THE PLUGIN
-- libinput:register({1})
libinput:connect("new-evdev-device", function (device)
local info = device:info()
if info.vid == 0x046D and info.pid == 0xC548 then
device:connect("evdev-frame", function (device, frame, timestamp)
for _, event in ipairs(frame) do
if event.usage == evdev.REL_HWHEEL or event.usage == evdev.REL_HWHEEL_HI_RES then
event.value = -event.value
end
end
return frame
end)
end
end)

View file

@ -1,22 +0,0 @@
-- SPDX-License-Identifier: MIT
--
-- An example plugin to make the pointer go three times as fast
--
-- Install this file in /etc/libinput/plugins and
--
-- UNCOMMENT THIS LINE TO ACTIVATE THE PLUGIN
-- libinput:register({1})
libinput:connect("new-evdev-device", function(device)
local usages = device:usages()
if usages[evdev.REL_X] then
device:connect("evdev-frame", function(device, frame, timestamp)
for _, v in ipairs(frame) do
if v.usage == evdev.REL_X or v.usage == evdev.REL_Y then
-- Multiply the relative motion by 3
v.value = v.value * 3
end
end
return frame
end)
end
end)

View file

@ -1,56 +0,0 @@
-- SPDX-License-Identifier: MIT
--
-- An example plugin to make the pointer go three times as slow
--
-- Install this file in /etc/libinput/plugins and
--
-- UNCOMMENT THIS LINE TO ACTIVATE THE PLUGIN
-- libinput:register({1})
remainders = {}
function split(v)
if math.abs(v) >= 1.0 then
local i = math.floor(math.abs(v))
local r = math.abs(v) % 1.0
if v < 0.0 then
i = -i
r = -r
end
return i, r
else
return 0, v
end
end
function decelerate(device, x, y)
local remainder = remainders[device]
local rx, ry = 0, 0
if x ~= 0.0 then
rx, remainder.x = split(remainder.x + x/3.0)
end
if y ~= 0.0 then
ry, remainder.y = split(remainder.y + y/3.0)
end
return rx, ry
end
libinput:connect("new-evdev-device", function(device)
local usages = device:usages()
if usages[evdev.REL_X] then
remainders[device] = { x = 0.0, y = 0.0 }
device:connect("evdev-frame", function(device, frame, timestamp)
for _, v in ipairs(frame) do
if v.usage == evdev.REL_X then
v.value, _ = decelerate(device, v.value, 0.0)
elseif v.usage == evdev.REL_Y then
_, v.value = decelerate(device, 0.0, v.value)
end
end
return frame
end)
device:connect("device-removed", function(dev)
remainders[dev] = nil
end)
end
end)

View file

@ -1,121 +0,0 @@
-- SPDX-License-Identifier: MIT
--
-- This is an example libinput plugin
--
-- This plugin controls a mouse/pointer from a tablet device. This
-- effectively hides stylus interactions and sends pointer events
-- instead. In other words: mouse emulation for tablets, implemented
-- by (remote) controlling a mouse device. This allows using a
-- tablet stylus as a mouse replacement without tablet limitations
-- from compositors or clients. Note that axis usually needed for
-- drawing (like pressure, tilt or distance) are no longer emitted
-- when this plugin is active and a mouse is connected. When no
-- mouse is connected, this plugin doesn't change tablet events,
-- thus the stylus works like a normal stylus.
-- UNCOMMENT THIS LINE TO ACTIVATE THE PLUGIN
-- libinput:register({1})
-- globals
pointer_device = nil
tablet_device = nil
maximum_x = nil
maximum_y = nil
function adjust_for_aspect_ratio(y)
-- adjust y to match monitor 21:9 aspect ratio
local adj_maximum_y = maximum_x * 1440 / 3440
return math.floor(math.min(y * maximum_y / adj_maximum_y, maximum_y + 1))
end
function on_tablet_frame(device, frame, time_in_microseconds)
-- emit tablet frame when there is no pointer device
if not pointer_device then return nil end
-- map tablet frame to pointer frame
local events = {}
for _, v in ipairs(frame) do
if v.usage == evdev.ABS_MISC then
-- save a few cycles on Wacom tablets by discarding a
-- proximity in / out frame early, non-Wacom tablets should
-- use BTN_TOOL_PEN/RUBBER/... instead
return {}
elseif v.usage == evdev.ABS_X then
table.insert(events, { usage = evdev.ABS_X, value = v.value })
elseif v.usage == evdev.ABS_Y then
-- uncomment the next two lines and comment the original line
-- for configuring aspect correction, see
-- adjust_for_aspect_ratio() for details and configuration
-- local adj_value = adjust_for_aspect_ratio(v.value)
-- table.insert(events, { usage = evdev.ABS_Y, value = adj_value })
table.insert(events, { usage = evdev.ABS_Y, value = v.value })
elseif v.usage == evdev.BTN_TOUCH then
table.insert(events, { usage = evdev.BTN_LEFT, value = v.value })
elseif v.usage == evdev.BTN_STYLUS then
table.insert(events, { usage = evdev.BTN_RIGHT, value = v.value })
elseif v.usage == evdev.BTN_STYLUS2 then
table.insert(events, { usage = evdev.BTN_MIDDLE, value = v.value })
end
end
-- emit pointer frame, if any
if #events > 0 then pointer_device:append_frame(events) end
-- discard tablet frame
return {}
end
function on_tablet_removed(device)
libinput:log_info("Remove tablet device")
tablet_device = nil
end
function on_pointer_removed(device)
libinput:log_info("Remove pointer device")
pointer_device = nil
end
function setup()
if not pointer_device or not tablet_device then return end
libinput:log_info("Controlling '" .. pointer_device:name() .. "' with '" .. tablet_device:name() .. "'")
-- fetch absinfos from tablet
local absinfo_x = {}
local absinfo_y = {}
for a, b in pairs(tablet_device:absinfos()) do
if a == evdev.ABS_X then absinfo_x = b end
if a == evdev.ABS_Y then absinfo_y = b end
end
-- copy max values for aspect ratio correction later on
maximum_x = absinfo_x.maximum
maximum_y = absinfo_y.maximum
-- copy absinfos to pointer device
pointer_device:set_absinfo(evdev.ABS_X, absinfo_x)
pointer_device:set_absinfo(evdev.ABS_Y, absinfo_y)
-- setup listeners
pointer_device:connect("device-removed", on_pointer_removed)
tablet_device:connect("device-removed", on_tablet_removed)
tablet_device:connect("evdev-frame", on_tablet_frame)
end
function on_new_device(device)
local udev = device:udev_properties()
if udev["ID_INPUT_TABLET"] and not udev["ID_INPUT_TABLET_PAD"] then
libinput:log_info("Found tablet device")
tablet_device = device
setup()
end
if udev["ID_INPUT_MOUSE"] then
libinput:log_info("Found pointer device")
pointer_device = device
setup()
end
end
-- setup listener
libinput:connect("new-evdev-device", on_new_device)

View file

@ -1,64 +0,0 @@
-- SPDX-License-Identifier: MIT
--
-- This is an example libinput plugin
--
-- This plugin maps a downwards mouse wheel to a button down event and
-- an upwards wheel movement to a button up event.
-- UNCOMMENT THIS LINE TO ACTIVATE THE PLUGIN
-- libinput:register({1})
-- The button we want to press on wheel events
local wheel_button = evdev.BTN_EXTRA
local button_states = {}
local function evdev_frame(device, frame, timestamp)
local events = {}
local modified = false
for _, v in ipairs(frame) do
if v.usage == evdev.REL_WHEEL then
-- REL_WHEEL is inverted, neg value -> down, pos value -> up
if v.value < 0 then
if not button_states[device] then
table.insert(events, { usage = wheel_button, value = 1 })
button_states[device] = true
end
else
if button_states[device] then
table.insert(events, { usage = wheel_button, value = 0 })
button_states[device] = false
end
end
modified = true
-- Because REL_WHEEL is no longer a wheel, the high-res
-- events are dropped
elseif v.usage == evdev.REL_WHEEL_HI_RES then
modified = true
else
table.insert(events, v)
end
end
if modified then
return events
else
return nil
end
end
local function device_new(device)
local usages = device:usages()
if usages[evdev.REL_WHEEL] then
button_states[device] = false
if not usages[wheel_button] then
device:enable_evdev_usage(wheel_button)
end
device:connect("evdev-frame", evdev_frame)
device:connect("device-removed", function(dev)
button_states[dev] = nil
end)
end
end
libinput:connect("new-evdev-device", device_new)

View file

@ -1,17 +0,0 @@
plugins = [
'10-example.lua',
'10-dwt.lua',
'10-logitech-mx-master-horiz-scroll.lua',
'10-pointer-go-faster.lua',
'10-pointer-go-slower.lua',
'10-delay-motion.lua',
'10-disable-feature.lua',
'10-copilot-key-override.lua',
'10-wheel-to-button.lua',
'10-tablet-mouse-control.lua',
]
fs = import('fs')
foreach plugin : plugins
fs.copyfile(plugin)
endforeach

View file

@ -9,23 +9,3 @@ AttrKeyboardIntegration=internal
MatchUdevType=keyboard MatchUdevType=keyboard
MatchBus=bluetooth MatchBus=bluetooth
AttrKeyboardIntegration=external AttrKeyboardIntegration=external
# Detachable devices usually have the tablet part buttons wired as ps2 keyboard,
# don't disable them when tablet-mode switch is in effect.
# DMI Chassis Type 20h (32 decimal) is Detachable as per SMBIOS specification.
[Detachable Device Buttons]
MatchBus=ps2
MatchUdevType=keyboard
MatchDMIModalias=dmi:*:ct32:*
ModelTabletModeNoSuspend=1
# Tablet devices usually have the tablet part buttons wired as ps2 keyboard,
# despite being tablets some of them, e.g. Microsoft Surface Laptop Studio,
# expose tablet-mode switch, so don't disable the ps2 keyboard.
# Tablets that don't expose tablet-mode switch won't have any diference.
# DMI Chassis Type 1Eh (30 decimal) is Tablet as per SMBIOS specification.
[Tablet Device Buttons]
MatchBus=ps2
MatchUdevType=keyboard
MatchDMIModalias=dmi:*:ct30:*
ModelTabletModeNoSuspend=1

View file

@ -0,0 +1,11 @@
# Do not edit this file, it will be overwritten on update
[Lid Switch Ct9]
MatchName=*Lid Switch*
MatchDMIModalias=dmi:*:ct9:*
AttrLidSwitchReliability=reliable
[Lid Switch Ct10]
MatchName=*Lid Switch*
MatchDMIModalias=dmi:*:ct10:*
AttrLidSwitchReliability=reliable

View file

@ -1,6 +0,0 @@
# Do not edit this file, it will be overwritten on update
# https://gitlab.freedesktop.org/libinput/libinput/-/issues/656
[Emulated Mouse]
MatchName=ImPS/2 Generic Wheel Mouse
ModelBouncingKeys=1

View file

@ -1,8 +0,0 @@
# Do not edit this file, it will be overwritten on update
[A4TECH USB X-710BK]
MatchUdevType=mouse
MatchBus=usb
MatchVendor=0x09DA
MatchProduct=0x9090
ModelBouncingKeys=1

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