Compare commits

..

No commits in common. "main" and "1.11.901" have entirely different histories.

473 changed files with 31025 additions and 99860 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

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

View file

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

View file

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

View file

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

View file

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

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

@ -5,8 +5,8 @@ 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 needs 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
relative pointer events from touchpads, pointer acceleration, etc. relative pointer events from touchpads, pointer acceleration, etc.
@ -15,11 +15,11 @@ User documentation
------------------ ------------------
Documentation explaining features available in libinput is available Documentation explaining features available in libinput is available
[here](https://wayland.freedesktop.org/libinput/doc/latest/features.html). [here](https://wayland.freedesktop.org/libinput/doc/latest/pages.html).
This includes the [FAQ](https://wayland.freedesktop.org/libinput/doc/latest/faqs.html) This includes the [FAQ](https://wayland.freedesktop.org/libinput/doc/latest/faq.html)
and the instructions on and the instructions on
[reporting bugs](https://wayland.freedesktop.org/libinput/doc/latest/reporting-bugs.html). [reporting bugs](https://wayland.freedesktop.org/libinput/doc/latest/reporting_bugs.html).
Source code Source code
@ -32,7 +32,7 @@ For a list of current and past releases visit:
https://www.freedesktop.org/wiki/Software/libinput/ https://www.freedesktop.org/wiki/Software/libinput/
Build instructions: Build instructions:
https://wayland.freedesktop.org/libinput/doc/latest/building.html https://wayland.freedesktop.org/libinput/doc/latest/building_libinput.html
Reporting Bugs Reporting Bugs
-------------- --------------
@ -43,25 +43,24 @@ https://gitlab.freedesktop.org/libinput/libinput/issues/
Where possible, please provide the `libinput record` output Where possible, please provide the `libinput record` output
of the input device and/or the event sequence in question. of the input device and/or the event sequence in question.
See https://wayland.freedesktop.org/libinput/doc/latest/reporting-bugs.html See @ref reporting_bugs for more info.
for more info.
Documentation Documentation
------------- -------------
- Developer API documentation: https://wayland.freedesktop.org/libinput/doc/latest/development.html - Developer API documentation: https://wayland.freedesktop.org/libinput/doc/latest/modules.html
- High-level documentation about libinput's features: - High-level documentation about libinput's features:
https://wayland.freedesktop.org/libinput/doc/latest/features.html https://wayland.freedesktop.org/libinput/doc/latest/pages.html
- Build instructions: - Build instructions:
https://wayland.freedesktop.org/libinput/doc/latest/building.html https://wayland.freedesktop.org/libinput/doc/latest/building_libinput.html
- Documentation for previous versions of libinput: https://wayland.freedesktop.org/libinput/doc/ - Documentation for previous versions of libinput: https://wayland.freedesktop.org/libinput/doc/
Examples of how to use libinput are the debugging tools in the libinput 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 +74,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

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

View file

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

1
doc/api/git-version.dox Normal file
View file

@ -0,0 +1 @@
<a href="https://gitlab.freedesktop.org/libinput/libinput/commit/__GIT_VERSION__">__GIT_VERSION__</a>

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

@ -96,7 +96,7 @@ int main(void) {
// handle the event here // handle the event here
libinput_event_destroy(event); libinput_event_destroy(li);
libinput_dispatch(li); libinput_dispatch(li);
} }
@ -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,32 @@ 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
doc_git_version = vcs_tag(command : ['git', 'log', '-1', '--format=%h'],
fallback : 'ERROR - unable to fetch git version',
input : 'git-version.dox',
output : 'git-version.dox',
replace_string: '__GIT_VERSION__')
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 +43,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,13 +52,11 @@ src_doxygen = files(
'style/libinputdoxygen.css', 'style/libinputdoxygen.css',
) )
doxyfiles = [] doxyfiles = custom_target('doxyfiles',
foreach f : src_doxygen input : src_doxygen,
df = configure_file(input: f, output : 'doxyfiles',
output: '@PLAINNAME@', command : [prg_install, '-t', '@OUTDIR@', '@INPUT@'],
copy : true) build_by_default: true)
doxyfiles += [ df ]
endforeach
doc_config = configuration_data() doc_config = configuration_data()
doc_config.set('PACKAGE_NAME', meson.project_name()) doc_config.set('PACKAGE_NAME', meson.project_name())
@ -41,12 +65,13 @@ doc_config.set('builddir', meson.current_build_dir())
doxyfile = configure_file(input : 'libinput.doxygen.in', doxyfile = configure_file(input : 'libinput.doxygen.in',
output : 'libinput.doxygen', output : 'libinput.doxygen',
configuration : doc_config) configuration : doc_config,
install : false)
custom_target('doxygen', custom_target('doxygen',
input : [ doxyfiles, doxyfile, mainpage ] + src_doxygen, input : [ doxyfile, mainpage, doc_git_version] + src_doxygen,
output : [ 'html' ], output : [ '.' ],
command : [ doxygen, doxyfile ], command : [ doxygen, doxyfile ],
install : false, install : false,
depends: [ mainpage ], depends: [doxyfiles, mainpage, doc_git_version],
build_by_default : true) build_by_default : true)

View file

@ -1,42 +1,18 @@
@import url("https://fonts.googleapis.com/css?family=Roboto+Mono");
dd { dd {
margin-left: 30px; margin-left: 30px;
} }
.title { .title {
font-size: 200%; font-size: 400%;
font-weight: bold; font-weight: 200;
}
.title .ingroups {
font-size: 50%;
} }
h1 { h1 {
font-size: 150%; font-size: 300%;
color: #354C7B;
background: none;
border-bottom: 1px solid #879ECB;
font-size: 150%;
font-weight: normal;
padding-top: 8px;
padding-bottom: 8px;
padding-left: 0px;
width: 100%;
} }
h2 { h2 {
font-size: 120%; font-size: 200%;
color: #354C7B;
background: none;
border-bottom: 1px solid #879ECB;
font-size: 150%;
font-weight: normal;
padding-top: 8px;
padding-bottom: 8px;
padding-left: 0px;
width: 100%;
} }
.sm-dox li { .sm-dox li {
@ -69,52 +45,3 @@ h2 {
#main-menu li ul { #main-menu li ul {
display: none; display: none;
} }
.paramname {
padding-right: 10px;
}
.memtitle {
background-image: none;
background-color: #F0F0F0;
}
.memproto {
background-color: #F0F0F0;
}
.headertitle {
background-image: none;
background-color: #F0F0F0;
}
div.header {
border: none;
}
td.fieldname {
font-family: 'Roboto Mono', monospace;
}
.fieldtable th {
background-image: none;
background-color: #F0F0F0;
}
body {
letter-spacing: 0px;
}
.mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams {
background-color: #F0F0F0;
}
a {
color: #2873b0;
}
.navpath ul {
background-image: none;
background-color: #F0F0F0;
}

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 78 KiB

83
doc/doxygen-to-sphinx.sh Executable file
View file

@ -0,0 +1,83 @@
#!/bin/bash -e
#
# Helper script to convert doxygenisms to sphinx-isms
outdir=$1
fname=$2
! test -z "$outdir" || exit 1
! test -z "$fname" || exit 1
file="$fname"
outfile="$(basename --suffix='.dox' $fname).rst"
# awk commands:
# indent anything between the verbatim tags
# indent anything between the code tags
# add a empty line before the first list item (line starting with -)
cat "$file" | \
awk \
'$0 ~ /.*@verbatim$/ { inside=1; print $0 "\n"; next; }
$0 ~ /@endverbatim/ { inside=0; }
inside == 1 { print " " $0 }
inside == 0 { print }' | \
awk \
'$0 ~ /@code$/ { inside=1; print $0 "\n"; next; }
$0 ~ /@endcode/ { inside=0; }
inside == 1 { print " " $0 }
inside == 0 { print }' | \
awk \
'$0 ~ /@dot$/ { inside=1; print $0 "\n"; next; }
$0 ~ /@enddot/ { inside=0; }
inside == 1 { print " " $0 }
inside == 0 { print }' | \
awk \
'$0 ~ /<dd>/ { inside=1; print $0 "\n"; next; }
$0 ~ /<\/dd>/ { inside=0; }
inside == 1 { print " " $0 }
inside == 0 { print }' | \
awk \
'/^-/{
if (!in_list && a != "") print ""; in_list=1
}
/^$/ {in_list=0}
{a=$0; print}' | \
sed \
-e 's|@page \([^ ]*\) \(.*\)|.. _\1:\n\n==============================================================================\n\2\n==============================================================================|' \
-e 's|@section \([^ ]*\) \(.*\)|.. _\1:\n\n------------------------------------------------------------------------------\n\2\n------------------------------------------------------------------------------|' \
-e 's|@subsection \([^ ]*\) \(.*\)|.. _\1:\n\n..............................................................................\n\2\n..............................................................................|' \
-e ':a;/@[[:alpha:]]\+$/{N;s/\(@[[:alpha:]]\+\)\n/\n\1 /;ba}' \
-e 's|@see \(LIBINPUT_[_[:alpha:]]\+\)|**\1**|' \
-e 's|@ref \(LIBINPUT_[_[:alpha:]]\+\)|**\1**|' \
-e 's|@ref \(libinput_[_[:alpha:]]\+\)|**\1**|' \
-e 's|\(libinput_[_[:alpha:]]\+()\)|**\1**|' \
-e 's|[ ]*<dt>||' \
-e 's|</dt>||' \
-e 's|[ ]*<dd>| |' \
-e 's|</dd>||' \
-e '/<\/\?dl>/d' \
-e 's|<b>|**|' \
-e 's|</b>|**|' \
-e 's|\*40|\\*40|' \
-e 's|\*50|\\*50|' \
-e 's|@note|.. note::|' \
-e 's|@warning|.. warning::|' \
-e 's|@dotfile \(.*\)|.. graphviz:: \1|' \
-e 's|@dot[ ]*|.. graphviz::\n\n|' \
-e 's|@enddot||' \
-e 's|@code[ ]*|::\n\n|' \
-e 's|`[^`]\+|`\0|g' \
-e 's|[^`]\+`$|\0`|g' \
-e 's|@ref \([-[:alnum:]_]*\) "\(.*\)"|:ref:`\2 <\1>`|' \
-e 's|@ref \([-[:alnum:]_]*\)|:ref:`\1`|' \
-e 's|@endcode||' \
-e 's|@tableofcontents[ ]*|.. contents::\n :local:\n :backlinks: entry\n|' \
-e 's|@verbatim[ ]*|::\n|' \
-e 's|@endverbatim[ ]*||' \
-e 's|@image html \([^ ]*\) "\?\(.*\)"\?|.. figure:: \1\n :align: center\n\n \2|' \
-e 's|<a href="\(.*\)">\(.*\)</a>|`\2 <\1>`_|' \
-e 's|\[\(.*\)\](\(.*\))|`\1 <\2>`_|' \
-e 's|^ \+$||' \
-e '/^\*\//d' \
-e '/^\/\*\*$/d' \
> "$outdir/$outfile"

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

After

Width:  |  Height:  |  Size: 166 KiB

View file

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

View file

@ -136,7 +136,7 @@ devices is something other than 1:1. A normalized axes thus is only useful to
determine that the stylus is e.g. at 78% from the left, 34% from the top of determine that the stylus is e.g. at 78% from the left, 34% from the top of
the device. Without knowing the per-axis resolution, these numbers are the device. Without knowing the per-axis resolution, these numbers are
meaningless. Worse, calculation based on previous coordinates is simply wrong: meaningless. Worse, calculation based on previous coordinates is simply wrong:
a movement from 0/0 to 50%/50% is not a 45-degree line. a movement from 0/0 to 50%/50% is not a 45% degree line.
This could be alleviated by providing resolution and information about the This could be alleviated by providing resolution and information about the
aspect ratio to the caller. Which shifts processing and likely errors into the aspect ratio to the caller. Which shifts processing and likely errors into the

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 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 pipeline"]
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

@ -13,32 +13,9 @@ Instructions on how to build libinput and its tools and how to build against
libinput. libinput.
The build instruction on this page detail how to overwrite your The build instruction on this page detail how to overwrite your
system-provided libinput with one from the git repository, 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 diligence
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
@ -64,30 +41,30 @@ When running libinput versions 1.11.x or earlier, you must run
:: ::
$> sudo systemd-hwdb update $> sudo udevadm hwdb --update
Additional options may also be specified. For example: 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
for testing and reduces the number of dependencies needed. for testing and reduces the number of dependencies needed.
The ``prefix`` or other options can be changed later with the The ``prefix`` or other options can be changed later with the
``meson configure`` command. For example: ``mesonconf`` command. For example:
:: ::
$> meson configure builddir/ -Dprefix=/some/other/prefix -Ddocumentation=true $> mesonconf builddir/ -Dprefix=/some/other/prefix -Ddocumentation=true
$> ninja -C builddir $> ninja -C builddir
$> sudo ninja -C builddir/ install $> sudo ninja -C builddir/ install
Running ``meson configure builddir/`` with no other arguments lists all Running ``mesonconf builddir/`` with no other arguments lists all
configurable options meson provides. configurable options meson provides.
To rebuild from scratch, simply remove the build directory and run meson To rebuild from scratch, simply remove the build directory and run meson
@ -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:
@ -150,8 +129,6 @@ overwriting manually installed files.
SELinux adjustments SELinux adjustments
.............................................................................. ..............................................................................
.. note:: This section only applies to meson version < 0.42.0
On systems with SELinux, overwriting the distribution-provided package with On systems with SELinux, overwriting the distribution-provided package with
a manually built libinput may cause SELinux denials. This usually manifests a manually built libinput may cause SELinux denials. This usually manifests
when gdm does not start because it is denied access to libinput. The journal when gdm does not start because it is denied access to libinput. The journal
@ -180,16 +157,16 @@ This issue is tracked in https://github.com/mesonbuild/meson/issues/1967.
.. _building_dependencies: .. _building_dependencies:
------------------------------------------------------------------------------ ..............................................................................
Build dependencies Build dependencies
------------------------------------------------------------------------------ ..............................................................................
libinput has a few build-time dependencies that must be installed prior to libinput has a few build-time dependencies that must be installed prior to
running meson. running configure.
.. hint:: The build dependencies for some distributions can be found in the .. note:: 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
@ -217,52 +194,106 @@ with one of the following commands:
If dependencies are missing, meson shows a message ``No package 'foo' If dependencies are missing, a message ``No package 'foo' found`` will be
found``. See shown during the configure stage. 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.au/2014/05/configure-fails-with-no-package-foo.html>`_
for instructions on how to fix it. for instructions on how to fix it.
.. _building_libwacom:
.............................................................................. ..............................................................................
Build dependencies per distribution Building without libwacom
.............................................................................. ..............................................................................
libwacom is required by libinput's tablet code to gather additional
.. include:: dependencies.rst information about tablets that is not available from the kernel device
itself. libwacom is required by default but can be skipped when
:ref:`building`.
.. _building_conditional: ::
------------------------------------------------------------------------------ $> meson --prefix=/usr -Dlibwacom=false builddir
Conditional builds
------------------------------------------------------------------------------
libinput supports several meson options to disable parts of the build. See
the ``meson_options.txt`` file in the source tree for a full list of
available options. The default build enables most options and thus requires
more build dependencies. On systems where build dependencies are an issue,
options may be disabled with this meson command: ::
meson setup --prefix=/usr -Dsomefeature=false builddir It is not recommended to disable libwacom unless libinput is used in an
environment where tablet support is not required. libinput provides tablet
support even without libwacom, but some features may be missing or working
differently.
.. _building_debug_gui:
..............................................................................
Building without the graphical helper tool
..............................................................................
The :ref:`tools` provide commandline features as well as graphical debugging
features. To keep dependencies in check on some builds, the graphical
features of the :ref:`tools` can be disabled. By default, the ``debug-gui``
feature of the ``libinput`` tool is enabled and if the required libraries are
not available, the build will fail. If the feature is not required, use the
```--disable-debug-gui``` argument when :ref:`building`.
::
$> meson --prefix=/usr -Ddebug-gui=false builddir
.. _building_autotools:
..............................................................................
Building with autotools
..............................................................................
**libinput no longer supports building with autotools.** These
instructions are kept for users for libinput versions up to 1.8.x.
A build with automake is usually the process below. A successful build
requires the :ref:`building_dependencies` to be installed at configure
time.
::
$> git clone https://gitlab.freedesktop.org/libinput/libinput
$> cd libinput
$> ./autogen.sh --prefix=/usr --libdir=/usr/lib64
$> make
$> sudo make install
$> sudo udevadm hwdb --update
.. note:: On Debian-based distributions including Ubuntu and its derivatives skip the
``--libdir=/usr/lib64`` argument.
To uninstall libinput as detailed in section :ref:`reverting_install`, run
::
$> sudo make uninstall
# WARNING: Do not restart the computer/X/the Wayland compositor after make
# uninstall, reinstall the system package immediately!
To disable libwacom as detailed in section :ref:`building_libwacom`, run
::
$> ./autogen.sh --disable-libwacom --prefix=/usr --libdir=/usr/lib64
To disable the graphical helper tool as detailed in section
:ref:`building_debug_gui`, run
::
$> ./autogen.sh --disable-debug-gui --prefix=/usr --libdir=/usr/lib64
Where ``-Dsomefeature=false`` may be one of:
- ``-Ddocumentation=false``
Disables the documentation build (this website). Building the
documentation is only needed on the maintainer machine.
- ``-Dtests=false``
Disables the test suite. The test suite is only needed on developer
systems.
- ``-Ddebug-gui=false``
Disables the ``libinput debug-gui`` helper tool (see :ref:`tools`),
dropping GTK and other build dependencies. The debug-gui is only
required for troubleshooting.
- ``-Dlibwacom=false``
libwacom is required by libinput's tablet code to gather additional
information about tablets that is not available from the kernel device.
It is not recommended to disable libwacom unless libinput is used in an
environment where tablet support is not required. libinput provides tablet
support even without libwacom, but some features may be missing or working
differently.
.. _building_against: .. _building_against:
@ -272,21 +303,8 @@ Building against libinput
libinput provides a libinput provides a
`pkg-config <https://www.freedesktop.org/wiki/Software/pkg-config/>`_ file. `pkg-config <https://www.freedesktop.org/wiki/Software/pkg-config/>`_ file.
Software that uses autotools should use the ``PKG_CHECK_MODULES`` autoconf Software that uses libinput should use pkg-config and the
macro: :: ``PKG_CHECK_MODULES`` autoconf macro.
PKG_CHECK_MODULES(LIBINPUT, "libinput")
Software that uses meson should use the ``dependency()`` function: ::
pkgconfig = import('pkgconfig')
dep_libinput = dependency('libinput')
Software that uses CMake should use: ::
find_package(Libinput)
target_link_libraries(myprogram PRIVATE Libinput::Libinput)
Otherwise, the most rudimentary way to compile and link a program against Otherwise, the most rudimentary way to compile and link a program against
libinput is: libinput is:

View file

@ -30,10 +30,10 @@ The "bounce" method guarantees that all press events are delivered
immediately and most release events are delivered immediately. The immediately and most release events are delivered immediately. The
"spurious" method requires that release events are delayed, libinput thus "spurious" method requires that release events are delayed, libinput thus
does not enable this method unless a faulty event sequence is detected. A does not enable this method unless a faulty event sequence is detected. A
message is printed to the log when spurious debouncing was detected. message is printed to the log when spurious deboucing was detected.
libinput's debouncing is supposed to correct hardware damage or Note that libinput's debouncing intended to correct hardware damage or
substandard hardware. Debouncing also exists as an accessibility feature substandard hardware. Debouncing is also used as an accessibility feature
but the requirements are different. In the accessibility feature, multiple but the requirements are different. In the accessibility feature, multiple
physical key presses, usually caused by involuntary muscle movement, must be physical key presses, usually caused by involuntary muscle movement, must be
filtered to only one key press. This feature must be implemented higher in filtered to only one key press. This feature must be implemented higher in
@ -48,9 +48,4 @@ correspond to the buttons 'pressed' and 'released' states, respectively.
.. figure:: button-debouncing-wave-diagram.svg .. figure:: button-debouncing-wave-diagram.svg
:align: center :align: center
Diagram illustrating button debouncing Diagram illustrating button debouncing"
Some devices send events in bursts, erroneously triggering the button
debouncing detection. Please :ref:`file a bug <reporting_bugs>` if that
occurs for your device.

View file

@ -4,23 +4,22 @@
Clickpad software button behavior Clickpad software button behavior
============================================================================== ==============================================================================
"Clickpads" are touchpads without separate physical buttons. Instead, the Clickpad is the name given to touchpads without physical buttons below the
whole touchpad acts as a button and left or right button clicks are touchpad. Instead, the whole touchpad acts as a button and left or right
distinguished by :ref:`the location of the fingers <software_buttons>` or button clicks are distinguished by the location and/or number of fingers on
the :ref:`number of fingers on the touchpad <clickfinger>`. the touchpad.
"ClickPad" is a trademark by `Synaptics Inc. <http://www.synaptics.com/en/clickpad.php>`_ ("ClickPad" is a trademark by Synaptics Inc.)[http://www.synaptics.com/en/clickpad.php]
but for simplicity we refer to any touchpad with the above feature as Clickpad, but for simplicity we refer to any touchpad with the above feature as Clickpad,
regardless of the manufacturer. regardless of the manufacturer.
The kernel marks clickpads with the A clickpad is always marked with the
`INPUT_PROP_BUTTONPAD <https://www.kernel.org/doc/Documentation/input/event-codes.txt>`_ `INPUT_PROP_BUTTONPAD <https://www.kernel.org/doc/Documentation/input/event-codes.txt>`_
property. Without this property, libinput would not know whether a touchpad property. To perform a right-click on a Clickpad, libinput provides
is a clickpad or not. To perform a right-click on a Clickpad, libinput :ref:`software_buttons` and @ref clickfinger.
provides :ref:`software_buttons` and :ref:`clickfinger`.
.. note:: The term "click" refers refer to a physical button press In the page below, the term "click" shall refer to a physical button press
and/or release of the touchpad, the term "button event" refers to and/or release of the touchpad, the term "button event" refers to the events
the events generated by libinput in response to a click. generated by libinput and passed to the caller in response to a click.
.. _software_buttons: .. _software_buttons:
@ -28,15 +27,10 @@ provides :ref:`software_buttons` and :ref:`clickfinger`.
Software button areas Software button areas
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
The bottom of the touchpad is split into three distinct areas generate left, On most clickpads, this is the default behavior. The bottom of the touchpad
middle or right button events on click. The height of the button area is split into three distinct areas generate left, middle or right button
depends on the hardware but is usually around 10mm. events on click. The height of the button area depends on the hardware but
is usually around 10mm.
.. figure :: software-buttons-visualized.svg
:align: center
The locations of the virtual button areas.
Left, right and middle button events can be triggered as follows: Left, right and middle button events can be triggered as follows:
@ -45,49 +39,34 @@ Left, right and middle button events can be triggered as follows:
- if a finger is in the right area, a click generates right button events. - if a finger is in the right area, a click generates right button events.
- if a finger is in the middle area, a click generates middle button events. - if a finger is in the middle area, a click generates middle button events.
The middle button is always centered on the touchpad and smaller in size
than the left or right button. The actual size is device-dependent though as
many touchpads do not have visible markings for the middle button the exact
location of the button is not visibly obvious.
.. figure:: software-buttons.svg .. figure:: software-buttons.svg
:align: center :align: center
Left, right and middle-button click with software button areas Left, right and middle-button click with software button areas"
The middle button is always centered on the touchpad and smaller in size .. note:: If middle button emulation is enabled on a clickpad, only left and right
than the left or right button. The actual size is device-dependent. Many button areas are available. For more details, see
touchpads do not have visible markings so the exact location of the button **libinput_device_config_middle_emulation_set_enabled()**.
is unfortunately not visibly obvious.
.. note:: If :ref:`middle button emulation <middle_button_emulation>` is
enabled on a clickpad, only left and right button areas are
available.
If fingers are down in the main area in addition to fingers in the If fingers are down in the main area in addition to fingers in the
left or right button area, those fingers are are ignored. left or right button area, those fingers are are ignored.
A release event always releases the buttons logically down, regardless of A release event always releases the buttons logically down, regardless of
the current finger position the current finger position
.. figure:: software-buttons-thumbpress.svg
:align: center
Only the location of the thumb determines whether it is a left, right or
middle click.
The movement of a finger can alter the button area behavior: The movement of a finger can alter the button area behavior:
- if a finger starts in the main area and moves into the software button - if a finger starts in the main area and moves into the software button
area, the software buttons do not apply to that finger area, the software buttons do not apply to that finger
- a finger in the software button area does not move the pointer
- if a finger moves out out of the button area it will control the pointer
if it's the first finger in the main area
- once a finger has moved out of the button area, it cannot move back in and - once a finger has moved out of the button area, it cannot move back in and
trigger a right or middle button event trigger a right or middle button event
- a finger moving within the software button area does not move the pointer
- once a finger moves out out of the button area it will control the
pointer (this only applies if there is no other finger down on the
touchpad)
.. figure:: software-buttons-conditions.svg
:align: center
**Left:** moving a finger into the right button area does not trigger a
right-button click.
**Right:** moving within the button areas does not generate pointer
motion.
On some touchpads, notably the 2015 Lenovo X1 Carbon 3rd series, the very On some touchpads, notably the 2015 Lenovo X1 Carbon 3rd series, the very
bottom end of the touchpad is outside of the sensor range but it is possible bottom end of the touchpad is outside of the sensor range but it is possible
@ -102,17 +81,16 @@ 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
One, two and three-finger click with Clickfinger behavior One, two and three-finger click with Clickfinger behavior"
On some touchpads, libinput imposes a limit on how the fingers may be placed On some touchpads, libinput imposes a limit on how the fingers may be placed
on the touchpad. In the most common use-case this allows for a user to on the touchpad. In the most common use-case this allows for a user to
@ -122,12 +100,18 @@ the touchpad.
.. figure:: clickfinger-distance.svg .. figure:: clickfinger-distance.svg
:align: center :align: center
Illustration of the distance detection algorithm Illustration of the distance detection algorithm"
In the illustration above the red area marks the proximity area around the In the illustration above the red area marks the proximity area around the
first finger. Since the thumb is outside of that area libinput considers the first finger. Since the thumb is outside of that area libinput considers the
click a single-finger click rather than a two-finger click. click a single-finger click rather than a two-finger click.
Clickfinger configuration can be enabled through the
**libinput_device_config_click_set_method()** call. If clickfingers are
enabled on a touchpad with top software buttons, the top area will keep
acting as softbuttons for use with the trackpoint. Clickfingers will be used
everywhere else on the touchpad.
.. _special_clickpads: .. _special_clickpads:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------

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

@ -12,16 +12,15 @@
# add these directories to sys.path here. If the directory is relative to the # add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here. # documentation root, use os.path.abspath to make it absolute, like shown here.
# #
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.')) # sys.path.insert(0, os.path.abspath('.'))
import sys
import os
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
@ -42,7 +41,6 @@ release = '@PROJECT_VERSION@'
extensions = [ extensions = [
'sphinx.ext.mathjax', 'sphinx.ext.mathjax',
'sphinx.ext.graphviz', 'sphinx.ext.graphviz',
'sphinx.ext.extlinks',
] ]
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
@ -62,7 +60,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.
@ -167,27 +165,6 @@ texinfo_documents = [
from recommonmark.parser import CommonMarkParser from recommonmark.parser import CommonMarkParser
extlinks = { 'commit' : source_parsers = {
('https://gitlab.freedesktop.org/libinput/libinput/commit/%s', '.md': CommonMarkParser,
'git commit %s')
} }
# -- git version hack -------------------------------------------------
#
# meson doesn't take configuration_data() for vcs_tag, so we cannot replace
# two substrings in the same file.
#
# sphinx cannot do ..include:: without linebreaks, so in-line replacements
# are a no-go.
#
# Work around this by generating a mini python module in meson through
# vcs_tag, then use that to generate the replacements in rst_prolog.
import git_version
rst_prolog = """
.. |git_version| replace:: :commit:`{}`
.. |git_version_full| replace:: :commit:`{}`
""".format(git_version.get_git_version(),
git_version.get_git_version_full)

View file

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

View file

@ -1,21 +0,0 @@
.. warning:: The package lists are autogenerated from the `CI <https://gitlab.freedesktop.org/libinput/libinput/-/tree/master/.gitlab-ci.yml>`_.
- Fedora: ::
dnf install @FEDORA_PACKAGES@
- Ubuntu: ::
apt install @UBUNTU_PACKAGES@
- Debian: ::
apt install @DEBIAN_PACKAGES@
- Arch: ::
pacman -S @ARCH_PACKAGES@
- Alpine: ::
apk add @ALPINE_PACKAGES@

View file

@ -5,26 +5,22 @@ Information for developers
============================================================================== ==============================================================================
Below is a list of topics of interest to developers, divided into Below is a list of topics of interest to developers, divided into
information for those :ref:`using_libinput_as_library` in a Wayland compositor information for those **using** libinput as library in a Wayland compositor
or other project. The :ref:`hacking_on_libinput` section applies to developers working on or other project. The :ref:`hacking_on_libinput` section applies to developers working on
libinput itself. libinput itself.
.. note:: If you use or work on libinput you should get in touch with the
libinput developers on the wayland-devel@lists.freedesktop.org
mailing lists
.. _using_libinput_as_library: .. _using_libinput_as_library:
------------------------------------------------------------------------------ *************************
Using libinput as library Using libinput as library
------------------------------------------------------------------------------ *************************
See :ref:`building_against` for information on how to integrate libinput .. note:: If you use libinput you should get in touch with the libinput
with your project's build system. developers on the wayland-devel@lists.freedesktop.org mailing
lists
.. note:: **libinput's API documentation is available here:**
http://wayland.freedesktop.org/libinput/doc/latest/api/
The API documentation is available here:
http://wayland.freedesktop.org/libinput/doc/latest/api/
Topics below explain some behaviors of libinput. Topics below explain some behaviors of libinput.
@ -36,17 +32,17 @@ 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:
------------------------------------------------------------------------------ *******************
Hacking on libinput 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:
@ -115,8 +136,7 @@ Model-specific configuration
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
As of libinput 1.12, model-specific configuration is stored in the As of libinput 1.12, model-specific configuration is stored in the
:ref:`device-quirks` and not in the hwdb anymore. Please see :ref:`device-quirks` and not in the hwdb anymore. Please see @ref device-quirks for
:ref:`device-quirks` for
details. details.
.. _model_specific_configuration_x220fw81: .. _model_specific_configuration_x220fw81:
@ -129,7 +149,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.
@ -213,7 +233,7 @@ that update causes a hwdb change).
To update the binary file on-disk, run: :: To update the binary file on-disk, run: ::
sudo systemd-hwdb update sudo udevadm hwdb --update
Then, to trigger a reload of all properties on your device, run: :: Then, to trigger a reload of all properties on your device, run: ::
@ -226,11 +246,6 @@ in the udev rules files). ::
sudo udevadm test /sys/class/input/eventX sudo udevadm test /sys/class/input/eventX
.. warning:: ``udevadm test`` does not run commands specified in ``RUN``
directives. This affects the udev properties relying on e.g.
the udev keyboard builtin such as the :ref:`touchpad_jitter`
workarounds.
.. _hwdb_modifying: .. _hwdb_modifying:
.............................................................................. ..............................................................................
@ -242,4 +257,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.
@ -46,7 +46,7 @@ Installing temporary local device quirks
The model quirks are part of the source distribution and should never be The model quirks are part of the source distribution and should never be
modified. For temporary local workarounds, libinput reads the modified. For temporary local workarounds, libinput reads the
``/etc/libinput/local-overrides.quirks`` file. Users may add sections to ``/etc/libinput/local-overrides.quirks`` file. Users may add a sections to
this file to add a device quirk for a local device but beware that **any this file to add a device quirk for a local device but beware that **any
modification must be upstreamed** or it may cease to work at any time. modification must be upstreamed** or it may cease to work at any time.
@ -70,10 +70,10 @@ This tool takes an action as first argument, the most common invocation is
devices. :: devices. ::
$ libinput quirks list /dev/input/event19 $ libinput quirks list /dev/input/event19
Device has no quirks defined
$ libinput quirks list /dev/input/event0 $ libinput quirks list /dev/input/event0
AttrLidSwitchReliability=unreliable AttrLidSwitchReliability
The device `event19` does not have any quirks assigned.
When called with the ``--verbose`` argument, ``libinput quirks list`` prints When called with the ``--verbose`` argument, ``libinput quirks list`` prints
information about all files and its attempts to match the device: :: information about all files and its attempts to match the device: ::
@ -112,12 +112,12 @@ 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
|git_version|. commit @includedoc git-version.dox
.. 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.
No guarantee is given that any quirk below works on your version of No guarantee is given that any quirk below works on your version of
@ -132,14 +132,18 @@ general-purpose **Model*** flags are listed here.
ModelALPSTouchpad, ModelAppleTouchpad, ModelWacomTouchpad, ModelChromebook ModelALPSTouchpad, ModelAppleTouchpad, ModelWacomTouchpad, ModelChromebook
Reserved for touchpads made by the respective vendors Reserved for touchpads made by the respective vendors
ModelTabletNoTilt
Indicates that the tablet stylus does not provide tilt axis
information, even if the kernel exposes that axis.
ModelTabletNoProximityOut
Indicates that the tablet stylus does not send correct proximity out
events.
ModelTouchpadVisibleMarker ModelTouchpadVisibleMarker
Indicates the touchpad has a drawn-on visible marker between the software Indicates the touchpad has a drawn-on visible marker between the software
buttons. buttons.
ModelTabletModeNoSuspend ModelTabletModeNoSuspend
Indicates that the device does not need to be Indicates that the device does not need to be
suspended in :ref:`switches_tablet_mode`. suspended in :ref:`switches_tablet_mode`.
ModelTabletModeSwitchUnreliable
Indicates that this tablet mode switch's state cannot be relied upon.
ModelTrackball ModelTrackball
Reserved for trackballs Reserved for trackballs
ModelBouncingKeys ModelBouncingKeys
@ -147,21 +151,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 +161,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 +177,3 @@ 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;
Enables or disables the evdev event type/code tuples on the device. The prefix
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
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
Indicates the integration of the pointing stick. This is a string enum.
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,20 +0,0 @@
digraph stack
{
compound=true;
rankdir="LR";
node [
shape="box";
]
kernel [label="Kernel"];
libinput;
xserver [label="X Server"];
record [label="libinput record"];
kernel -> libinput
libinput -> xserver
kernel -> record;
record -> stdout
}

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,25 +5,25 @@ 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 @see device-quirks
to be useful. to be useful.
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
button-debouncing.rst button_debouncing.rst
clickpad-softbuttons.rst clickpad-softbuttons.rst
gestures.rst gestures.rst
middle-button-emulation.rst middle-button-emulation.rst
palm-detection.rst palm-detection.rst
touchpad-thumb-detection.rst
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-jitter.rst
touchpad-jumping-cursors.rst
touchpad-pressure.rst touchpad-pressure.rst
trackpoints.rst trackpoints.rst

View file

@ -4,26 +4,42 @@
Gestures Gestures
============================================================================== ==============================================================================
libinput supports :ref:`gestures_pinch` and :ref:`gestures_swipe` on most libinput supports basic gestures on touchpads and other indirect input
modern touchpads and other indirect touch devices. Note that libinput **does devices. Two types of gestures are supported: :ref:`gestures_pinch` and
not** support gestures on touchscreens, see :ref:`gestures_touchscreens`. @ref gestures_swipe. Support for gestures depends on the hardware device, most
touchpads support both gestures and any device that may send gesture events
has the **LIBINPUT_DEVICE_CAP_GESTURE** capability set.
Note that libinput **does not** support gestures on touchscreens, see
:ref:`gestures_touchscreens`.
.. _gestures_lifetime: .. _gestures_lifetime:
----------------------------------------------------------------------------- ------------------------------------------------------------------------------
Lifetime of a gesture Lifetime of a gesture
----------------------------------------------------------------------------- ------------------------------------------------------------------------------
A gesture starts when the finger position and/or finger motion is A gesture's lifetime has three distinct stages: begin, update and end, each
unambiguous as to what gesture to trigger and continues until the first with their own event types. Begin is sent when the fingers are first set
finger belonging to this gesture is lifted. down or libinput decides that the gesture begins. For :ref:`gestures_pinch`
this sets the initial scale. Any events changing properties of the gesture
are sent as update events. On termination of the gesture, an end event is
sent.
A single gesture cannot change the finger count. For example, if a user A gesture includes the finger count (see
puts down a fourth finger during a three-finger swipe gesture, libinput will **libinput_event_gesture_get_finger_count()**) and that finger count remains the
end (cancel) the three-finger gesture and, if applicable, start a same for the lifetime of a gesture. Thus, if a user puts down a fourth
four-finger swipe gesture. A caller may however decide that those gestures finger during a three-finger swipe gesture, libinput will end
are semantically identical and continue the two gestures as one single the three-finger gesture and, if applicable, start a four-finger swipe
gesture. gesture. A caller may decide that those gestures are semantically identical
and continue the two gestures as one single gesture.
**LIBINPUT_EVENT_GESTURE_PINCH_BEGIN**
**LIBINPUT_EVENT_GESTURE_PINCH_UPDATE**
**LIBINPUT_EVENT_GESTURE_PINCH_END**
**LIBINPUT_EVENT_GESTURE_PINCH_BEGIN**
**LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE**
**LIBINPUT_EVENT_GESTURE_SWIPE_END**
.. _gestures_pinch: .. _gestures_pinch:
@ -43,7 +59,7 @@ to the initial finger position.
.. figure:: pinch-gestures.svg .. figure:: pinch-gestures.svg
:align: center :align: center
The pinch and rotate gestures The pinch and rotate gestures"
The illustration above shows a basic pinch in the left image and a rotate in The illustration above shows a basic pinch in the left image and a rotate in
the right angle. Not shown is a movement of the logical center if the the right angle. Not shown is a movement of the logical center if the
@ -69,232 +85,11 @@ gesture into an action or limit a gesture to specific directions only.
.. figure:: swipe-gestures.svg .. figure:: swipe-gestures.svg
:align: center :align: center
The swipe gestures The swipe gestures"
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
current hold gesture is no longer active. This may also occur 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:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -312,13 +107,14 @@ screen as well as the context of those virtual objects:
.. figure:: touchscreen-gestures.svg .. figure:: touchscreen-gestures.svg
:align: center :align: center
Context-sensitivity of touchscreen gestures Context-sensitivity of touchscreen gestures"
In the above example, the finger movements are identical but in the left In this example, the finger movements are identical but in the left case
case both fingers are located within the same window, thus suggesting an both fingers are located within the same window, thus suggesting an attempt
attempt to zoom. In the right case both fingers are located on a window to zoom. In the right case both fingers are located on a window border,
border, thus suggesting a window movement. libinput has no knowledge of the thus suggesting a window movement. libinput only has knowledge of the finger
window coordinates and thus cannot differentiate the two. coordinates (and even then only in device coordinates, not in screen
coordinates) and thus cannot differentiate the two.
.. _gestures_softbuttons: .. _gestures_softbuttons:
@ -328,14 +124,14 @@ Gestures with enabled software buttons
If the touchpad device is a :ref:`Clickpad <touchpads_buttons_clickpads>`, it If the touchpad device is a :ref:`Clickpad <touchpads_buttons_clickpads>`, it
is recommended that a caller switches to :ref:`clickfinger`. is recommended that a caller switches to :ref:`clickfinger`.
Usually fingers placed in a :ref:`software button area <software_buttons>` Usually fingers placed in a :ref:`software button area <software_buttons>` is not
are not considered for gestures, resulting in some gestures to be considered for gestures, resulting in some gestures to be interpreted as
interpreted as pointer motion or two-finger scroll events. pointer motion or two-finger scroll events.
.. figure:: pinch-gestures-softbuttons.svg .. figure:: pinch-gestures-softbuttons.svg
:align: center :align: center
Interference of software buttons and pinch gestures Interference of software buttons and pinch gestures"
In the example above, the software button area is highlighted in red. The In the example above, the software button area is highlighted in red. The
user executes a three-finger pinch gesture, with the thumb remaining in the user executes a three-finger pinch gesture, with the thumb remaining in the
@ -359,13 +155,13 @@ Touchpoints are assigned in sequential order and only the first two touch
points are trackable. For libinput this produces an ambiguity where it is points are trackable. For libinput this produces an ambiguity where it is
impossible to detect whether a gesture is a pinch gesture or a swipe gesture impossible to detect whether a gesture is a pinch gesture or a swipe gesture
whenever a user puts the index and middle finger down first. Since the third whenever a user puts the index and middle finger down first. Since the third
finger does not have positional information, its location cannot be finger does not have positional information, it's location cannot be
determined. determined.
.. figure:: gesture-2fg-ambiguity.svg .. figure:: gesture-2fg-ambiguity.svg
:align: center :align: center
Ambiguity of three-finger gestures on two-finger touchpads Ambiguity of three-finger gestures on two-finger touchpads"
The image above illustrates this ambiguity. The index and middle finger are The image above illustrates this ambiguity. The index and middle finger are
set down first, the data stream from both finger positions looks identical. set down first, the data stream from both finger positions looks identical.

View file

@ -1,5 +0,0 @@
def get_git_version():
return "__GIT_VERSION__"[:7]
def get_git_version_full():
return "__GIT_VERSION__"

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.
@ -71,4 +68,5 @@ file for the full license information.
..... .....
About About
..... .....
Documentation generated from |git_version| Documentation generated from git commit
`__GIT_VERSION__ <https://gitlab.freedesktop.org/libinput/libinput/commit/__GIT_VERSION__>`_

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,104 +4,23 @@ 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('HTTP_DOC_LINK', doc_url)
git_version_page = vcs_tag(command : ['git', 'log', '-1', '--format=%H'],
fallback : 'unknown',
input : 'git_version.py.in',
output : 'git_version.py',
replace_string: '__GIT_VERSION__')
sphinx_conf_py = configure_file(input : 'conf.py.in', sphinx_conf_py = configure_file(input : 'conf.py.in',
output : 'conf.py', output : 'conf.py',
configuration : sphinx_config) configuration : sphinx_config,
install : false)
# 404 replacements for old URLs src_extra = [
# The switch to sphinx caused a few pages to be renamed, sphinx uses
# filename.html whereas doxygen used whatever the @page foo was. So old docs
# *mostly* used underscores, now we're consistent with dashes.
# We can't use htaccess on the server, so let's auto-generate a 404 list
# with a basic page telling users that the link has moved. This can be
# removed in a few months, towards the end of 2018.
#
# File list is: [current-sphinx-input-file, old-generated-page]
# If they're the same they'll be ignored.
src_404s = [
[ 'absolute-axes.rst', 'absolute_axes.html'],
[ 'absolute-coordinate-ranges.rst', 'absolute_coordinate_ranges.html'],
[ 'architecture.rst', 'architecture.html'],
[ 'building.rst', 'building_libinput.html'],
[ 'button-debouncing.rst', 'button_debouncing.html'],
[ 'clickpad-softbuttons.rst', 'clickpad_softbuttons.html'],
[ 'configuration.rst', 'config_options.html'],
[ 'contributing.rst', 'contributing.html'],
[ 'development.rst', 'development.html'],
[ 'device-configuration-via-udev.rst', 'udev_config.html'],
[ 'device-quirks.rst', 'device-quirks.html'],
[ 'faqs.rst', 'faq.html'],
[ 'features.rst', 'features.html'],
[ 'gestures.rst', 'gestures.html'],
[ 'incorrectly-enabled-hires.rst', 'incorrectly-enabled-hires.html'],
[ 'middle-button-emulation.rst', 'middle_button_emulation.html'],
[ 'normalization-of-relative-motion.rst', 'motion_normalization.html'],
[ 'palm-detection.rst', 'palm_detection.html'],
[ 'pointer-acceleration.rst', 'pointer-acceleration.html'],
[ 'reporting-bugs.rst', 'reporting_bugs.html'],
[ 'scrolling.rst', 'scrolling.html'],
[ 'seats.rst', 'seats.html'],
[ 'switches.rst', 'switches.html'],
[ 't440-support.rst', 't440_support.html'],
[ 'tablet-support.rst', 'tablet-support.html'],
[ 'tapping.rst', 'tapping.html'],
[ 'test-suite.rst', 'test-suite.html'],
[ 'timestamps.rst', 'timestamps.html'],
[ 'tools.rst', 'tools.html'],
[ 'touchpad-jitter.rst', 'touchpad_jitter.html'],
[ 'touchpad-jumping-cursors.rst', 'touchpad_jumping_cursor.html'],
[ 'touchpad-pressure.rst', 'touchpad_pressure.html'],
[ 'touchpads.rst', 'touchpads.html'],
[ 'trackpoints.rst', 'trackpoints.html'],
[ 'troubleshooting.rst', 'troubleshooting.html'],
[ 'what-is-libinput.rst', 'what_is_libinput.html'],
]
dst_404s = []
foreach s404 : src_404s
target = s404[0]
oldpage = s404[1]
tname = target.split('.rst')[0]
oname = oldpage.split('.html')[0]
if tname != oname
config_404 = configuration_data()
config_404.set('TARGET', '@0@.html'.format(tname))
c = configure_file(input : '404.rst',
output : '@0@.rst'.format(oname),
configuration : config_404)
dst_404s += [c]
endif
endforeach
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/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,21 +31,14 @@ 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',
'svg/ptraccel-trackpoint.svg', 'svg/ptraccel-trackpoint.svg',
'svg/software-buttons.svg', 'svg/software-buttons.svg',
'svg/software-buttons-conditions.svg',
'svg/software-buttons-thumbpress.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',
@ -138,26 +50,23 @@ src_rst = files(
'svg/touchscreen-gestures.svg', 'svg/touchscreen-gestures.svg',
'svg/trackpoint-delta-illustration.svg', 'svg/trackpoint-delta-illustration.svg',
'svg/twofinger-scrolling.svg', 'svg/twofinger-scrolling.svg',
# rst files ]
src_rst = files(
'absolute-axes.rst', 'absolute-axes.rst',
'absolute-coordinate-ranges.rst', 'absolute-coordinate-ranges.rst',
'architecture.rst', 'architecture.rst',
'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',
'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',
@ -168,57 +77,38 @@ src_rst = files(
'tapping.rst', 'tapping.rst',
'test-suite.rst', 'test-suite.rst',
'timestamps.rst', 'timestamps.rst',
'tablet-debugging.rst',
'tools.rst', 'tools.rst',
'touchpad-jumping-cursors.rst', 'touchpad-jumping-cursors.rst',
'touchpad-pressure.rst', 'touchpad-pressure.rst',
'touchpad-pressure-debugging.rst',
'touchpad-jitter.rst', 'touchpad-jitter.rst',
'touchpad-thumb-detection.rst',
'touchpads.rst', 'touchpads.rst',
'trackpoints.rst', 'trackpoints.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',
) )
src_sphinx = [] src_sphinx = custom_target('sphinx-sources',
foreach f : src_rst input : [src_rst, src_extra],
sf = configure_file(input: f, output : '.',
output: '@PLAINNAME@', command : [prg_install, '-t', '@OUTDIR@', '@INPUT@'],
copy : true) build_by_default: true)
src_sphinx += [ sf ]
endforeach
configure_file(input: 'index.rst', index_page = vcs_tag(command : ['git', 'log', '-1', '--format=%h'],
output: 'index.rst', fallback : 'unknown',
configuration: sphinx_config) input : 'index.rst',
output : 'index.rst',
dependencies_config = configuration_data() replace_string: '__GIT_VERSION__')
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)
# drop '-a' once we are happy with all this
# do not use -j, it breaks on Ubuntu # do not use -j, it breaks on Ubuntu
sphinx_output_dir = 'Documentation' sphinx_output_dir = 'Documentation'
custom_target('sphinx', custom_target('sphinx',
input : [ sphinx_conf_py, git_version_page ] + src_sphinx + dst_404s, input : [ sphinx_conf_py, index_page ] + src_rst + src_extra,
output : [ sphinx_output_dir ], output : [ sphinx_output_dir ],
command : [ sphinx, '-q', '-b', 'html', command : [ sphinx, '-q', '-b', 'html', '-a',
'-d', meson.current_build_dir() / 'doctrees',
meson.current_build_dir(), sphinx_output_dir], meson.current_build_dir(), sphinx_output_dir],
depends: [ src_sphinx ],
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

@ -0,0 +1,84 @@
.. _misc:
==============================================================================
Users
==============================================================================
- @subpage what_is_libinput
- @subpage faq
- @subpage tools
- @subpage reporting_bugs
.. _touchpads:
==============================================================================
Touchpads
==============================================================================
- @subpage scrolling
- @subpage clickpad_softbuttons
- @subpage tapping
- @subpage gestures
- @subpage touchpad_pressure
- @subpage palm_detection
- @subpage t440_support
- @subpage touchpad_jumping_cursor
- @subpage absolute_coordinate_ranges
- @subpage touchpad_jitter
.. _touchscreens:
==============================================================================
Touchscreens
==============================================================================
- @subpage absolute_axes
.. _pointers:
==============================================================================
Mice, Trackballs, etc.
==============================================================================
- @subpage motion_normalization
- @subpage middle_button_emulation
- @subpage button_debouncing
- @subpage trackpoints
.. _tablets:
==============================================================================
Graphics Tablets
==============================================================================
- @subpage tablet-support
.. _other_devices:
==============================================================================
Other devices
==============================================================================
- @subpage switches
.. _developers:
==============================================================================
Developers
==============================================================================
Contributions to libinput are always welcome. See the links below for
specific documentation.
- @subpage what_is_libinput
- @subpage contributing
- @subpage architecture
- @subpage building_libinput
- @subpage test-suite
- @subpage tools
- @subpage pointer-acceleration
- @subpage device-quirks
- @subpage udev_config
- @subpage seats
- @subpage timestamps

View file

@ -14,7 +14,7 @@ touch the bottom edges of the touchpad during normal interaction.
Interference from a palm depends on the size of the touchpad and the position Interference from a palm depends on the size of the touchpad and the position
of the user's hand. Data from touchpads showed that almost all palm events of the user's hand. Data from touchpads showed that almost all palm events
during typing on a Lenovo T440 happened in the left-most and right-most 5% of during tying on a Lenovo T440 happened in the left-most and right-most 5% of
the touchpad. The T440 series has one of the largest touchpads, other the touchpad. The T440 series has one of the largest touchpads, other
touchpads are less affected by palm touches. touchpads are less affected by palm touches.
@ -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
@ -52,7 +51,7 @@ Palm detection based on pressure
The simplest form of palm detection labels a touch as palm when the pressure The simplest form of palm detection labels a touch as palm when the pressure
value goes above a certain threshold. This threshold is usually high enough value goes above a certain threshold. This threshold is usually high enough
that it cannot be triggered by a finger movement. Once a touch is labelled as that it cannot be triggered by a finger movement. One a touch is labelled as
palm based on pressure, it will remain so even if the pressure drops below palm based on pressure, it will remain so even if the pressure drops below
the threshold again. This ensures that a palm remains a palm even when the the threshold again. This ensures that a palm remains a palm even when the
pressure changes as the user is typing. pressure changes as the user is typing.
@ -66,7 +65,7 @@ pressure ranges, see :ref:`touchpad_pressure`.
Palm detection based on touch size Palm detection based on touch size
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
On touchpads that support the ``ABS_MT_TOUCH_MAJOR`` axes, libinput can perform On touchads that support the ``ABS_MT_TOUCH_MAJOR`` axes, libinput can perform
palm detection based on the size of the touch ellipse. This works similar to palm detection based on the size of the touch ellipse. This works similar to
the pressure-based palm detection in that a touch is labelled as palm when the pressure-based palm detection in that a touch is labelled as palm when
it exceeds the (device-specific) touch size threshold. it exceeds the (device-specific) touch size threshold.
@ -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,11 +103,12 @@ 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 @image html palm-detection.svg
:align: center
.. _trackpoint-disabling: .. _trackpoint-disabling:
@ -155,29 +156,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:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -187,7 +169,7 @@ Stylus-touch arbitration
A special case of palm detection is touch arbitration on devices that A special case of palm detection is touch arbitration on devices that
support styli. When interacting with a stylus on the screen, parts of the support styli. When interacting with a stylus on the screen, parts of the
hand may touch the surface and trigger touches. As the user is currently hand may touch the surface and trigger touches. As the user is currently
interacting with the stylus, these touches would interfere with the correct interacting with the stylus, these touches would interfer with the correct
working of the stylus. working of the stylus.
libinput employs a method similar to :ref:`disable-while-typing` to detect libinput employs a method similar to :ref:`disable-while-typing` to detect
@ -209,7 +191,7 @@ libinput uses two triggers for thumb detection: pressure and
location. A touch exceeding a pressure threshold is considered a thumb if it location. A touch exceeding a pressure threshold is considered a thumb if it
is within the thumb detection zone. is within the thumb detection zone.
.. note:: "Pressure" on touchpads is synonymous with "contact area." A large touch .. note:: "Pressure" on touchpads is synonymous with "contact area", a large touch
surface area has a higher pressure and thus hints at a thumb or palm surface area has a higher pressure and thus hints at a thumb or palm
touching the surface. touching the surface.
@ -218,8 +200,7 @@ thumb hanging mostly off the touchpad will have a small surface area.
libinput has a definitive thumb zone where any touch is considered a resting libinput has a definitive thumb zone where any touch is considered a resting
thumb. thumb.
.. figure:: thumb-detection.svg @image html thumb-detection.svg
:align: center
The picture above shows the two detection areas. In the larger (light red) The picture above shows the two detection areas. In the larger (light red)
area, a touch is labelled as thumb when it exceeds a device-specific area, a touch is labelled as thumb when it exceeds a device-specific

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:
@ -39,7 +33,7 @@ Velocity calculation
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
The device's speed of movement is measured across multiple input events The device's speed of movement is measured across multiple input events
through so-called "trackers". Each event prepends a tracker item, each through so-called "trackers". Each event prepends a the tracker item, each
subsequent tracker contains the delta of that item to the current position, subsequent tracker contains the delta of that item to the current position,
the timestamp of the event that created it and the cardinal direction of the the timestamp of the event that created it and the cardinal direction of the
movement at the time. If a device moves into the same direction, the movement at the time. If a device moves into the same direction, the
@ -97,7 +91,7 @@ and after :ref:`motion_normalization` is applied.
.. figure:: ptraccel-linear.svg .. figure:: ptraccel-linear.svg
:align: center :align: center
Linear pointer acceleration Linear pointer acceleration"
The image above shows the linear pointer acceleration settings at various The image above shows the linear pointer acceleration settings at various
speeds. The line for 0.0 is the default acceleration curve, speed settings speeds. The line for 0.0 is the default acceleration curve, speed settings
@ -123,7 +117,7 @@ coordinates (see :ref:`motion_normalization`).
.. figure:: ptraccel-low-dpi.svg .. figure:: ptraccel-low-dpi.svg
:align: center :align: center
Pointer acceleration for low-dpi devices Pointer acceleration for low-dpi devices"
The image above shows the default pointer acceleration curve for a speed of The image above shows the default pointer acceleration curve for a speed of
0.0 at different DPI settings. A device with low DPI has the acceleration 0.0 at different DPI settings. A device with low DPI has the acceleration
@ -144,7 +138,7 @@ deceleration factor.
.. figure:: ptraccel-touchpad.svg .. figure:: ptraccel-touchpad.svg
:align: center :align: center
Pointer acceleration curve for touchpads Pointer acceleration curve for touchpads"
The image above shows the touchpad acceleration profile in comparison to the The image above shows the touchpad acceleration profile in comparison to the
:ref:`ptraccel-linear`. The shape of the curve is identical but vertically squashed. :ref:`ptraccel-linear`. The shape of the curve is identical but vertically squashed.
@ -172,12 +166,12 @@ 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
Pointer acceleration curves for trackpoints Pointer acceleration curves for trackpoints"
The image above shows the trackpoint acceleration profile for the speed in The image above shows the trackpoint acceleration profile for the speed in
units/ms. units/ms.
@ -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

@ -7,14 +7,15 @@ Reporting bugs
A new bug can be filed here: A new bug can be filed here:
https://gitlab.freedesktop.org/libinput/libinput/issues/new https://gitlab.freedesktop.org/libinput/libinput/issues/new
.. hint:: libinput has lots of users but very few developers. It is in your .. note:: libinput has lots of users but very few developers. It is in your own
own interest to follow the steps here precisely to ensure your bug can be interested to follow these steps precisely to ensure your bug can be
dealt with efficiently. dealt with efficiently.
When reporting bugs against libinput, you will need: When reporting bugs against libinput, please follow the instructions below
and provide the required data. You will need:
- a reliable :ref:`reproducer <reporting_bugs_reproducer>` for the bug - a reliable :ref:`reproducer <reporting_bugs_reproducer>` for the bug
- a :ref:`recording <libinput-record>` of the device while the bug is reproduced - an :ref:`evemu recording <evemu>` of the device while the bug is reproduced
- device-specific information, see - device-specific information, see
- :ref:`reporting_bugs_touchpad` - :ref:`reporting_bugs_touchpad`
@ -35,8 +36,8 @@ Stay technical, on-topic, and keep the description concise.
Obtaining the libinput version Obtaining the libinput version
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
If your libinput version is older than the current stable branch, please try If your libinput version is older than the current stable branch, you will
the latest version. If you run a distribution-provided get asked to try the latest version. If you run a distribution-provided
libinput, use the package manager to get the **full** package name and libinput, use the package manager to get the **full** package name and
version of libinput, e.g. version of libinput, e.g.
@ -64,16 +65,12 @@ 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`
man page. Use the ``--verbose`` flag to get more information about how "libinput-debug-events" man page. Use the ``--verbose`` flag to get more
libinput processes events. information about how libinput processes events.
If the bug cannot be reproduced with the :ref:`libinput-debug-events` helper, If the bug cannot be reproduced with the :ref:`libinput-debug-events` helper,
even with the correct configuration options set, it is likely not a bug in even with the correct configuration options set, it is likely not a bug in
@ -108,13 +105,13 @@ Reporting touchpad bugs
When you file a bug, please attach the following information: When you file a bug, please attach the following information:
- a virtual description of your input device, see :ref:`libinput-record`. - a virtual description of your input device, see :ref:`evemu`. This is the
This is the most important piece of information, do not forget it! most important piece of information, do not forget it!
- 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-detectior`` 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:
@ -132,8 +129,8 @@ Reporting mouse bugs
When you file a bug, please attach the following information: When you file a bug, please attach the following information:
- a virtual description of your input device, see :ref:`libinput-record`. - a virtual description of your input device, see :ref:`evemu`. This is the
This is the most important piece of information, do not forget it! 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`.
@ -155,8 +152,8 @@ the issue is.
When you file a bug, please attach the following information: When you file a bug, please attach the following information:
- a virtual description of your input device, see :ref:`libinput-record`. - a virtual description of your input device, see :ref:`evemu`. This is the
This is the most important piece of information, do not forget it! most important piece of information, do not forget it!
.. _reporting_bugs_trackpoint: .. _reporting_bugs_trackpoint:
@ -166,11 +163,12 @@ Reporting trackpoint bugs
When you file a bug, please attach the following information: When you file a bug, please attach the following information:
- a virtual description of your input device, see :ref:`libinput-record`. - a virtual description of your input device, see :ref:`evemu`. This is the
This is the most important piece of information, do not forget it! 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
@ -183,9 +181,9 @@ All other devices
When you file a bug, please attach the following information: When you file a bug, please attach the following information:
- a virtual description of your input device, see :ref:`libinput-record`. - a virtual description of your input device, see :ref:`evemu`. This is the
This is the most important piece of information, do not forget it! most important piece of information, do not forget it!
- the vendor model number of the device (e.g. "Sony PlayStation3 controller") - the vendor model number of the device (e.g. "Sony Plastation3 controller")
.. _udev_info: .. _udev_info:
@ -223,15 +221,15 @@ node for your device. An example output is below: ::
Recording devices with evemu Recording devices with evemu
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
.. warning:: Where available, the :ref:`libinput-record` tools should be used instead .. note:: Where available, the :ref:`libinput-record` tools should be used instead
of evemu of evemu
`evemu-record <https://www.freedesktop.org/wiki/Evemu/>`_ records the `evemu-record <https://www.freedesktop.org/wiki/Evemu/>`_ records the
device capabilities together with the event stream from the kernel. On our device capabilities together with the event stream from the kernel. On our
side, this allows us to recreate a virtual device identical to your device side, this allows us to recreate a virtual device identical to your device
and re-play the event sequence, hopefully triggering the same bug. and re-play the event sequence, hopefully triggering the same bug.
evemu-record takes a ``/dev/input/eventX`` event node, but without arguments evemu-record takes a <tt>/dev/input/eventX</tt> event node, but without arguments
it will simply show the list of devices and let you select: :: it will simply show the list of devices and let you select: ::
$ sudo evemu-record > scroll.evemu $ sudo evemu-record > scroll.evemu
@ -277,10 +275,10 @@ device. For example, to replay the sequence recorded in the example above: ::
If the bug is triggered by replaying on your device, attach the recording to If the bug is triggered by replaying on your device, attach the recording to
the bug report. the bug report.
libinput does not affect the evemu recording. libinput and evemu talk .. note:: libinput does not affect the evemu recording. libinput and evemu talk
directly to the kernel's device nodes. An evemu recording is not directly to the kernel's device nodes. An evemu recording is not
influenced by the libinput version or whether a libinput context is influenced by the libinput version or whether a libinput context is
currently active. currently active.
.. graphviz:: evemu.gv .. graphviz:: evemu.gv
@ -291,7 +289,7 @@ My bug was closed as fixed, what now?
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
libinput's policy on closing bugs is: once the fix for a given bug is on git libinput's policy on closing bugs is: once the fix for a given bug is on git
master, the bug is considered fixed and the gitlab issue will be closed master, the bug is considered fixed and the bugzilla entry will be closed
accordingly. accordingly.
Of course, unless you actually run git master, the bug will continue to Of course, unless you actually run git master, the bug will continue to
@ -304,7 +302,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.
@ -318,7 +316,7 @@ Your distribution may pick a patch up immediately and ship the fix
even before the next stable branch update is released. For example, Fedora even before the next stable branch update is released. For example, Fedora
does this frequently. does this frequently.
.. hint:: If a bug needs to be fixed urgently, file a bug in your .. note:: If a bug needs to be fixed urgently, file a bug in your
distribution's bug tracker. distribution's bug tracker.
Patches on git master will end up in the next libinput release. Once your Patches on git master will end up in the next libinput release. Once your
@ -345,51 +343,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 need 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 burden on the maintainers.
These tags are high-level categories only, always look for the comments in
the issue to get further details.

View file

@ -5,14 +5,14 @@ Scrolling
============================================================================== ==============================================================================
libinput supports three different types of scrolling methods: libinput supports three different types of scrolling methods:
:ref:`twofinger_scrolling`, :ref:`edge_scrolling` and :ref:`twofinger_scrolling`, @ref edge_scrolling and @ref button_scrolling. Some
:ref:`button_scrolling`. Some devices support multiple methods, though only devices support multiple methods, though only one can be enabled at a time.
one can be enabled at a time. As a general overview: As a general overview:
- touchpad devices with physical buttons below the touchpad support edge and - touchpad devices with physical buttons below the touchpad support edge and
two-finger scrolling two-finger scrolling
- touchpad devices without physical buttons (:ref:`ClickPads <clickpad_softbuttons>`) - touchpad devices without physical buttons (:ref:`clickpad_softbuttons`
support two-finger scrolling only "clickpads") support two-finger scrolling only
- pointing sticks provide on-button scrolling by default - pointing sticks provide on-button scrolling by default
- mice and other pointing devices support on-button scrolling but it is not - mice and other pointing devices support on-button scrolling but it is not
enabled by default enabled by default
@ -50,19 +50,15 @@ vertically or horizontally.
.. figure:: twofinger-scrolling.svg .. figure:: twofinger-scrolling.svg
:align: center :align: center
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.
When a scroll gesture remains close to perfectly straight, it will be held to
exact 90-degree angles; but if the gesture moves diagonally, it is free to
scroll in any direction.
Two-finger scrolling requires the touchpad to track both touch points with Two-finger scrolling requires the touchpad to track both touch points with
reasonable precision. Unfortunately, some so-called "semi-mt" touchpads can reasonable precision. Unfortunately, some so-called "semi-mt" touchpads can
only track the bounding box of the two fingers rather than the actual only track the bounding box of the two fingers rather than the actual
@ -83,7 +79,7 @@ scroll).
.. figure:: edge-scrolling.svg .. figure:: edge-scrolling.svg
:align: center :align: center
Vertical and horizontal edge scrolling Vertical and horizontal edge scrolling"
Due to the layout of the edges, diagonal scrolling is not possible. The Due to the layout of the edges, diagonal scrolling is not possible. The
behavior of edge scrolling using both edges at the same time is undefined. behavior of edge scrolling using both edges at the same time is undefined.
@ -109,7 +105,7 @@ scroll events when the trackstick's middle mouse button is held down.
.. figure:: button-scrolling.svg .. figure:: button-scrolling.svg
:align: center :align: center
Button scrolling Button scrolling"
The button may be changed with The button may be changed with
**libinput_device_config_scroll_set_button()** but must be on the same device as **libinput_device_config_scroll_set_button()** but must be on the same device as
@ -117,28 +113,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 +136,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.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

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

@ -77,28 +77,23 @@
</g> </g>
</g> </g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M159.2,422.4 L159.2,413.4 M159.2,16.7 L159.2,25.7 '/> <g transform="translate(159.2,444.3)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="middle"> <path stroke='black' d='M185.2,422.4 L185.2,413.4 M185.2,16.7 L185.2,25.7 '/> <g transform="translate(185.2,444.3)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="middle">
<text><tspan font-family="Arial" > 0.2</tspan></text> <text><tspan font-family="Arial" > 5</tspan></text>
</g> </g>
</g> </g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M263.2,422.4 L263.2,413.4 M263.2,16.7 L263.2,25.7 '/> <g transform="translate(263.2,444.3)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="middle"> <path stroke='black' d='M315.2,422.4 L315.2,413.4 M315.2,16.7 L315.2,25.7 '/> <g transform="translate(315.2,444.3)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="middle">
<text><tspan font-family="Arial" > 0.4</tspan></text> <text><tspan font-family="Arial" > 10</tspan></text>
</g> </g>
</g> </g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M367.1,422.4 L367.1,413.4 M367.1,16.7 L367.1,25.7 '/> <g transform="translate(367.1,444.3)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="middle"> <path stroke='black' d='M445.1,422.4 L445.1,413.4 M445.1,16.7 L445.1,25.7 '/> <g transform="translate(445.1,444.3)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="middle">
<text><tspan font-family="Arial" > 0.6</tspan></text> <text><tspan font-family="Arial" > 15</tspan></text>
</g>
</g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M471.1,422.4 L471.1,413.4 M471.1,16.7 L471.1,25.7 '/> <g transform="translate(471.1,444.3)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="middle">
<text><tspan font-family="Arial" > 0.8</tspan></text>
</g> </g>
</g> </g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='black' d='M575.0,422.4 L575.0,413.4 M575.0,16.7 L575.0,25.7 '/> <g transform="translate(575.0,444.3)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="middle"> <path stroke='black' d='M575.0,422.4 L575.0,413.4 M575.0,16.7 L575.0,25.7 '/> <g transform="translate(575.0,444.3)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="middle">
<text><tspan font-family="Arial" > 1</tspan></text> <text><tspan font-family="Arial" > 20</tspan></text>
</g> </g>
</g> </g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
@ -112,7 +107,7 @@
</g> </g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<g transform="translate(315.1,471.3)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="middle"> <g transform="translate(315.1,471.3)" stroke="none" fill="black" font-family="Arial" font-size="12.00" text-anchor="middle">
<text><tspan font-family="Arial" >delta (units/ms)</tspan></text> <text><tspan font-family="Arial" >delta (units)</tspan></text>
</g> </g>
</g> </g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
@ -124,10 +119,19 @@
</g> </g>
</g> </g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='rgb(148, 0, 211)' d='M516.2,34.7 L558.4,34.7 M55.3,421.2 L75.8,420.3 L96.2,419.2 L116.7,418.0 L137.1,416.9 L157.6,415.8 <path stroke='rgb(148, 0, 211)' d='M516.2,34.7 L558.4,34.7 M55.3,422.4 L60.5,418.5 L65.7,414.6 L70.9,410.7 L76.1,406.8 L81.3,402.9
L178.1,414.7 L198.5,413.7 L219.0,412.8 L239.4,411.8 L259.9,410.9 L280.4,410.1 L300.8,409.3 L321.3,408.5 L86.5,399.0 L91.7,395.1 L96.9,391.2 L102.1,387.3 L107.3,383.5 L112.5,379.6 L117.7,375.7 L122.9,371.8
L341.7,407.8 L362.2,407.1 L382.7,406.4 L403.1,405.8 L423.6,405.2 L444.1,404.6 L464.5,404.1 L485.0,403.5 L128.1,367.9 L133.3,364.0 L138.5,360.1 L143.6,356.2 L148.8,352.3 L154.0,348.4 L159.2,344.5 L164.4,340.6
L505.4,403.0 L525.9,402.6 L546.4,402.1 L566.8,401.7 L575.0,401.5 '/></g> L169.6,336.7 L174.8,332.8 L180.0,328.9 L185.2,325.0 L190.4,321.1 L195.6,317.2 L200.8,313.3 L206.0,310.0
L211.2,310.0 L216.4,310.0 L221.6,310.0 L226.8,310.0 L232.0,310.0 L237.2,310.0 L242.4,310.0 L247.6,310.0
L252.8,310.0 L258.0,310.0 L263.2,310.0 L268.4,310.0 L273.6,310.0 L278.8,310.0 L284.0,310.0 L289.2,310.0
L294.4,310.0 L299.6,310.0 L304.8,310.0 L310.0,310.0 L315.2,310.0 L320.3,310.0 L325.5,310.0 L330.7,310.0
L335.9,310.0 L341.1,310.0 L346.3,310.0 L351.5,310.0 L356.7,310.0 L361.9,310.0 L367.1,310.0 L372.3,310.0
L377.5,310.0 L382.7,310.0 L387.9,310.0 L393.1,310.0 L398.3,310.0 L403.5,310.0 L408.7,310.0 L413.9,310.0
L419.1,310.0 L424.3,310.0 L429.5,310.0 L434.7,310.0 L439.9,310.0 L445.1,310.0 L450.3,310.0 L455.5,310.0
L460.7,310.0 L465.9,310.0 L471.1,310.0 L476.3,310.0 L481.5,310.0 L486.7,310.0 L491.8,310.0 L497.0,310.0
L502.2,310.0 L507.4,310.0 L512.6,310.0 L517.8,310.0 L523.0,310.0 L528.2,310.0 L533.4,310.0 L538.6,310.0
L543.8,310.0 L549.0,310.0 L554.2,310.0 L559.4,310.0 L564.6,310.0 L569.8,310.0 L575.0,310.0 '/></g>
</g> </g>
<g id="gnuplot_plot_2" ><title>-0.75</title> <g id="gnuplot_plot_2" ><title>-0.75</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
@ -136,10 +140,19 @@
</g> </g>
</g> </g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='rgb( 0, 158, 115)' d='M516.2,52.7 L558.4,52.7 M55.3,420.4 L75.8,418.7 L96.2,416.7 L116.7,414.8 L137.1,412.8 L157.6,410.9 <path stroke='rgb( 0, 158, 115)' d='M516.2,52.7 L558.4,52.7 M55.3,422.4 L60.5,415.3 L65.7,408.1 L70.9,401.0 L76.1,393.8 L81.3,386.7
L178.1,409.1 L198.5,407.3 L219.0,405.6 L239.4,404.0 L259.9,402.4 L280.4,401.0 L300.8,399.6 L321.3,398.2 L86.5,379.6 L91.7,372.4 L96.9,365.3 L102.1,358.1 L107.3,351.0 L112.5,343.9 L117.7,336.7 L122.9,329.6
L341.7,397.0 L362.2,395.8 L382.7,394.6 L403.1,393.5 L423.6,392.5 L444.1,391.4 L464.5,390.5 L485.0,389.6 L128.1,322.4 L133.3,315.3 L138.5,308.2 L143.6,301.0 L148.8,293.9 L154.0,286.7 L159.2,279.6 L164.4,272.5
L505.4,388.7 L525.9,387.8 L546.4,387.0 L566.8,386.3 L575.0,386.0 '/></g> L169.6,270.7 L174.8,270.7 L180.0,270.7 L185.2,270.7 L190.4,270.7 L195.6,270.7 L200.8,270.7 L206.0,270.7
L211.2,270.7 L216.4,270.7 L221.6,270.7 L226.8,270.7 L232.0,270.7 L237.2,270.7 L242.4,270.7 L247.6,270.7
L252.8,270.7 L258.0,270.7 L263.2,270.7 L268.4,270.7 L273.6,270.7 L278.8,270.7 L284.0,270.7 L289.2,270.7
L294.4,270.7 L299.6,270.7 L304.8,270.7 L310.0,270.7 L315.2,270.7 L320.3,270.7 L325.5,270.7 L330.7,270.7
L335.9,270.7 L341.1,270.7 L346.3,270.7 L351.5,270.7 L356.7,270.7 L361.9,270.7 L367.1,270.7 L372.3,270.7
L377.5,270.7 L382.7,270.7 L387.9,270.7 L393.1,270.7 L398.3,270.7 L403.5,270.7 L408.7,270.7 L413.9,270.7
L419.1,270.7 L424.3,270.7 L429.5,270.7 L434.7,270.7 L439.9,270.7 L445.1,270.7 L450.3,270.7 L455.5,270.7
L460.7,270.7 L465.9,270.7 L471.1,270.7 L476.3,270.7 L481.5,270.7 L486.7,270.7 L491.8,270.7 L497.0,270.7
L502.2,270.7 L507.4,270.7 L512.6,270.7 L517.8,270.7 L523.0,270.7 L528.2,270.7 L533.4,270.7 L538.6,270.7
L543.8,270.7 L549.0,270.7 L554.2,270.7 L559.4,270.7 L564.6,270.7 L569.8,270.7 L575.0,270.7 '/></g>
</g> </g>
<g id="gnuplot_plot_3" ><title>-0.5</title> <g id="gnuplot_plot_3" ><title>-0.5</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
@ -148,10 +161,19 @@
</g> </g>
</g> </g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='rgb( 86, 180, 233)' d='M516.2,70.7 L558.4,70.7 M55.3,416.8 L75.8,412.1 L96.2,406.6 L116.7,401.1 L137.1,395.6 L157.6,390.3 <path stroke='rgb( 86, 180, 233)' d='M516.2,70.7 L558.4,70.7 M55.3,422.4 L60.5,412.0 L65.7,401.6 L70.9,391.2 L76.1,380.9 L81.3,370.5
L178.1,385.2 L198.5,380.3 L219.0,375.6 L239.4,371.1 L259.9,366.8 L280.4,362.7 L300.8,358.8 L321.3,355.1 L86.5,360.1 L91.7,349.7 L96.9,339.3 L102.1,328.9 L107.3,318.5 L112.5,308.2 L117.7,297.8 L122.9,287.4
L341.7,351.6 L362.2,348.2 L382.7,345.0 L403.1,341.9 L423.6,338.9 L444.1,336.1 L464.5,333.5 L485.0,330.9 L128.1,277.0 L133.3,266.6 L138.5,256.2 L143.6,245.8 L148.8,235.5 L154.0,225.1 L159.2,217.6 L164.4,217.6
L505.4,328.5 L525.9,326.1 L546.4,323.9 L566.8,321.7 L575.0,320.9 '/></g> L169.6,217.6 L174.8,217.6 L180.0,217.6 L185.2,217.6 L190.4,217.6 L195.6,217.6 L200.8,217.6 L206.0,217.6
L211.2,217.6 L216.4,217.6 L221.6,217.6 L226.8,217.6 L232.0,217.6 L237.2,217.6 L242.4,217.6 L247.6,217.6
L252.8,217.6 L258.0,217.6 L263.2,217.6 L268.4,217.6 L273.6,217.6 L278.8,217.6 L284.0,217.6 L289.2,217.6
L294.4,217.6 L299.6,217.6 L304.8,217.6 L310.0,217.6 L315.2,217.6 L320.3,217.6 L325.5,217.6 L330.7,217.6
L335.9,217.6 L341.1,217.6 L346.3,217.6 L351.5,217.6 L356.7,217.6 L361.9,217.6 L367.1,217.6 L372.3,217.6
L377.5,217.6 L382.7,217.6 L387.9,217.6 L393.1,217.6 L398.3,217.6 L403.5,217.6 L408.7,217.6 L413.9,217.6
L419.1,217.6 L424.3,217.6 L429.5,217.6 L434.7,217.6 L439.9,217.6 L445.1,217.6 L450.3,217.6 L455.5,217.6
L460.7,217.6 L465.9,217.6 L471.1,217.6 L476.3,217.6 L481.5,217.6 L486.7,217.6 L491.8,217.6 L497.0,217.6
L502.2,217.6 L507.4,217.6 L512.6,217.6 L517.8,217.6 L523.0,217.6 L528.2,217.6 L533.4,217.6 L538.6,217.6
L543.8,217.6 L549.0,217.6 L554.2,217.6 L559.4,217.6 L564.6,217.6 L569.8,217.6 L575.0,217.6 '/></g>
</g> </g>
<g id="gnuplot_plot_4" ><title>-0.25</title> <g id="gnuplot_plot_4" ><title>-0.25</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
@ -160,10 +182,19 @@
</g> </g>
</g> </g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='rgb(230, 159, 0)' d='M516.2,88.7 L558.4,88.7 M55.3,409.5 L75.8,398.8 L96.2,386.3 L116.7,373.7 L137.1,361.2 L157.6,349.1 <path stroke='rgb(230, 159, 0)' d='M516.2,88.7 L558.4,88.7 M55.3,422.4 L60.5,408.8 L65.7,395.1 L70.9,381.5 L76.1,367.9 L81.3,354.2
L178.1,337.4 L198.5,326.1 L219.0,315.3 L239.4,305.0 L259.9,295.2 L280.4,285.9 L300.8,276.9 L321.3,268.4 L86.5,340.6 L91.7,327.0 L96.9,313.3 L102.1,299.7 L107.3,286.1 L112.5,272.5 L117.7,258.8 L122.9,245.2
L341.7,260.3 L362.2,252.6 L382.7,245.2 L403.1,238.2 L423.6,231.5 L444.1,225.1 L464.5,218.9 L485.0,213.1 L128.1,231.6 L133.3,217.9 L138.5,204.3 L143.6,190.7 L148.8,177.0 L154.0,163.4 L159.2,149.8 L164.4,145.9
L505.4,207.5 L525.9,202.1 L546.4,197.0 L566.8,192.1 L575.0,190.2 '/></g> L169.6,145.9 L174.8,145.9 L180.0,145.9 L185.2,145.9 L190.4,145.9 L195.6,145.9 L200.8,145.9 L206.0,145.9
L211.2,145.9 L216.4,145.9 L221.6,145.9 L226.8,145.9 L232.0,145.9 L237.2,145.9 L242.4,145.9 L247.6,145.9
L252.8,145.9 L258.0,145.9 L263.2,145.9 L268.4,145.9 L273.6,145.9 L278.8,145.9 L284.0,145.9 L289.2,145.9
L294.4,145.9 L299.6,145.9 L304.8,145.9 L310.0,145.9 L315.2,145.9 L320.3,145.9 L325.5,145.9 L330.7,145.9
L335.9,145.9 L341.1,145.9 L346.3,145.9 L351.5,145.9 L356.7,145.9 L361.9,145.9 L367.1,145.9 L372.3,145.9
L377.5,145.9 L382.7,145.9 L387.9,145.9 L393.1,145.9 L398.3,145.9 L403.5,145.9 L408.7,145.9 L413.9,145.9
L419.1,145.9 L424.3,145.9 L429.5,145.9 L434.7,145.9 L439.9,145.9 L445.1,145.9 L450.3,145.9 L455.5,145.9
L460.7,145.9 L465.9,145.9 L471.1,145.9 L476.3,145.9 L481.5,145.9 L486.7,145.9 L491.8,145.9 L497.0,145.9
L502.2,145.9 L507.4,145.9 L512.6,145.9 L517.8,145.9 L523.0,145.9 L528.2,145.9 L533.4,145.9 L538.6,145.9
L543.8,145.9 L549.0,145.9 L554.2,145.9 L559.4,145.9 L564.6,145.9 L569.8,145.9 L575.0,145.9 '/></g>
</g> </g>
<g id="gnuplot_plot_5" ><title>0</title> <g id="gnuplot_plot_5" ><title>0</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
@ -172,10 +203,19 @@
</g> </g>
</g> </g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='rgb(240, 228, 66)' d='M516.2,106.7 L558.4,106.7 M55.3,398.0 L75.8,377.7 L96.2,354.1 L116.7,330.2 L137.1,306.6 L157.6,283.6 <path stroke='rgb(240, 228, 66)' d='M516.2,106.7 L558.4,106.7 M55.3,422.4 L60.5,405.5 L65.7,388.6 L70.9,371.8 L76.1,354.9 L81.3,338.0
L178.1,261.4 L198.5,240.1 L219.0,219.7 L239.4,200.2 L259.9,181.7 L280.4,163.9 L300.8,147.0 L321.3,130.9 L86.5,321.1 L91.7,304.3 L96.9,287.4 L102.1,270.5 L107.3,253.6 L112.5,236.8 L117.7,219.9 L122.9,203.0
L341.7,115.6 L362.2,101.0 L382.7,87.0 L403.1,73.7 L423.6,61.0 L444.1,48.8 L464.5,37.3 L485.0,26.2 L128.1,186.1 L133.3,169.2 L138.5,152.4 L143.6,135.5 L148.8,118.6 L154.0,101.7 L159.2,84.9 L164.4,68.0
L503.2,16.7 '/></g> L169.6,51.1 L174.8,49.2 L180.0,49.2 L185.2,49.2 L190.4,49.2 L195.6,49.2 L200.8,49.2 L206.0,49.2
L211.2,49.2 L216.4,49.2 L221.6,49.2 L226.8,49.2 L232.0,49.2 L237.2,49.2 L242.4,49.2 L247.6,49.2
L252.8,49.2 L258.0,49.2 L263.2,49.2 L268.4,49.2 L273.6,49.2 L278.8,49.2 L284.0,49.2 L289.2,49.2
L294.4,49.2 L299.6,49.2 L304.8,49.2 L310.0,49.2 L315.2,49.2 L320.3,49.2 L325.5,49.2 L330.7,49.2
L335.9,49.2 L341.1,49.2 L346.3,49.2 L351.5,49.2 L356.7,49.2 L361.9,49.2 L367.1,49.2 L372.3,49.2
L377.5,49.2 L382.7,49.2 L387.9,49.2 L393.1,49.2 L398.3,49.2 L403.5,49.2 L408.7,49.2 L413.9,49.2
L419.1,49.2 L424.3,49.2 L429.5,49.2 L434.7,49.2 L439.9,49.2 L445.1,49.2 L450.3,49.2 L455.5,49.2
L460.7,49.2 L465.9,49.2 L471.1,49.2 L476.3,49.2 L481.5,49.2 L486.7,49.2 L491.8,49.2 L497.0,49.2
L502.2,49.2 L507.4,49.2 L512.6,49.2 L517.8,49.2 L523.0,49.2 L528.2,49.2 L533.4,49.2 L538.6,49.2
L543.8,49.2 L549.0,49.2 L554.2,49.2 L559.4,49.2 L564.6,49.2 L569.8,49.2 L575.0,49.2 '/></g>
</g> </g>
<g id="gnuplot_plot_6" ><title>0.5</title> <g id="gnuplot_plot_6" ><title>0.5</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
@ -184,8 +224,9 @@
</g> </g>
</g> </g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='rgb( 0, 114, 178)' d='M516.2,124.7 L558.4,124.7 M55.3,360.4 L75.8,308.6 L96.2,248.7 L116.7,187.8 L137.1,127.6 L157.6,69.2 <path stroke='rgb( 0, 114, 178)' d='M516.2,124.7 L558.4,124.7 M55.3,422.4 L60.5,399.0 L65.7,375.7 L70.9,352.3 L76.1,328.9 L81.3,305.6
L176.6,16.7 '/></g> L86.5,282.2 L91.7,258.8 L96.9,235.5 L102.1,212.1 L107.3,188.7 L112.5,165.3 L117.7,142.0 L122.9,118.6
L128.1,95.2 L133.3,71.9 L138.5,48.5 L143.6,25.1 L145.5,16.7 '/></g>
</g> </g>
<g id="gnuplot_plot_7" ><title>1</title> <g id="gnuplot_plot_7" ><title>1</title>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
@ -194,7 +235,9 @@
</g> </g>
</g> </g>
<g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="black" stroke="currentColor" stroke-width="1.00" stroke-linecap="butt" stroke-linejoin="miter">
<path stroke='rgb(229, 30, 16)' d='M516.2,142.7 L558.4,142.7 M55.3,300.7 L75.8,199.0 L96.2,81.4 L107.3,16.7 '/></g> <path stroke='rgb(229, 30, 16)' d='M516.2,142.7 L558.4,142.7 M55.3,422.4 L60.5,392.5 L65.7,362.7 L70.9,332.8 L76.1,303.0 L81.3,273.1
L86.5,243.2 L91.7,213.4 L96.9,183.5 L102.1,153.7 L107.3,123.8 L112.5,93.9 L117.7,64.1 L122.9,34.2
L125.9,16.7 '/></g>
</g> </g>
<g fill="none" color="#FFFFFF" stroke="rgb(229, 30, 16)" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter"> <g fill="none" color="#FFFFFF" stroke="rgb(229, 30, 16)" stroke-width="2.00" stroke-linecap="butt" stroke-linejoin="miter">
</g> </g>

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -1,210 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="700.66412"
height="272.14511"
id="svg2"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="software-buttons-conditions.svg">
<metadata
id="metadata4314">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1101"
id="namedview4312"
showgrid="false"
inkscape:zoom="1.1559716"
inkscape:cx="212.0146"
inkscape:cy="238.29755"
inkscape:window-x="1920"
inkscape:window-y="28"
inkscape:window-maximized="1"
inkscape:current-layer="svg2"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-page="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0">
<sodipodi:guide
position="563.298,393.72836"
orientation="0,1"
id="guide4473"
inkscape:locked="false" />
<sodipodi:guide
position="0,-89.159632"
orientation="1,0"
id="guide33334"
inkscape:locked="false" />
</sodipodi:namedview>
<defs
id="defs4">
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="marker34335"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path34333"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="marker34049"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path34047"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path33345"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.8,0,0,0.8,10,0)"
inkscape:connector-curvature="0" />
</marker>
<inkscape:path-effect
effect="spiro"
id="path-effect34019"
is_visible="true" />
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path33348"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.8,0,0,-0.8,-10,0)"
inkscape:connector-curvature="0" />
</marker>
<inkscape:path-effect
effect="spiro"
id="path-effect33343"
is_visible="true" />
</defs>
<rect
width="313.09872"
height="167.89594"
x="2.5968816"
y="2.5968816"
id="rect2858-0"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.19376326;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" />
<rect
width="313.09872"
height="167.89594"
x="384.96854"
y="2.5968931"
id="rect2858"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.19376326;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" />
<g
transform="translate(-776.70962,4.38162)"
id="g4656-3">
<g
id="g4639-2">
<path
inkscape:connector-curvature="0"
style="fill:none;stroke:#000000;stroke-width:0.72135597px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path2820-0-5-6"
d="m 970.15914,263.93369 32.58666,-97.47985 c 0,0 12.2603,-46.32869 38.5506,-33.925 20.7457,9.78778 17.4301,24.72594 16.4399,28.75425 -10.1846,41.43257 -30.105,105.84033 -30.105,105.84033 l -0.428,-0.37827 z"
sodipodi:nodetypes="ccssccc" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.00144271;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
id="path2824-9-3-6"
d="m 987.16367,214.84092 c 8.97014,-26.84686 16.75933,-50.19953 17.30923,-51.89481 3.8651,-11.91483 10.3862,-22.76212 16.5622,-27.54951 6.8496,-5.30946 13.8243,-5.75615 21.9108,-1.40323 3.7999,2.04543 6.0302,3.61208 8.2265,5.77836 2.5214,2.487 3.6881,4.17002 5.1008,7.35828 1.3655,3.08181 1.9391,7.11725 1.5051,10.58923 -0.597,4.77663 -10.2821,40.41668 -20.9931,77.25236 -7.7256,26.56907 -9.371,31.11182 -9.5644,31.10964 -0.1479,-0.002 -55.70067,-1.83937 -56.08626,-2.18017 -0.16723,-0.1478 6.29681,-19.93218 16.02913,-49.06015 z"
sodipodi:nodetypes="scsssscsccs" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.92000002;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;enable-background:accumulate"
id="path2824-7-8-8-4"
d="m 1008.3595,164.57667 c 3.8651,-11.91483 7.6606,-19.35039 13.8366,-24.13778 6.8495,-5.30946 12.0833,-5.57765 20.1698,-1.22474 9.3061,4.73331 12.9905,9.62271 11.9094,19.03362 -6.3459,19.3209 -6.9054,22.12042 -9.2168,26.32727 -0.1479,-0.002 -33.6651,-14.70742 -35.0296,-15.23839 -1.4035,-0.54616 -1.8884,-3.70289 -1.6694,-4.75998 z" />
</g>
</g>
<path
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.23500001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker34335)"
d="M 72.262856,47.254699 C 87.505219,34.288464 106.29239,25.531663 126.02382,22.196431 c 19.73142,-3.335232 40.35297,-1.239746 59.01017,5.996395 18.65721,7.236141 35.29888,19.59309 47.62145,35.360371 12.32257,15.767281 20.29224,34.901646 22.80582,54.754473 0.32542,2.57024 0.56139,5.1518 0.70733,7.73844"
id="path33341"
inkscape:connector-curvature="0"
inkscape:path-effect="#path-effect33343"
inkscape:original-d="M 72.262856,47.254699 C 133.3298,70.938208 194.39594,94.622538 255.46126,118.30767 c 61.06532,23.68514 0.47237,5.15815 0.70733,7.73844" />
<path
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.23500001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#Arrow1Lstart);marker-end:url(#marker34049)"
d="M 429.07628,149.3047 H 647.07471"
id="path34017"
inkscape:connector-curvature="0"
inkscape:path-effect="#path-effect34019"
inkscape:original-d="m 429.07628,149.3047 c 72.66714,-0.001 145.33329,-0.001 217.99843,0" />
<g
transform="matrix(0.79657897,0.11742288,-0.14814182,0.631399,377.36191,-341.92052)"
id="g3663-9-5">
<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-6"
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-1"
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-4"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.92000002;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;enable-background:accumulate"
inkscape:connector-curvature="0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 10 KiB

View file

@ -1,107 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="318.29248"
height="224.63223"
id="svg2"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="software-buttons-thumbpress.svg">
<metadata
id="metadata4314">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1101"
id="namedview4312"
showgrid="false"
inkscape:zoom="0.81739537"
inkscape:cx="284.62214"
inkscape:cy="70.498403"
inkscape:window-x="1920"
inkscape:window-y="28"
inkscape:window-maximized="1"
inkscape:current-layer="svg2"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-page="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0">
<sodipodi:guide
position="563.298,346.2155"
orientation="0,1"
id="guide4473"
inkscape:locked="false" />
</sodipodi:namedview>
<defs
id="defs4" />
<rect
width="313.09872"
height="167.89594"
x="2.5968816"
y="2.5968816"
id="rect2858-0"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.19376326;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" />
<g
transform="matrix(0.79657897,0.11742288,-0.14814182,0.631399,23.947506,-457.51364)"
id="g3663-9-5">
<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-6"
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-1"
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-4"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.92000002;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;enable-background:accumulate"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.0545106,0.16057813,-0.16057813,1.0545106,-220.12096,-375.662)"
id="g4151">
<path
sodipodi:nodetypes="sszzzcss"
d="m 353.70196,495.15765 c -24.01774,-7.29937 -29.0012,-10.10221 -30.51977,-10.54973 -10.67294,-3.14527 -18.27051,-5.54063 -23.77758,-13.4704 -5.50707,-7.92977 -5.34967,-20.78347 8.87612,-26.31604 14.2258,-5.53257 39.34351,8.79597 60.13061,16.16341 20.7871,7.36744 33.04563,11.44545 39.33422,13.87551 -8.10022,18.05041 -7.22129,21.15857 -10.11054,33.34117 -0.0481,0.20261 -17.87459,-5.12433 -43.93306,-13.04392 z"
id="path2824-1-1-3"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00100005;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="ccccc"
d="m 324.44991,483.39364 c -10.67294,-1.94747 -17.88441,-5.64478 -21.62691,-8.75386 -8.11652,-9.03765 -6.31775,-15.03428 -3.3272,-13.99784 8.90495,-0.9097 30.20384,9.01528 33.86042,10.17935 -5.80268,11.37909 -1.08919,13.70271 -8.90631,12.57235 z"
id="path2824-7-1-4-3"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.92000002;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;enable-background:accumulate"
inkscape:connector-curvature="0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.7 KiB

View file

@ -1,146 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="318.29248"
height="173.08969"
id="svg2"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="software-buttons-visualized.svg">
<metadata
id="metadata4314">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1101"
id="namedview4312"
showgrid="false"
inkscape:zoom="2.3119432"
inkscape:cx="188.48331"
inkscape:cy="69.297483"
inkscape:window-x="1920"
inkscape:window-y="28"
inkscape:window-maximized="1"
inkscape:current-layer="svg2"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-page="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0">
<sodipodi:guide
position="563.298,294.67296"
orientation="0,1"
id="guide4473"
inkscape:locked="false" />
</sodipodi:namedview>
<defs
id="defs4">
<inkscape:path-effect
is_visible="true"
id="path-effect22667"
effect="spiro" />
<inkscape:path-effect
effect="spiro"
id="path-effect22663"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect22659"
is_visible="true" />
</defs>
<rect
width="313.09872"
height="167.89594"
x="2.5968816"
y="2.5968816"
id="rect2858-0"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.19376326;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" />
<path
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00157475;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.00157475, 6.00944853;stroke-dashoffset:0;stroke-opacity:1"
d="M 1.2976097,125.94773 H 314.88662"
id="path22657"
inkscape:connector-curvature="0"
inkscape:path-effect="#path-effect22659"
inkscape:original-d="m 1.2976097,125.94773 c 104.5306703,-0.001 209.0603403,-0.001 313.5890103,0" />
<path
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00157475;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.00157475, 6.00944853;stroke-dashoffset:0;stroke-opacity:1"
d="m 124.9176,127.3866 v 43.12479"
id="path22661"
inkscape:connector-curvature="0"
inkscape:path-effect="#path-effect22663"
inkscape:original-d="m 124.9176,127.3866 c 0.001,14.27198 0.001,28.74886 0,43.12479" />
<path
inkscape:original-d="m 184.9176,127.3866 c 0.001,14.27198 0.001,28.74886 0,43.12479"
inkscape:path-effect="#path-effect22667"
inkscape:connector-curvature="0"
id="path22665"
d="m 184.9176,127.3866 v 43.12479"
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00157475;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.00157475, 6.00944853;stroke-dashoffset:0;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:100%;font-family:Helvetica;-inkscape-font-specification:Helvetica;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
x="128.8959"
y="73.610809"
id="text22671"><tspan
sodipodi:role="line"
id="tspan22669"
x="128.8959"
y="73.610809">main area</tspan></text>
<text
id="text22693"
y="151.37802"
x="215.27881"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:100%;font-family:Helvetica;-inkscape-font-specification:Helvetica;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
xml:space="preserve"><tspan
y="151.37802"
x="215.27881"
id="tspan22691"
sodipodi:role="line">right button</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:100%;font-family:Helvetica;-inkscape-font-specification:Helvetica;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
x="37.278809"
y="151.37802"
id="text22697"><tspan
sodipodi:role="line"
id="tspan22695"
x="37.278809"
y="151.37802">left button</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:100%;font-family:Helvetica;-inkscape-font-specification:Helvetica;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
x="137.27881"
y="151.37802"
id="text22701"><tspan
sodipodi:role="line"
id="tspan22699"
x="137.27881"
y="151.37802">middle</tspan></text>
</svg>

Before

Width:  |  Height:  |  Size: 6.4 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

@ -24,7 +24,7 @@ the respective area:
.. figure:: top-software-buttons.svg .. figure:: top-software-buttons.svg
:align: center :align: center
Left, right and middle-button click with top software button areas Left, right and middle-button click with top software button areas"
This page only covers the top software buttons, the bottom button behavior This page only covers the top software buttons, the bottom button behavior
is covered in :ref:`Clickpad software buttons <clickpad_softbuttons>`. is covered in :ref:`Clickpad software buttons <clickpad_softbuttons>`.

View file

@ -1,44 +0,0 @@
.. _tablet-debugging:
==============================================================================
Debugging tablet issues
==============================================================================
.. _tablet-capabilities:
------------------------------------------------------------------------------
Required tablet capabilities
------------------------------------------------------------------------------
To handle a tablet correctly, libinput requires a set of capabilities
on the device. When these capabilities are missing, libinput ignores the
device and prints an error to the log. This error messages reads
::
missing tablet capabilities: xy pen btn-stylus resolution. Ignoring this device.
or in older versions of libinput simply:
::
libinput bug: device does not meet tablet criteria. Ignoring this device.
When a tablet is rejected, it is usually possible to verify the issue with
the ``libinput record`` tool.
- **xy** indicates that the tablet is missing the ``ABS_X`` and/or ``ABS_Y``
axis. This indicates that the device is mislabelled and the udev tag
``ID_INPUT_TABLET`` is applied to a device that is not a tablet.
A bug should be filed against `systemd <http://github.com/systemd/systemd>`__.
- **pen** or **btn-stylus** indicates that the tablet does not have the
``BTN_TOOL_PEN`` or ``BTN_STYLUS`` bit set. libinput requires either or both
of them to be present. This indicates a bug in the kernel driver
or the HID descriptors of the device.
- **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
the `60-evdev.hwdb
<https://github.com/systemd/systemd/blob/main/hwdb.d/60-evdev.hwdb>`__ file
on your machine and file a pull request with the fixes against
`systemd <https://github.com/systemd/systemd/>`__.

View file

@ -12,7 +12,7 @@ Apple iPad.
.. figure:: tablet.svg .. figure:: tablet.svg
:align: center :align: center
Illustration of a graphics tablet Illustration of a graphics tablet"
.. _tablet-tools: .. _tablet-tools:
@ -36,7 +36,7 @@ across multiple kernel devices.
.. figure:: tablet-interfaces.svg .. figure:: tablet-interfaces.svg
:align: center :align: center
Difference between Pad and Tool buttons Difference between Pad and Tool buttons"
Touch events on the tablet integrated into a screen itself are exposed Touch events on the tablet integrated into a screen itself are exposed
through the **LIBINPUT_DEVICE_CAP_TOUCH** capability. Touch events on a through the **LIBINPUT_DEVICE_CAP_TOUCH** capability. Touch events on a
@ -67,7 +67,7 @@ tools are capable of detecting 1 gram of pressure.
libinput uses a device-specific pressure threshold to determine when the tip libinput uses a device-specific pressure threshold to determine when the tip
is considered logically down. As a result, libinput may send a nonzero is considered logically down. As a result, libinput may send a nonzero
pressure value while the tip is logically up. Most applications can and pressure value while the tip is logically up. Most application can and
should ignore pressure information until they receive the event of type should ignore pressure information until they receive the event of type
**LIBINPUT_EVENT_TABLET_TOOL_TIP**. Applications that require extremely **LIBINPUT_EVENT_TABLET_TOOL_TIP**. Applications that require extremely
fine-grained pressure sensitivity should use the pressure data instead of fine-grained pressure sensitivity should use the pressure data instead of
@ -118,7 +118,7 @@ additionally provide tilt information along the x and y axis.
.. figure:: tablet-axes.svg .. figure:: tablet-axes.svg
:align: center :align: center
Illustration of the distance, pressure and tilt axes Illustration of the distance, pressure and tilt axes"
The granularity and precision of the distance and pressure axes varies The granularity and precision of the distance and pressure axes varies
between tablet devices and cannot usually be mapped into a physical unit. between tablet devices and cannot usually be mapped into a physical unit.
@ -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:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -284,7 +238,7 @@ with **libinput_tablet_tool_get_tool_id()** but makes no promises about the
content or format of the ID. content or format of the ID.
libinput currently supports Wacom-style tool IDs as provided on the Wacom libinput currently supports Wacom-style tool IDs as provided on the Wacom
Intuos 3, 4, 5, Wacom Cintiq and Wacom Intuos Pro series. The tool ID can Intuos 3, 4, 5, Wacon Cintiq and Wacom Intuos Pro series. The tool ID can
be used to distinguish between e.g. a Wacom Classic Pen or a Wacom Pro Pen. be used to distinguish between e.g. a Wacom Classic Pen or a Wacom Pro Pen.
It is the caller's responsibility to interpret the tool ID. It is the caller's responsibility to interpret the tool ID.
@ -304,7 +258,7 @@ the caller to ignore these events.
.. figure:: tablet-out-of-bounds.svg .. figure:: tablet-out-of-bounds.svg
:align: center :align: center
Illustration of the out-of-bounds area on a tablet Illustration of the out-of-bounds area on a tablet"
In the image above, the display area is shown in black. The red area around In the image above, the display area is shown in black. The red area around
the display illustrates the sensor area that generates input events. Events the display illustrates the sensor area that generates input events. Events
@ -367,7 +321,7 @@ point.
.. figure:: tablet-left-handed.svg .. figure:: tablet-left-handed.svg
:align: center :align: center
Tablet axes in right- and left-handed mode Tablet axes in right- and left-handed mode"
Pad buttons are not affected by left-handed mode; the number of each button Pad buttons are not affected by left-handed mode; the number of each button
remains the same even when the perceived physical location of the button remains the same even when the perceived physical location of the button
@ -423,7 +377,7 @@ device.
.. figure:: tablet-intuos-modes.svg .. figure:: tablet-intuos-modes.svg
:align: center :align: center
Modes on an Intuos Pro-like tablet Modes on an Intuos Pro-like tablet"
In the image above, the Intuos Pro-like tablet provides 4 LEDs to indicate In the image above, the Intuos Pro-like tablet provides 4 LEDs to indicate
the currently active modes. The button inside the touch ring cycles through the currently active modes. The button inside the touch ring cycles through
@ -438,7 +392,7 @@ and all subsequent events.
.. figure:: tablet-cintiq24hd-modes.svg .. figure:: tablet-cintiq24hd-modes.svg
:align: center :align: center
Modes on an Cintiq 24HD-like tablet Modes on an Cintiq 24HD-like tablet"
In the image above, the Cintiq 24HD-like tablet provides 3 LEDs on each side In the image above, the Cintiq 24HD-like tablet provides 3 LEDs on each side
of the tablet to indicate the currently active mode for that group of of the tablet to indicate the currently active mode for that group of
@ -468,77 +422,37 @@ 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-capabilities:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
Tablet area Required tablet capabilities
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
External tablet devices such as e.g. the Wacom Intuos series can be configured To handle a tablet correctly, libinput requires a set of capabilities
to reduce the available logical input area. Typically the logical input area on the device. When these capabilities are missing, libinput ignores the
is equivalent to the physical input area but it can be reduced with the device and prints an error to the log. This error messages reads
**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 missing tablet capabilities: xy pen btn-stylus resolution. Ignoring this device.
In the image above, the area is set to the rectangle 0.25/0.25 to 0.5/0.75. or in older versions of libinput simply:
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: libinput bug: device does not meet tablet criteria. Ignoring this device.
------------------------------------------------------------------------------
Tablet eraser buttons
------------------------------------------------------------------------------
Tablet tools come in a variety of forms but the most common one is a When a tablet is rejected, it is usually possible to check the issue with
pen-like tool. Some of these pen-like tools have a virtual eraser at the the ``evemu-descibe`` tool.
tip of the tool - inverting the tool brings the eraser into proximity.
.. figure:: tablet-eraser-invert.svg - **xy** indicates that the tablet is missing the ``ABS_X`` and/or ``ABS_Y``
:align: center axis. This indicates that the device is mislabelled and the udev tag
``ID_INPUT_TABLET`` is applied to a device that is not a tablet.
An pen-like tool used as pen and as eraser by inverting it - **pen** or **btn-stylus** indicates that the tablet does not have the
``BTN_TOOL_PEN`` or ``BTN_STYLUS`` bit set. libinput requires either or both
Having an eraser as a separate tool is beneficial in many applications as the of them to be present. This usually indicates a bug in the kernel driver
eraser tool can be assigned different functionality (colors, paint tools, etc.) or the HID descriptors of the device.
that is easily available. - **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
However, a large proportion of tablet pens have an "eraser button". By the 60-evdev.hwdb file on your machine to address this.
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:
@ -22,8 +21,9 @@ hardware can distinguish between that many fingers.
Tap-to-click default setting Tap-to-click default setting
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
Tapping is **disabled** by default on most devices, see Tapping is **disabled** by default on most devices, see [this
:commit:`2219c12c3` because: commit](https://gitlab.freedesktop.org/libinput/libinput/commit/2219c12c3aa45b80f235e761e87c17fb9ec70eae)
because:
- if you don't know that tapping is a thing (or enabled by default), you get - if you don't know that tapping is a thing (or enabled by default), you get
spurious button events that make the desktop feel buggy. spurious button events that make the desktop feel buggy.
@ -34,10 +34,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,27 +50,17 @@ 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 Also optional is a feature called "drag lock". With drag lock disabled, lifting
the initial tap decide the type of button click. For example, to the finger will stop any drag process. When enabled, libinput will ignore a
middle-click drag, tap with three fingers followed by a finger up event during a drag process, provided the finger is set down again
single-finger drag. within a implementation-specific timeout. Drag lock can be enabled and
disabled with **libinput_device_config_tap_set_drag_lock_enabled()**.
Also optional is a feature called "drag lock". With drag lock **disabled**, Note that drag lock only applies if tap-and-drag is be enabled.
lifting the finger will stop any drag process. When **enabled**, the drag
process continues even after lifting a finger, allowing the user to
reset the finger position and keep moving without releasing the drag.
libinput supports two variations of this drag lock: "sticky" and "timeout".
In sticky mode, the drag lock must be ended with an explicit additional tap.
In timeout mode, the drag lock ends automatically if no finger was put back on
the touchpad within a timeout. Drag lock can be 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
Tap-and-drag process Tap-and-drag process"
The above diagram explains the process, a tap (a) followed by a finger held The above diagram explains the process, a tap (a) followed by a finger held
down (b) starts the drag process and logically holds the left mouse button down (b) starts the drag process and logically holds the left mouse button
@ -84,13 +70,8 @@ position can be reset by lifting and quickly setting it down again on the
touchpad (d). This will be interpreted as continuing move and is especially touchpad (d). This will be interpreted as continuing move and is especially
useful on small touchpads or with slow pointer acceleration. useful on small touchpads or with slow pointer acceleration.
If drag lock is enabled, the release of the mouse buttons after the finger If drag lock is enabled, the release of the mouse buttons after the finger
release (e) is triggered by a timeout (if in timeout mode) or by tapping again (f). release (e) is triggered by a timeout. To release the button immediately,
simply tap again (f).
libinput also supports an "auto drag-lock" feature: if drag lock is **disabled**
but the dragging finger is released at the very edge of the touchpad,
a drag lock automatically activates for a short timeout. This allows a user to
quickly reset the finger to elsewhere on the touchpad and continue the dragging
motion. If the finger is released elsewhere, no drag lock activates.
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

@ -4,41 +4,19 @@
libinput test suite libinput test suite
============================================================================== ==============================================================================
libinput's primary test suite can be invoked with libinput ships with a number of tests all run automatically on ``ninja test``.
The primary test suite is the ``libinput-test-suite-runner``. When testing,
the ``libinput-test-suite-runner`` should always be invoked to check for
behavior changes.
:: The test suite runner uses
`Check <http://check.sourceforge.net/doc/check_html/>`_ underneath the hood
$ sudo ./builddir/libinput-test-suite but most of the functionality is abstracted into *litest* wrappers.
When developing libinput, the ``libinput-test-suite`` should always be
run to check for behavior changes and/or regressions. For quick iteration,
the number of tests to run can be filtered, see :ref:`test-filtering`.
This allows for developers to verify a subset of tests (e.g.
touchpad tap-to-click) while hacking on that specific feature and only run
the full suite when development is finished.
.. note:: The test suite relies on udev and the kernel, specifically uinput.
It creates virtual input devices and replays the events. This may
interfere with your running session. The test suite is not suitable
for running inside containers.
In addition, libinput ships with a set of (primarily janitorial) tests that
must pass for any merge request. These tests are invoked by calling
``meson test -C builddir`` (or ``ninja test``). The ``libinput-test-suite`` is
part of that test set by default.
The upstream CI runs all these tests and is run for every merge request.
.. _test-job-control:
------------------------------------------------------------------------------
Job control in the test suite
------------------------------------------------------------------------------
The test suite runner has a make-like job control enabled by the ``-j`` or The test suite runner has a make-like job control enabled by the ``-j`` or
``--jobs`` flag and will fork off as many parallel processes as given by this ``--jobs`` flag and will fork off as many parallel processes as given by this
flag. The default if unspecified is 8. When debugging a specific test case flag. The default if unspecified is 8. When debugging a specific test case
failure it is recommended to employ test filters (see :ref:`test-filtering`) failure it is recommended to employ test filtures (see :ref:`test-filtering`)
and disable parallel tests. The test suite automatically disables parallel and disable parallel tests. The test suite automatically disables parallel
make when run in gdb. make when run in gdb.
@ -65,8 +43,8 @@ Permissions required to run tests
Most tests require the creation of uinput devices and access to the Most tests require the creation of uinput devices and access to the
resulting ``/dev/input/eventX`` nodes. Some tests require temporary udev rules. resulting ``/dev/input/eventX`` nodes. Some tests require temporary udev rules.
**This usually requires the tests to be run as root**. If not run as **This usually requires the tests to be run as root**. If not run as
root, the test suite runner will exit with status 77, an exit status root, the test suite runner will exit with status 77, interpreted as
interpreted as "skipped". "skipped" by ninja.
.. _test-filtering: .. _test-filtering:
@ -84,7 +62,7 @@ run for a device.
:: ::
$ ./builddir/libinput-test-suite --list $ ./test/libinput-test-suite-runner --list
... ...
pointer:left-handed: pointer:left-handed:
pointer_left_handed_during_click_multiple_buttons: pointer_left_handed_during_click_multiple_buttons:
@ -139,7 +117,7 @@ basic shell-style function name matching. For example:
:: ::
$ ./builddir/libinput-test-suite --filter-test="*1fg_tap*" $ ./test/libinput-test-suite-runner --filter-test="*1fg_tap*"
The ``--filter-device`` argument enables selective running of tests through The ``--filter-device`` argument enables selective running of tests through
@ -149,7 +127,7 @@ litest-specific shortnames, see the output of ``--list``. For example:
:: ::
$ ./builddir/libinput-test-suite --filter-device="synaptics*" $ ./test/libinput-test-suite-runner --filter-device="synaptics*"
The ``--filter-group`` argument enables selective running of test groups The ``--filter-group`` argument enables selective running of test groups
@ -159,7 +137,7 @@ litest-specific test groups, see the output of ``--list``. For example:
:: ::
$ ./builddir/libinput-test-suite --filter-group="touchpad:*hover*" $ ./test/libinput-test-suite-runner --filter-group="touchpad:*hover*"
The ``--filter-device`` and ``--filter-group`` arguments can be combined with The ``--filter-device`` and ``--filter-group`` arguments can be combined with
@ -178,65 +156,5 @@ environment variable, if set, also enables verbose mode.
:: ::
$ ./builddir/libinput-test-suite --verbose $ ./test/libinput-test-suite-runner --verbose
$ LITEST_VERBOSE=1 meson test -C builddir $ LITEST_VERBOSE=1 ninja test
.. _test-installed:
------------------------------------------------------------------------------
Installing the test suite
------------------------------------------------------------------------------
If libinput is configured to install the tests, the test suite is available
as the ``libinput test-suite`` command. When run as installed binary, the
behavior of the test suite changes:
- the ``libinput.so`` used is the one in the library lookup paths
- no system-wide quirks are installed by the test suite, only those specific
to the test devices
- test device-specific quirks are installed in the system-wide quirks
directory, usually ``/usr/share/libinput/``.
It is not advisable to run ``libinput test-suite`` on a production machine.
Data loss may occur. The primary use-case for the installed test suite is
verification of distribution composes.
.. note:: The ``prefix`` is still used by the test suite. For verification
of a system package, the test suite must be configured with the same prefix.
To configure libinput to install the tests, use the ``-Dinstall-tests=true``
meson option::
$ meson setup builddir -Dtests=true -Dinstall-tests=true <other options>
.. _test-meson-suites:
------------------------------------------------------------------------------
Meson test suites
------------------------------------------------------------------------------
This section is primarily of interest to distributors that want to run test
or developers working on libinput's CI.
Tests invoked by ``meson test`` are grouped into test suites, the test suite
names identify when the respective test can be run:
- ``valgrind``: tests that can be run under valgrind (in addition to a
normal run)
- ``root``: tests that must be run as root
- ``hardware``: tests that require a VM or physical machine
- ``all``: all tests, only needed because of
`meson bug 5340 <https://github.com/mesonbuild/meson/issues/5340>`_
The suite names can be provided as filters to ``meson test
--suite=<suitename>`` or ``meson test --no-suite=<suitename>``.
For example, if running a container-based CI, you may specify the test
suites as:
::
$ meson test --no-suite=machine # only run container-friendly tests
$ meson test --suite=valgrind --setup=valgrind # run all valgrind-compatible tests
$ meson test --no-suite=root # run all tests not requiring root
These suites are subject to change at any time.

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,12 +21,8 @@ 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
:ref:`here <libinput-quirks>`
Most of the tools must be run as root to have access to the kernel's Most the tools must be run as root to have access to the kernel's
``/dev/input/event*`` device files. ``/dev/input/event*`` device files.
.. _libinput-list-devices: .. _libinput-list-devices:
@ -73,56 +67,7 @@ The above listing shows example output for a touchpad. The
default configuration for this device, for options that have more than a default configuration for this device, for options that have more than a
binary state all available options are listed, with the default one prefixed 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 clickinger 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.
@ -207,20 +152,16 @@ the available options.
libinput record and libinput replay libinput record and libinput replay
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
.. note:: For libinput versions 1.10 and older, use :ref:`evemu`.
The ``libinput record`` command records the **kernel** events from a specific The ``libinput record`` command records the **kernel** events from a specific
device node. The recorded sequence can be replayed with the ``libinput device node. The recorded sequence can be replayed with the ``libinput
replay`` command. This pair of tools is crucial to capturing bugs and replay`` command. This pair of tools is crucial to capturing bugs and
reproducing them on a developer's machine. reproducing them on a developer's machine.
.. graphviz:: libinput-record.gv .. note:: These tools are shipped with libinput, but the recorded events
:align: center are **kernel events** and independent of the libinput context. libinput
does not need to be running, it does not matter whether a user is
The recorded events are **kernel events** and independent of the running X.Org or Wayland or even what version of libinput is currently
libinput context. libinput does not need to be running, it does running.
not matter whether a user is running X.Org or Wayland or even what
version of libinput is currently running.
The use of the tools is straightforward, just run without arguments, piping The use of the tools is straightforward, just run without arguments, piping
the output into a file: :: the output into a file: ::
@ -255,16 +196,12 @@ the user select one. Supply the number (17 in this case for
events to the file it is redirected to. More arguments are available, see events to the file it is redirected to. More arguments are available, see
the **libinput-record(1)** man page. the **libinput-record(1)** man page.
.. note:: When reproducing a bug that crashes libinput, run inside ``screen`` or
``tmux``.
Reproduce the bug, ctrl+c and attach the output file to a bug report. Reproduce the bug, ctrl+c and attach the output file to a bug report.
For data protection, ``libinput record`` obscures key codes by default, any For data protection, ``libinput record`` obscures key codes by default, any
alphanumeric key shows up as letter "a". alphanumeric key shows up as letter "a".
.. warning:: The longer the recording, the harder it is to identify the event .. note:: When reproducing a bug that crashes libinput, run inside ``screen`` or
sequence triggering the bug. Please keep the event sequence as ``tmux``.
short as possible.
The recording can be replayed with the ``libinput replay`` command: :: The recording can be replayed with the ``libinput replay`` command: ::
@ -354,30 +291,3 @@ measure specific properties on the device. These tools generally measure one
thing and one thing only and their usage is highly specific to the tool. 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 tool.
.. _libinput-quirks:
------------------------------------------------------------------------------
Listing quirks assigned to a device
------------------------------------------------------------------------------
The ``libinput quirks`` tool can show quirks applied for any given device. ::
$ libinput quirks list /dev/input/event0
AttrLidSwitchReliability=unreliable
If the tool's output is empty, no quirk is applied. See :ref:`device-quirks`
for more information.

View file

@ -8,7 +8,7 @@ Touchpad jitter describes random movement by a few pixels even when the
user's finger is unmoving. user's finger is unmoving.
libinput has a mechanism called a **hysteresis** to avoid that jitter. When libinput has a mechanism called a **hysteresis** to avoid that jitter. When
active, movement within the **hysteresis margin** is discarded. If the active, movement with in the **hysteresis margin** is discarded. If the
movement delta is larger than the margin, the movement is passed on as movement delta is larger than the margin, the movement is passed on as
pointer movement. This is a simplified summary, developers should pointer movement. This is a simplified summary, developers should
read the implementation of the hysteresis in ``src/evdev.c``. read the implementation of the hysteresis in ``src/evdev.c``.
@ -61,7 +61,7 @@ value in case the ``libinput measure fuzz`` tool fails.
Check with ``udevadm info /sys/class/input/eventX`` (replace your device node Check with ``udevadm info /sys/class/input/eventX`` (replace your device node
number) whether an existing hwdb override exists. If the ``EVDEV_ABS_`` number) whether an existing hwdb override exists. If the ``EVDEV_ABS_``
properties are present, the hwdb override exists. Find the file that properties are present, the hwdb overried exists. Find the file that
contains that entry, most likely in ``/etc/udev/hwdb.d`` or contains that entry, most likely in ``/etc/udev/hwdb.d`` or
``/usr/lib/udev/hwdb.d``. ``/usr/lib/udev/hwdb.d``.

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 evemu-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 an evemu
your touchpad with :ref:`libinput record <libinput-record>` and file a bug. recording of your touchpad and file a bug. See :ref:`reporting_bugs` for more
See :ref:`reporting_bugs` for more details. 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

@ -1,234 +0,0 @@
==============================================================================
Debugging touchpad pressure/size ranges
==============================================================================
:ref:`Touchpad pressure/size ranges <touchpad_pressure>` depend on
:ref:`device-quirks` entry specific to each laptop model. To check if a
pressure/size range is already defined for your device, use the
:ref:`libinput quirks <device-quirks-debugging>` tool: ::
$ libinput quirks list /dev/input/event19
If your device does not list any quirks, it probably needs a touch
pressure/size range, a palm threshold and a thumb threshold. Start with
:ref:`touchpad_pressure_hwdb`, then :ref:`touchpad_touch_size_hwdb`. The
respective tools will exit if the required axis is not supported.
.. _touchpad_pressure_hwdb:
------------------------------------------------------------------------------
Debugging touchpad pressure ranges
------------------------------------------------------------------------------
This section describes how to determine the touchpad pressure ranges
required for a touchpad device and how to add the required
:ref:`device-quirks` locally. Note that the quirk is **not public API** and **may
change at any time**. Users are advised to :ref:`report a bug <reporting_bugs>`
with the updated pressure ranges when testing has completed.
.. note:: Most distributions ship ``libinput measure`` in a separate
``libinput-utils`` package.
Use the ``libinput measure touchpad-pressure`` tool provided by libinput.
This tool will search for your touchpad device and print some pressure
statistics, including whether a touch is/was considered logically down.
.. note:: This tool will only work on touchpads with pressure.
Example output of the tool is below: ::
$ sudo libinput measure touchpad-pressure
Using Synaptics TM2668-002: /dev/input/event21
This is an interactive tool
Place a single finger on the touchpad to measure pressure values.
Check that:
- touches subjectively perceived as down are tagged as down
- touches with a thumb are tagged as thumb
- touches with a palm are tagged as palm
If the touch states do not match the interaction, re-run
with --touch-thresholds=down:up using observed pressure values.
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.
For each, the respective minimum and maximum pressure values are printed as
well as some statistics. The ``down`` column shows that each sequence was
considered logically down at some point (see the thresholds in the last line),
two of the sequences were considered thumbs. This is an interactive tool and
its output may change frequently. Refer to the
**libinput-measure-touchpad-pressure(1)** man page for more details.
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
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``
argument: ::
$ sudo libinput measure touchpad-pressure --touch-thresholds=10:8 --palm-threshold=20
Interact with the touchpad and check if the output of this tool matches your
expectations.
.. note:: This is an interactive process. You will need to re-run the
tool with varying thresholds until you find the right range for
your touchpad. Attaching output logs to a bug will not help, only
you with access to the hardware can figure out the correct
ranges.
Once the thresholds are decided on (e.g. 10 and 8), they can be enabled with
:ref:`device-quirks` entry similar to this: ::
$> cat /etc/libinput/local-overrides.quirks
[Touchpad pressure override]
MatchUdevType=touchpad
MatchName=*SynPS/2 Synaptics TouchPad
MatchDMIModalias=dmi:*:svnLENOVO:*:pvrThinkPadX230:*
AttrPressureRange=10:8
AttrPalmPressureThreshold=150
AttrThumbPressureThreshold=100
The file name **must** be ``/etc/libinput/local-overrides.quirks``.
The first line is the section name and can be free-form. The ``Match``
directives limit the quirk to your touchpad, make sure the device name
matches your device's name (see ``libinput record``'s output). The dmi
modalias match should be based on the information in
``/sys/class/dmi/id/modalias``. This modalias should be shortened to the
specific system's information, usually system vendor (svn)
and product name (pn).
Once in place, run the following command to verify the quirk is valid and
works for your device: ::
$ sudo libinput quirks list /dev/input/event10
AttrPressureRange=10:8
Replace the event node with the one from your device. If the
``AttrPressureRange`` quirk does not show up, re-run with ``--verbose`` and
check the output for any error messages.
If the pressure range quirk shows up correctly, restart X or the
Wayland compositor and libinput should now use the correct pressure
thresholds. The :ref:`tools` can be used to verify the correct
functionality first without the need for a restart.
Once the pressure ranges are deemed correct,
:ref:`report a bug <reporting_bugs>` to get the pressure ranges into the
repository.
.. _touchpad_touch_size_hwdb:
------------------------------------------------------------------------------
Debugging touch size ranges
------------------------------------------------------------------------------
This section describes how to determine the touchpad size ranges
required for a touchpad device and how to add the required
:ref:`device-quirks` locally. Note that the quirk is **not public API** and **may
change at any time**. Users are advised to :ref:`report a bug <reporting_bugs>`
with the updated pressure ranges when testing has completed.
.. note:: Most distributions ship ``libinput measure`` in a separate
``libinput-utils`` package.
Use the ``libinput measure touch-size`` tool provided by libinput.
This tool will search for your touchpad device and print some touch size
statistics, including whether a touch is/was considered logically down.
.. note:: This tool will only work on touchpads with the ``ABS_MT_MAJOR`` axis.
Example output of the tool is below: ::
$ sudo libinput measure touch-size --touch-thresholds 10:8 --palm-threshold 14
Using ELAN Touchscreen: /dev/input/event5
&nbsp;
Ready for recording data.
Touch sizes used: 10:8
Palm size used: 14
Place a single finger on the device to measure touch size.
Ctrl+C to exit
&nbsp;
Sequence: major: [ 9.. 11] minor: [ 7.. 9]
Sequence: major: [ 9.. 10] minor: [ 7.. 7]
Sequence: major: [ 9.. 14] minor: [ 6.. 9] down
Sequence: major: [ 11.. 11] minor: [ 9.. 9] down
Sequence: major: [ 4.. 33] minor: [ 1.. 5] down palm
The example output shows five completed touch sequences. For each, the
respective minimum and maximum pressure values are printed as well as some
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
output may change frequently. Refer to the **libinput-measure-touch-size(1)** man
page for more details.
By default, this tool uses the :ref:`device-quirks` for the touch size range. To
narrow down on the best values for your device, specify the 'logically down'
and 'logically up' pressure thresholds with the ``--touch-thresholds``
arguments as in the example above.
Interact with the touchpad and check if the output of this tool matches your
expectations.
.. note:: This is an interactive process. You will need to re-run the
tool with varying thresholds until you find the right range for
your touchpad. Attaching output logs to a bug will not help, only
you with access to the hardware can figure out the correct
ranges.
Once the thresholds are decided on (e.g. 10 and 8), they can be enabled with
:ref:`device-quirks` entry similar to this: ::
$> cat /etc/libinput/local-overrides.quirks
[Touchpad touch size override]
MatchUdevType=touchpad
MatchName=*SynPS/2 Synaptics TouchPad
MatchDMIModalias=dmi:*:svnLENOVO:*:pvrThinkPadX230:*
AttrTouchSizeRange=10:8
The first line is the match line and should be adjusted for the device name
(see :ref:`libinput record <libinput-record>`'s output) and for the local system, based on the
information in ``/sys/class/dmi/id/modalias``. The modalias should be
shortened to the specific system's information, usually system vendor (svn)
and product name (pn).
Once in place, run the following command to verify the quirk is valid and
works for your device: ::
$ sudo libinput quirks list /dev/input/event10
AttrTouchSizeRange=10:8
Replace the event node with the one from your device. If the
``AttrTouchSizeRange`` quirk does not show up, re-run with ``--verbose`` and
check the output for any error messages.
If the touch size range property shows up correctly, restart X or the
Wayland compositor and libinput should now use the correct thresholds.
The :ref:`tools` can be used to verify the correct functionality first without
the need for a restart.
Once the touch size ranges are deemed correct, :ref:`reporting_bugs` "report a
bug" to get the thresholds into the repository.

View file

@ -5,17 +5,12 @@ Touchpad pressure-based touch detection
============================================================================== ==============================================================================
libinput uses the touchpad pressure values and/or touch size values to libinput uses the touchpad pressure values and/or touch size values to
detect whether a finger has been placed on the touchpad. This is detect wether a finger has been placed on the touchpad. This is
:ref:`kernel_pressure_information` and combines with a libinput-specific hardware :ref:`kernel_pressure_information` and combines with a libinput-specific hardware
database to adjust the thresholds on a per-device basis. libinput uses database to adjust the thresholds on a per-device basis. libinput uses
these thresholds primarily to filter out accidental light touches but these thresholds primarily to filter out accidental light touches but
the information is also used for some :ref:`palm_detection`. the information is also used for some :ref:`palm_detection`.
Most devices only support one of either touch pressure or touch size.
libinput uses whichever is available but a preference is given to touch size
as it provides more specific information. Since most devices only provide
one type anyway, this internal preference does not usually matter.
Pressure and touch size thresholds are **not** directly configurable by the Pressure and touch size thresholds are **not** directly configurable by the
user. Instead, libinput provides these thresholds for each device where user. Instead, libinput provides these thresholds for each device where
necessary. See :ref:`touchpad_pressure_hwdb` for instructions on how to adjust necessary. See :ref:`touchpad_pressure_hwdb` for instructions on how to adjust
@ -50,9 +45,196 @@ touchpads. Some devices can detect multiple fingers but only provide
Some devices provide additional touch size information through Some devices provide additional touch size information through
the ``ABS_MT_TOUCH_MAJOR/ABS_MT_TOUCH_MINOR`` axes and/or the ``ABS_MT_TOUCH_MAJOR/ABS_MT_TOUCH_MINOR`` axes and/or
the ``ABS_MT_WIDTH_MAJOR/ABS_MT_WIDTH_MINOR`` axes. These axes specify the ``ABS_MT_WIDTH_MAJOR/ABS_MT_WIDTH_MINOR`` axes. These axes specifcy
the size of the touch ellipse. While the kernel documentation specifies how the size of the touch ellipse. While the kernel documentation specifies how
these axes are supposed to be mapped, few devices forward reliable 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.
.. _touchpad_pressure_hwdb:
------------------------------------------------------------------------------
Debugging touchpad pressure ranges
------------------------------------------------------------------------------
This section describes how to determine the touchpad pressure ranges
required for a touchpad device and how to add the required
:ref:`device-quirks` locally. Note that the quirk is **not public API** and **may
change at any time**. Users are advised to :ref:`report a bug <reporting_bugs>`
with the updated pressure ranges when testing has completed.
Use the ``libinput measure touchpad-pressure`` tool provided by libinput.
This tool will search for your touchpad device and print some pressure
statistics, including whether a touch is/was considered logically down.
.. note:: This tool will only work on touchpads with pressure.
Example output of the tool is below: ::
$ sudo libinput measure touchpad-pressure
Ready for recording data.
Pressure range used: 8:10
Palm pressure range used: 65535
Place a single finger on the touchpad to measure pressure values.
Ctrl+C to exit
&nbsp;
Sequence 1190 pressure: min: 39 max: 48 avg: 43 median: 44 tags: down
Sequence 1191 pressure: min: 49 max: 65 avg: 62 median: 64 tags: down
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
Sequence 1194 pressure: min: 43 max: 76 avg: 72 median: 74 tags: down
Touchpad pressure: 47 min: 47 max: 86 tags: down
The example output shows five completed touch sequences and one ongoing one.
For each, the respective minimum and maximum pressure values are printed as
well as some statistics. The ``tags`` show that sequence was considered
logically down at some point. This is an interactive tool and its output may
change frequently. Refer to the <i>libinput-measure-touchpad-pressure(1)</i> man
page for more details.
By default, this tool uses the :ref:`device-quirks` for the pressure range. To
narrow down on the best values for your device, specify the 'logically down'
and 'logically up' pressure thresholds with the ``--touch-thresholds``
argument: ::
$ sudo libinput measure touchpad-pressure --touch-thresholds=10:8 --palm-threshold=20
Interact with the touchpad and check if the output of this tool matches your
expectations.
.. note:: This is an interactive process. You will need to re-run the
tool with varying thresholds until you find the right range for
your touchpad. Attaching output logs to a bug will not help, only
you with access to the hardware can figure out the correct
ranges.
Once the thresholds are decided on (e.g. 10 and 8), they can be enabled with
:ref:`device-quirks` entry similar to this: ::
$> cat /etc/libinput/local-overrides.quirks
[Touchpad pressure override]
MatchUdevType=touchpad
MatchName=*SynPS/2 Synaptics TouchPad
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadX230*
AttrPressureRange=10:8
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``
directives limit the quirk to your touchpad, make sure the device name
matches your device's name (see ``libinput record``'s output). The dmi
modalias match should be based on the information in
``/sys/class/dmi/id/modalias``. This modalias should be shortened to the
specific system's information, usually system vendor (svn)
and product name (pn).
Once in place, run the following command to verify the quirk is valid and
works for your device: ::
$ sudo libinput list-quirks /dev/input/event10
AttrPressureRange=10:8
Replace the event node with the one from your device. If the
``AttrPressureRange`` quirk does not show up, re-run with ``--verbose`` and
check the output for any error messages.
If the pressure range quirk shows up correctly, restart X or the
Wayland compositor and libinput should now use the correct pressure
thresholds. The :ref:`tools` can be used to verify the correct
functionality first without the need for a restart.
Once the pressure ranges are deemed correct,
:ref:`report a bug <reporting_bugs>` to get the pressure ranges into the
repository.
.. _touchpad_touch_size_hwdb:
------------------------------------------------------------------------------
Debugging touch size ranges
------------------------------------------------------------------------------
This section describes how to determine the touchpad size ranges
required for a touchpad device and how to add the required
:ref:`device-quirks` locally. Note that the quirk is **not public API** and **may
change at any time**. Users are advised to :ref:`report a bug <reporting_bugs>`
with the updated pressure ranges when testing has completed.
Use the ``libinput measure touch-size`` tool provided by libinput.
This tool will search for your touchpad device and print some touch size
statistics, including whether a touch is/was considered logically down.
.. note:: This tool will only work on touchpads with the ``ABS_MT_MAJOR`` axis.
Example output of the tool is below: ::
$ sudo libinput measure touch-size --touch-thresholds 10:8 --palm-threshold 14
Using ELAN Touchscreen: /dev/input/event5
&nbsp;
Ready for recording data.
Touch sizes used: 10:8
Palm size used: 14
Place a single finger on the device to measure touch size.
Ctrl+C to exit
&nbsp;
Sequence: major: [ 9.. 11] minor: [ 7.. 9]
Sequence: major: [ 9.. 10] minor: [ 7.. 7]
Sequence: major: [ 9.. 14] minor: [ 6.. 9] down
Sequence: major: [ 11.. 11] minor: [ 9.. 9] down
Sequence: major: [ 4.. 33] minor: [ 1.. 5] down palm
The example output shows five completed touch sequences. For each, the
respective minimum and maximum pressure values are printed as well as some
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
output may change frequently. Refer to the <i>libinput-measure-touch-size(1)</i> man
page for more details.
By default, this tool uses the :ref:`device-quirks` for the touch size range. To
narrow down on the best values for your device, specify the 'logically down'
and 'logically up' pressure thresholds with the ``--touch-thresholds``
arguments as in the example above.
Interact with the touchpad and check if the output of this tool matches your
expectations.
.. note:: This is an interactive process. You will need to re-run the
tool with varying thresholds until you find the right range for
your touchpad. Attaching output logs to a bug will not help, only
you with access to the hardware can figure out the correct
ranges.
Once the thresholds are decided on (e.g. 10 and 8), they can be enabled with
:ref:`device-quirks` entry similar to this: ::
$> cat /etc/libinput/local-overrides.quirks
[Touchpad touch size override]
MatchUdevType=touchpad
MatchName=*SynPS/2 Synaptics TouchPad
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadX230*
AttrTouchSizeRange=10:8
The first line is the match line and should be adjusted for the device name
(see evemu-record's output) and for the local system, based on the
information in ``/sys/class/dmi/id/modalias``. The modalias should be
shortened to the specific system's information, usually system vendor (svn)
and product name (pn).
Once in place, run the following command to verify the quirk is valid and
works for your device: ::
$ sudo libinput list-quirks /dev/input/event10
AttrTouchSizeRange=10:8
Replace the event node with the one from your device. If the
``AttrTouchSizeRange`` quirk does not show up, re-run with ``--verbose`` and
check the output for any error messages.
If the touch size range property shows up correctly, restart X or the
Wayland compositor and libinput should now use the correct thresholds.
The :ref:`tools` can be used to verify the correct functionality first without
the need for a restart.
Once the touch size ranges are deemed correct, :ref:`reporting_bugs` "report a
bug" to get the thresholds into the repository.

View file

@ -1,89 +0,0 @@
.. _thumb_detection:
==============================================================================
Thumb detection
==============================================================================
Thumb detection tries to identify touches triggered by a thumb rather than a
pointer-moving finger. This is necessary on :ref:`touchpads_buttons_clickpads`
as a finger pressing a button always creates a new touch, causing
misinterpretation of gestures. Click-and-drag with two fingers (one holding
the button, one moving) would be interpreted as two-finger scrolling without
working thumb detection.
libinput has built-in thumb detection, partially dependent on
hardware-specific capabilities.
- :ref:`thumb_pressure`
- :ref:`thumb_areas`
- :ref:`thumb_speed`
Thumb detection uses multiple approaches and the final decision on whether
to ignore a thumb depends on the interaction at the time.
.. _thumb_pressure:
------------------------------------------------------------------------------
Thumb detection based on pressure or size
------------------------------------------------------------------------------
The simplest form of thumb detection identifies a touch as thumb when the
pressure value goes above a certain threshold. This threshold is usually
high enough that it cannot be triggered by a finger movement.
On touchpads that support the ``ABS_MT_TOUCH_MAJOR`` axes, libinput can perform
thumb detection based on the size of the touch ellipse. This works similar to
the pressure-based palm detection in that a touch is labelled as palm when
it exceeds the (device-specific) touch size threshold.
Pressure- and size-based thumb detection depends on the location of the
thumb and usually only applies within the :ref:`thumb_areas`.
For some information on how to detect pressure on a touch and debug the
pressure ranges, see :ref:`touchpad_pressure`. Pressure- and size-based
thumb detection require thresholds set in the :ref:`device-quirks`.
.. _thumb_areas:
------------------------------------------------------------------------------
Thumb detection areas
------------------------------------------------------------------------------
Pressure and size readings are unreliable at the far bottom of the touchpad.
A thumb hanging mostly off the touchpad will have a small surface area.
libinput has a definitive thumb zone where any touch is considered a
thumb. Immediately above that area is the area where libinput will label a
thumb as such if the pressure or size thresholds are exceeded.
.. figure:: thumb-detection.svg
:align: center
The picture above shows the two detection areas. In the larger (light red)
area, a touch is labelled as thumb when it exceeds a device-specific
pressure threshold. In the lower (dark red) area, a touch is always labelled
as thumb.
Moving outside the areas generally releases the thumb from being a thumb.
.. _thumb_speed:
------------------------------------------------------------------------------
Thumb movement based on speed
------------------------------------------------------------------------------
Regular interactions with thumbs do not usually move the thumb. When fingers
are moving across the touchpad and a thumb is dropped, this can cause
erroneous scroll motion or similar issues. libinput observes the finger
motion speed for all touches - where a finger has been moving a newly
dropped finger is more likely to be labeled as thumb.
------------------------------------------------------------------------------
Thumb detection based on finger positions
------------------------------------------------------------------------------
The shape of the human hand and the interactions that usually involve a
thumb imply that a thumb is situated in a specific position relative to
other fingers (usually to the side and below). This is used by libinput to
detect thumbs during some interactions that do not implicitly require a
thumb (e.g. pinch-and-rotate).

View file

@ -1,5 +1,3 @@
:orphan:
.. _touchpads: .. _touchpads:
============================================================================== ==============================================================================
@ -17,7 +15,7 @@ other properties.
Number of buttons Number of buttons
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
.. _touchpads_buttons_phys: .. _touchapds_buttons_phys:
.............................................................................. ..............................................................................
Physically separate buttons Physically separate buttons
@ -25,7 +23,7 @@ Physically separate buttons
Touchpads with physical buttons usually provide two buttons, left and right. Touchpads with physical buttons usually provide two buttons, left and right.
A few touchpads with three buttons exist, and Apple used to have touchpads A few touchpads with three buttons exist, and Apple used to have touchpads
with a single physical button until ca 2008. Touchpads with only two with a single physical buttons until ca 2008. Touchpads with only two
buttons require the software stack to emulate a middle button. libinput does buttons require the software stack to emulate a middle button. libinput does
this when both buttons are pressed simultaneously. this when both buttons are pressed simultaneously.
@ -51,13 +49,13 @@ whole, i.e. a user presses down on the touch area and triggers a physical
click. Clickpads thus only provide a single button, everything else needs to click. Clickpads thus only provide a single button, everything else needs to
be software-emulated. See :ref:`clickpad_softbuttons` for more information. be software-emulated. See :ref:`clickpad_softbuttons` for more information.
Clickpads are labelled by the kernel with the **INPUT_PROP_BUTTONPAD** input Clickpads are labelled by the kernel with the @c INPUT_PROP_BUTTONPAD input
property. 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 +63,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 +77,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
@ -89,9 +86,9 @@ Single-touch touchpads
Single-finger touchpads can track a single touchpoint. Most single-touch Single-finger touchpads can track a single touchpoint. Most single-touch
touchpads can also detect three fingers on the touchpad, but no positional touchpads can also detect three fingers on the touchpad, but no positional
information is provided for those. In libinput, these touches are termed information is provided for those. In libinput, these touches are termed
"fake touches". The kernel sends **BTN_TOOL_DOUBLETAP**, "fake touches". The kernel sends @c BTN_TOOL_DOUBLETAP,
**BTN_TOOL_TRIPLETAP**, **BTN_TOOL_QUADTAP** and **BTN_TOOL_QUINTTAP** @c BTN_TOOL_TRIPLETAP, @c BTN_TOOL_QUADTAP and @c BTN_TOOL_QUINTTAP events when
events when multiple fingers are detected. multiple fingers are detected.
.. _touchpads_touch_mt: .. _touchpads_touch_mt:
@ -109,10 +106,10 @@ provide an ellipse and the orientation of the ellipse for each touch point.
Other touchpads provide a pressure value for each touch point (see Other touchpads provide a pressure value for each touch point (see
:ref:`touchpads_pressure_handling`). :ref:`touchpads_pressure_handling`).
Note that the kernel sends **BTN_TOOL_DOUBLETAP**, Note that the kernel sends @c BTN_TOOL_DOUBLETAP,
**BTN_TOOL_TRIPLETAP**, **BTN_TOOL_QUADTAP** and **BTN_TOOL_QUINTTAP** @c BTN_TOOL_TRIPLETAP, @c BTN_TOOL_QUADTAP and @c BTN_TOOL_QUINTTAP events for
events for all touches for backwards compatibility. libinput ignores these all touches for backwards compatibility. libinput ignores these events if
events if the touchpad can track touches correctly. the touchpad can track touches correctly.
.. _touchpads_touch_partial_mt: .. _touchpads_touch_partial_mt:
@ -128,8 +125,8 @@ five.
The number of slots may limit which features are available in libinput. The number of slots may limit which features are available in libinput.
Any device with two slots can support two-finger scrolling, but Any device with two slots can support two-finger scrolling, but
:ref:`thumb-detection` or :ref:`palm_detection` may be limited if only two :ref:`thumb-detection` or @ref palm_detection may be limited if only two slots are
slots are available. available.
.. _touchpads_touch_semi_mt: .. _touchpads_touch_semi_mt:
@ -147,7 +144,7 @@ Many semi-mt touchpads also have a lower resolution for the second touch, or
both touches. This may limit some features such as :ref:`gestures` or both touches. This may limit some features such as :ref:`gestures` or
:ref:`scrolling`. :ref:`scrolling`.
Semi-mt are labelled by the kernel with the **INPUT_PROP_SEMI_MT** input Semi-mt are labelled by the kernel with the @c INPUT_PROP_SEMI_MT input
property. property.
.. _touchpads_mis: .. _touchpads_mis:

View file

@ -1,154 +0,0 @@
.. _trackpoint_configuration:
==============================================================================
Trackpoint configuration
==============================================================================
The sections below describe the trackpoint magic multiplier and how to apply
it to your local device. See :ref:`trackpoint_range` for an explanation on
why this multiplier is needed.
.. note:: The magic trackpoint multiplier **is not user visible configuration**. It is
part of the :ref:`device-quirks` system and provided once per device.
User-specific preferences can be adjusted with the
:ref:`config_pointer_acceleration` setting.
.. _trackpoint_multiplier:
------------------------------------------------------------------------------
The magic trackpoint multiplier
------------------------------------------------------------------------------
To accommodate for the wildly different input data on trackpoint, libinput
uses a multiplier that is applied to input deltas. Trackpoints that send
comparatively high deltas can be "slowed down", trackpoints that send low
deltas can be "sped up" to match the expected range. The actual acceleration
profile is applied to these pre-multiplied deltas.
Given a trackpoint delta ``(dx, dy)``, a multiplier ``M`` and a pointer acceleration
function ``f(dx, dy) → (dx', dy')``, the algorithm is effectively:
::
f(M * dx, M * dy) → (dx', dy')
.. _trackpoint_multiplier_adjustment:
..............................................................................
Adjusting the magic trackpoint multiplier
..............................................................................
This section only applies if:
- the trackpoint default speed (speed setting 0) is unusably slow or
unusably fast, **and**
- the lowest speed setting (-1) is still too fast **or** the highest speed
setting is still too slow, **and**
- the :ref:`device-quirks` for this device do not list a trackpoint multiplier
(see :ref:`device-quirks-debugging`)
If the only satisfactory speed settings are less than -0.75 or greater than
0.75, a multiplier *may* be required.
A specific multiplier will apply to **all users with the same laptop
model**, so proceed with caution. You must be capable/willing to adjust
device quirks, build libinput from source and restart the session frequently
to adjust the multiplier. If this does not apply, wait for someone else with
the same hardware to do this.
Finding the correct multiplier is difficult and requires some trial and
error. The default multiplier is always 1.0. A value between 0.0 and 1.0
slows the trackpoint down, a value above 1.0 speeds the trackpoint up.
Values below zero are invalid.
.. warning:: The multiplier is not a configuration to adjust to personal
preferences. The multiplier normalizes the input data into a range that
can then be configured with the speed setting.
To adjust the local multiplier, first
:ref:`build libinput from git master <building_libinput>`. It is not
required to install libinput from git. The below assumes that all
:ref:`building_dependencies` are already
installed.
::
$ cd path/to/libinput.git
# Use an approximate multiplier in the quirks file
$ cat > quirks/99-trackpoint-override.quirks <<EOF
[Trackpoint Override]
MatchUdevType=pointingstick
AttrTrackpointMultiplier=1.0
EOF
# Use your trackpoint's event node. If the Attr does not show up
# then the quirk does not apply to your trackpoint.
$ ./builddir/libinput quirks list /dev/input/event18
AttrTrackpointMultiplier=1.0
# Now start a GUI program to debug the trackpoint speed.
# ESC closes the debug GUI
$ sudo ./builddir/libinput debug-gui
Replace the multiplier with an approximate value and the event node with
your trackpoint's event node. Try to use trackpoint and verify the
multiplier is good enough. If not, adjust the ``.quirks`` file and re-run the
``libinput debug-gui``. Note that the ``libinput debug-gui`` always feels
less responsive than libinput would behave in a normal install.
Once the trackpoint behaves correctly you are ready to test the system
libinput:
::
$ sudo cp quirks/99-trackpoint-override.quirks /etc/libinput/local-overrides.quirks
Now verify the override is seen by the system libinput
::
$ libinput quirks list
AttrTrackpointMultiplier=1.0
If the multiplier is listed, restart your Wayland session or X server. The
new multiplier is now applied to your trackpoint.
If the trackpoint behavior is acceptable, you are ready to submit this file
upstream. First, find add a more precise match for the device so it only
applies to the built-in trackpoint on your laptop model. Usually a
variation of the following is sufficient:
::
[Trackpoint Override]
MatchUdevType=pointingstick
MatchName=*TPPS/2 IBM TrackPoint*
MatchDMIModalias=dmi:*:svnLENOVO:*:pvrThinkPadT440p:*
AttrTrackpointMultiplier=1.0
Look at your ``/sys/class/dmi/id/modalias`` file for the values to add. Verify
that ``libinput quirks list`` still shows the ``AttrTrackpointMultiplier``. If
it does, then you should :ref:`report a bug <reporting_bugs>` with the contents of
the file. Alternatively, file a merge request with the data added.
.. _trackpoint_range_measure:
------------------------------------------------------------------------------
Measuring the trackpoint range
------------------------------------------------------------------------------
This section only applied to libinput version 1.9.x, 1.10.x, and 1.11.x and
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
`the 1.11.0 documentation <https://wayland.freedesktop.org/libinput/doc/1.11.0/trackpoints.html#trackpoint_range_measure>`_

View file

@ -5,27 +5,21 @@ 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.
.. figure:: button-scrolling.svg .. figure:: button-scrolling.svg
:align: center :align: center
A trackpoint A trackpoint"
libinput always treats the buttons below the space bar as the buttons that libinput always treats the buttons below the space bar as the buttons that
belong to the trackpoint even on the few laptops where the buttons are not belong to the trackpoint even on the few laptops where the buttons are not
physically wired to the trackpoint device anyway, see :ref:`t440_support`. physically wired to the trackpoint device anyway, see :ref:`t440_support`.
.. _trackpoint_buttonscroll:
------------------------------------------------------------------------------
Button scrolling on trackpoints
------------------------------------------------------------------------------
Trackpoint devices have :ref:`button_scrolling` enabled by default. This may Trackpoint devices have :ref:`button_scrolling` enabled by default. This may
interfere with middle-button dragging, if middle-button dragging is required interfer with middle-button dragging, if middle-button dragging is required
by a user then button scrolling must be disabled. by a user then button scrolling must be disabled.
.. _trackpoint_range: .. _trackpoint_range:
@ -48,10 +42,9 @@ the delta values increase. The figure below shows a rough illustration of
this concept. As the pressure this concept. As the pressure
decreases, the delta decrease first, then the reporting rate until the 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 hart to generalize, see
`Observations on trackpoint input data <a href="https://who-t.blogspot.com/2018/06/observations-on-trackpoint-input-data.html">
<https://who-t.blogspot.com/2018/06/observations-on-trackpoint-input-data.html>`_ Observations on trackpoint input data</a> for more details.
for more details.
.. figure:: trackpoint-delta-illustration.svg .. figure:: trackpoint-delta-illustration.svg
:align: center :align: center
@ -63,5 +56,146 @@ maximum delta value of 30, others can go beyond 100. However, the useful
delta range is a fraction of the maximum range. It is uncomfortable to exert delta range is a fraction of the maximum range. It is uncomfortable to exert
sufficient pressure to even get close to the maximum ranges. sufficient pressure to even get close to the maximum ranges.
libinput provides a :ref:`Magic Trackpoint Multiplier .. _trackpoint_multiplier:
<trackpoint_multiplier>` to normalize the trackpoint input data.
------------------------------------------------------------------------------
The magic trackpoint multiplier
------------------------------------------------------------------------------
To accomodate for the wildly different input data on trackpoint, libinput
uses a multiplier that is applied to input deltas. Trackpoints that send
comparatively high deltas can be "slowed down", trackpoints that send low
deltas can be "sped up" to match the expected range. The actual acceleration
profile is applied to these pre-multiplied deltas.
Given a trackpoint delta (dx, dy), a multiplier M and a pointer acceleration
function f(dx, dy) → (dx', dy'), the algorithm is effectively:
::
f(M * dx, M * dy) → (dx', dy')
The magic trackpoint multiplier **is not user visible configuration**. It is
part of the :ref:`device-quirks` system and provided once per device.
User-specific preferences can be adjusted with the pointer acceleration speed
setting **libinput_device_config_accel_set_speed()**.
.. _trackpoint_multiplier_adjustment:
..............................................................................
Adjusting the magic trackpoint multiplier
..............................................................................
This section only applies if:
- the trackpoint default speed (speed setting 0) is unusably slow or
unusably fast, **and**
- the lowest speed setting (-1) is still too fast **or** the highest speed
setting is still too slow, **and**
- the :ref:`device-quirks` for this device do not list a trackpoint multiplier
(see :ref:`device-quirks-debugging`)
If the only satisfactory speed settings are less than -0.75 or greater than
0.75, a multiplier *may* be required.
A specific multiplier will apply to **all users with the same laptop
model**, so proceed with caution. You must be capable/willing to adjust
device quirks, build libinput from source and restart the session frequently
to adjust the multiplier. If this does not apply, wait for someone else with
the same hardware to do this.
Finding the correct multiplier is difficult and requires some trial and
error. The default multiplier is always 1.0. A value between 0.0 and 1.0
slows the trackpoint down, a value above 1.0 speeds the trackpoint up.
Values below zero are invalid.
.. note:: The multiplier is not a configuration to adjust to personal
preferences. The multiplier normalizes the input data into a range that
can then be configured with the speed setting.
To adjust the local multiplier, first :ref:`building_libinput`
"build libinput from git master". It is not required to install libinput
from git. The below assumes that all :ref:`building_dependencies` are already
installed.
::
$ cd path/to/libinput.git
# Use an approximate multiplier in the quirks file
$ cat > quirks/99-trackpont-override.quirks <<EOF
[Trackpoint Override]
MatchUdevType=pointingstick
AttrTrackpointMultiplier=1.0
EOF
# Use your trackpoint's event node. If the Attr does not show up
# then the quirk does not apply to your trackpoint.
$ ./builddir/libinput quirks list /dev/input/event18
AttrTrackpointMultiplier=1.0
# Now start a GUI program to debug the trackpoint speed.
# ESC closes the debug GUI
$ sudo ./builddir/libinput debug-gui
Replace the multiplier with an approximate value and the event node with
your trackpoint's event node. Try to use trackpoint and verify the
multiplier is good enough. If not, adjust the ``.quirks`` file and re-run the
``libinput debug-gui``. Note that the ``libinput debug-gui`` always feels
less responsive than libinput would behave in a normal install.
Once the trackpoint behaves correctly you are ready to test the system
libinput:
::
$ sudo cp quirks/99-trackpoint-override.quirks /etc/libinput/local-overrides.quirks
Now verify the override is seen by the system libinput
::
$ libinput quirks list
AttrTrackpointMultiplier=1.0
If the multiplier is listed, restart your Wayland session or X server. The
new multiplier is now applied to your trackpoint.
If the trackpoint behavior is acceptable, you are ready to submit this file
upstream. First, find add a more precise match for the device so it only
applies to the built-in trackpoint on your laptop model. Usually a
variation of the following is sufficient:
::
[Trackpoint Override]
MatchUdevType=pointingstick
MatchName=*TPPS/2 IBM TrackPoint*
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadT440p*
AttrTrackpointMultiplier=1.0
Look at your ``/sys/class/dmi/id/modalias`` file for the values to add. Verify
that ``libinput quirks list`` still shows the ``AttrTrackpointMultiplier``. If
it does, then you should :ref:`report a bug <reporting_bugs>` with the contents of
the file. Alternatively, file a merge request with the data added.
.. _trackpoint_range_measure:
------------------------------------------------------------------------------
Measuring the trackpoint range
------------------------------------------------------------------------------
This section only applied to libinput version 1.9.x, 1.10.x, and 1.11.x and
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
`the 1.11.0 documentation <https://wayland.freedesktop.org/libinput/doc/1.11.0/trackpoints.html#trackpoint_range_measure>`_

View file

@ -9,11 +9,3 @@ Troubleshooting
tools.rst tools.rst
device-quirks.rst device-quirks.rst
touchpad-jumping-cursors.rst
touchpad-jitter.rst
touchpad-pressure-debugging.rst
trackpoint-configuration.rst
tablet-debugging.rst
incorrectly-enabled-hires.rst
clickpad-with-right-button.rst
ignoring-devices.rst

View file

@ -14,26 +14,26 @@ what libinput is **not**.
What libinput is What libinput is
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
libinput is an input stack for processes that need to provide events from libinput is an input stack to be used by those applications that need full
commonly used input devices. That includes mice, keyboards, touchpads, input device processing by commonly used input devices. That includes mice,
touchscreens and graphics tablets. libinput handles device-specific quirks keyboards, touchpads, touchscreens and graphics tablets. libinput handles
and provides an easy-to-use API to receive events from devices. device-specific quirks and provides an easy-to-use interface to receive
events from devices.
libinput is designed to handle all input devices available on a system but libinput is designed to handle all input devices available on a system. It
it is possible to limit which devices libinput has access to. is possible to limit the devices that employ libinput. For example, the use
For example, the use of xf86-input-libinput depends on xorg.conf snippets of xf86-input-libinput depends on xorg.conf snippets for specific
for specific devices. But libinput works best if it handles all input devices. But libinput works best if it handles all input devices as this
devices as this allows for smarter handling of features that affect multiple allows for cross-device monitoring of events and smarter handling of
devices. features that affect multiple devices.
libinput restricts device-specific features to those devices that require libinput restricts device-specific features to applicable devices only.
those features. One example for this are the top software buttons on the Devices with specific hardware properties may expose extra features, but
touchpad in the Lenovo T440. While there may be use-cases for providing top these features are not made available on other devices, even where it may be
software buttons on other devices, libinput does not do so. possible to do so. One example for this are the top software buttons on the
touchpad in the Lenovo T440 and similar devices. While there may be
`This introductory blog post from 2015 use-cases for providing top software buttons on other devices, libinput does
<https://who-t.blogspot.com/2015/06/libinput-and-lack-of-device-types.html>`_ not do so.
describes some of the motivations.
.. _what_libinput_is_not: .. _what_libinput_is_not:
@ -49,9 +49,10 @@ not land in libinput master until the devices are commonly available.
libinput is **not** a box of legos. It does not provide the pieces to libinput is **not** a box of legos. It does not provide the pieces to
assemble a selection of features. Many features can be disabled through assemble a selection of features. Many features can be disabled through
configuration options, but some features are hardcoded and/or only available configuration options, but some features are hardcoded or hardcoded on some
on some devices. There are plenty of use-cases to provide niche features, devices. This usually matches the intended use of the device. There are
but libinput is not the place to support these. plenty of use-cases to provide out-of-the-ordinary features, but libinput is
not the place to support these.
libinput is **not** a showcase for features. There are a lot of potential libinput is **not** a showcase for features. There are a lot of potential
features that could be provided on input devices. But unless they have features that could be provided on input devices. But unless they have
@ -106,49 +107,3 @@ does not know whether libinput is in use.
libinput and xf86-input-libinput are not a requirement, the driver will only libinput and xf86-input-libinput are not a requirement, the driver will only
handle those devices explicitly assigned through an xorg.conf.d snippets. It handle those devices explicitly assigned through an xorg.conf.d snippets. It
is possible to mix xf86-input-libinput with other X.Org drivers. is possible to mix xf86-input-libinput with other X.Org drivers.
------------------------------------------------------------------------------
Device types
------------------------------------------------------------------------------
libinput handles all common devices used to interact with a desktop system.
This includes mice, keyboards, touchscreens, touchpads and graphics tablets.
libinput does not expose the device type to the caller, it solely provides
capabilities and the attached features (see
`this blog post <https://who-t.blogspot.com/2015/06/libinput-and-lack-of-device-types.html>`_).
For example, a touchpad in libinput is a device that provides pointer
events, gestures and has a number of :ref:`config_options` such as
:ref:`tapping`. A caller may present the device as touchpad to the user, or
simply as device with a config knob to enable or disable tapping.
..............................................................................
Handled device types
..............................................................................
- :ref:`Touchpads`
- Touchscreens
- Mice
- Keyboards
- Virtual absolute pointing devices such as those used by QEMU or VirtualBox
- Switches (Lid Switch, Tablet Mode switch, and Keypad Slide switch)
- Graphics tablets
- :ref:`Trackpoints`
If a device falls into one of the above categories but does not work as
expected, please :ref:`file a bug <reporting_bugs>`.
..............................................................................
Unhandled device types
..............................................................................
libinput does not handle some devices. The primary reason is that these
device have no clear interaction with a desktop environment.
Joysticks:
Joysticks have one or more axes and one or more buttons. Beyond that it is
difficult to find common ground between joysticks and much of the
interaction is application-specific, not system-specific. libinput does not
provide support for joysticks for that reason, any abstraction libinput
would provide for joysticks would be so generic that libinput would
merely introduce complexity and processing delays for no real benefit.

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 more 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,3 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/* /*
* Input event codes * Input event codes
* *
@ -27,7 +26,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 +277,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
@ -409,7 +406,6 @@
#define BTN_TOOL_MOUSE 0x146 #define BTN_TOOL_MOUSE 0x146
#define BTN_TOOL_LENS 0x147 #define BTN_TOOL_LENS 0x147
#define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */ #define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */
#define BTN_STYLUS3 0x149
#define BTN_TOUCH 0x14a #define BTN_TOUCH 0x14a
#define BTN_STYLUS 0x14b #define BTN_STYLUS 0x14b
#define BTN_STYLUS2 0x14c #define BTN_STYLUS2 0x14c
@ -441,12 +437,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 +511,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 +538,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 +591,7 @@
#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_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 */
@ -618,31 +600,10 @@
#define KEY_APPSELECT 0x244 /* AL Select Task/Application */ #define KEY_APPSELECT 0x244 /* AL Select Task/Application */
#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_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 +642,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
@ -847,16 +704,6 @@
#define REL_DIAL 0x07 #define REL_DIAL 0x07
#define REL_WHEEL 0x08 #define REL_WHEEL 0x08
#define REL_MISC 0x09 #define REL_MISC 0x09
/*
* 0x0a is reserved and should not be used in input drivers.
* It was used by HID as REL_MISC+1 and userspace needs to detect if
* the next REL_* event is correct or is just REL_MISC + n.
* We define here REL_RESERVED so userspace can rely on it and detect
* the situation described above.
*/
#define REL_RESERVED 0x0a
#define REL_WHEEL_HI_RES 0x0b
#define REL_HWHEEL_HI_RES 0x0c
#define REL_MAX 0x0f #define REL_MAX 0x0f
#define REL_CNT (REL_MAX+1) #define REL_CNT (REL_MAX+1)
@ -890,19 +737,9 @@
#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
/*
* 0x2e is reserved and should not be used in input drivers.
* It was used by HID as ABS_MISC+6 and userspace needs to detect if
* the next ABS_* event is correct or is just ABS_MISC + n.
* We define here ABS_RESERVED so userspace can rely on it and detect
* the situation described above.
*/
#define ABS_RESERVED 0x2e
#define ABS_MT_SLOT 0x2f /* MT slot being modified */ #define ABS_MT_SLOT 0x2f /* MT slot being modified */
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */ #define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */ #define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
@ -919,7 +756,6 @@
#define ABS_MT_TOOL_X 0x3c /* Center X tool position */ #define ABS_MT_TOOL_X 0x3c /* Center X tool position */
#define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */ #define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */
#define ABS_MAX 0x3f #define ABS_MAX 0x3f
#define ABS_CNT (ABS_MAX+1) #define ABS_CNT (ABS_MAX+1)
@ -945,9 +781,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

@ -269,11 +269,10 @@ struct input_mask {
/* /*
* MT_TOOL types * MT_TOOL types
*/ */
#define MT_TOOL_FINGER 0x00 #define MT_TOOL_FINGER 0
#define MT_TOOL_PEN 0x01 #define MT_TOOL_PEN 1
#define MT_TOOL_PALM 0x02 #define MT_TOOL_PALM 2
#define MT_TOOL_DIAL 0x0a #define MT_TOOL_MAX 2
#define MT_TOOL_MAX 0x0f
/* /*
* Values describing the status of a force-feedback effect * Values describing the status of a force-feedback effect

View file

@ -1,4 +1,3 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/* /*
* Input event codes * Input event codes
* *
@ -27,7 +26,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 +277,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
@ -409,7 +406,6 @@
#define BTN_TOOL_MOUSE 0x146 #define BTN_TOOL_MOUSE 0x146
#define BTN_TOOL_LENS 0x147 #define BTN_TOOL_LENS 0x147
#define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */ #define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */
#define BTN_STYLUS3 0x149
#define BTN_TOUCH 0x14a #define BTN_TOUCH 0x14a
#define BTN_STYLUS 0x14b #define BTN_STYLUS 0x14b
#define BTN_STYLUS2 0x14c #define BTN_STYLUS2 0x14c
@ -441,12 +437,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 +511,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 +538,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 +591,7 @@
#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_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 */
@ -618,31 +600,10 @@
#define KEY_APPSELECT 0x244 /* AL Select Task/Application */ #define KEY_APPSELECT 0x244 /* AL Select Task/Application */
#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_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 +642,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
@ -847,16 +704,6 @@
#define REL_DIAL 0x07 #define REL_DIAL 0x07
#define REL_WHEEL 0x08 #define REL_WHEEL 0x08
#define REL_MISC 0x09 #define REL_MISC 0x09
/*
* 0x0a is reserved and should not be used in input drivers.
* It was used by HID as REL_MISC+1 and userspace needs to detect if
* the next REL_* event is correct or is just REL_MISC + n.
* We define here REL_RESERVED so userspace can rely on it and detect
* the situation described above.
*/
#define REL_RESERVED 0x0a
#define REL_WHEEL_HI_RES 0x0b
#define REL_HWHEEL_HI_RES 0x0c
#define REL_MAX 0x0f #define REL_MAX 0x0f
#define REL_CNT (REL_MAX+1) #define REL_CNT (REL_MAX+1)
@ -890,19 +737,9 @@
#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
/*
* 0x2e is reserved and should not be used in input drivers.
* It was used by HID as ABS_MISC+6 and userspace needs to detect if
* the next ABS_* event is correct or is just ABS_MISC + n.
* We define here ABS_RESERVED so userspace can rely on it and detect
* the situation described above.
*/
#define ABS_RESERVED 0x2e
#define ABS_MT_SLOT 0x2f /* MT slot being modified */ #define ABS_MT_SLOT 0x2f /* MT slot being modified */
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */ #define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */ #define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
@ -919,7 +756,6 @@
#define ABS_MT_TOOL_X 0x3c /* Center X tool position */ #define ABS_MT_TOOL_X 0x3c /* Center X tool position */
#define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */ #define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */
#define ABS_MAX 0x3f #define ABS_MAX 0x3f
#define ABS_CNT (ABS_MAX+1) #define ABS_CNT (ABS_MAX+1)
@ -945,9 +781,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

@ -268,11 +268,10 @@ struct input_mask {
/* /*
* MT_TOOL types * MT_TOOL types
*/ */
#define MT_TOOL_FINGER 0x00 #define MT_TOOL_FINGER 0
#define MT_TOOL_PEN 0x01 #define MT_TOOL_PEN 1
#define MT_TOOL_PALM 0x02 #define MT_TOOL_PALM 2
#define MT_TOOL_DIAL 0x0a #define MT_TOOL_MAX 2
#define MT_TOOL_MAX 0x0f
/* /*
* Values describing the status of a force-feedback effect * Values describing the status of a force-feedback effect

File diff suppressed because it is too large Load diff

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