Compare commits
No commits in common. "main" and "0.6.0" have entirely different histories.
|
|
@ -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;"]
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
include/**/*
|
|
||||||
|
|
@ -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: '*'
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
include/*
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
((nil . ((indent-tabs-mode . t)
|
|
||||||
(tab-width . 8)
|
|
||||||
(fill-column . 80)))
|
|
||||||
(c-mode . ((c-basic-offset . 8))))
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
38
.gitignore
vendored
|
|
@ -1,12 +1,30 @@
|
||||||
|
*.o
|
||||||
|
*.pc
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
*.swp
|
*.swp
|
||||||
*~
|
Makefile
|
||||||
*.sig
|
Makefile.in
|
||||||
*.tar.*
|
aclocal.m4
|
||||||
*.announce
|
autom4te.cache/
|
||||||
*.patch
|
config.guess
|
||||||
*.rej
|
config.h
|
||||||
*.trs
|
config.h.in
|
||||||
*.gcda
|
config.log
|
||||||
*.gcno
|
config.status
|
||||||
|
config.sub
|
||||||
|
configure
|
||||||
|
depcomp
|
||||||
|
install-sh
|
||||||
|
libtool
|
||||||
|
ltmain.sh
|
||||||
|
missing
|
||||||
|
stamp-h1
|
||||||
|
.libs/
|
||||||
|
.deps/
|
||||||
|
src/libinput-version.h
|
||||||
|
doc/libinput.doxygen
|
||||||
|
doc/html
|
||||||
tags
|
tags
|
||||||
*.gnuplot
|
test/test-*
|
||||||
|
test-driver
|
||||||
|
|
|
||||||
1362
.gitlab-ci.yml
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
scan-build -v --status-bugs -plist-html "$@"
|
|
||||||
|
|
@ -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()
|
|
||||||
|
|
@ -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"
|
|
||||||
|
|
@ -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"
|
|
||||||
|
|
@ -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]
|
|
||||||
|
|
@ -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
|
|
||||||
1
.vimdir
|
|
@ -1 +0,0 @@
|
||||||
set noexpandtab shiftwidth=8 cinoptions=:0,+0,(0
|
|
||||||
244
CODING_STYLE.md
|
|
@ -1,244 +0,0 @@
|
||||||
# Coding style
|
|
||||||
|
|
||||||
- Indentation in tabs, 8 characters wide, spaces after the tabs where
|
|
||||||
vertical alignment is required (see below)
|
|
||||||
|
|
||||||
**Note: this file uses spaces due to markdown rendering issues for tabs.
|
|
||||||
Code must be implemented using tabs.**
|
|
||||||
|
|
||||||
- Max line width 80ch, do not break up printed strings though
|
|
||||||
|
|
||||||
- Break up long lines at logical groupings, one line for each logical group
|
|
||||||
|
|
||||||
```c
|
|
||||||
int a = somelongname() +
|
|
||||||
someotherlongname();
|
|
||||||
|
|
||||||
if (a < 0 &&
|
|
||||||
(b > 20 & d < 10) &&
|
|
||||||
d != 0.0)
|
|
||||||
|
|
||||||
|
|
||||||
somelongfunctioncall(arg1,
|
|
||||||
arg2,
|
|
||||||
arg3);
|
|
||||||
```
|
|
||||||
|
|
||||||
- Function declarations: return type on separate line, {} on separate line,
|
|
||||||
arguments broken up as above.
|
|
||||||
|
|
||||||
```c
|
|
||||||
static inline int
|
|
||||||
foobar(int a, int b)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
somenamethatiswaytoolong(int a,
|
|
||||||
int b,
|
|
||||||
int c)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- `/* comments only */`, no `// comments`
|
|
||||||
|
|
||||||
- `variable_name`, not `VariableName` or `variableName`. same for functions.
|
|
||||||
|
|
||||||
- no typedefs of structs, enums, unions
|
|
||||||
|
|
||||||
- if it generates a compiler warning, it needs to be fixed
|
|
||||||
- if it generates a static checker warning, it needs to be fixed or
|
|
||||||
commented
|
|
||||||
|
|
||||||
- declare variables when they are used first and try to keep them as local as possible.
|
|
||||||
Exception: basic loop variables, e.g. for (int i = 0; ...) should always be
|
|
||||||
declared inside the loop even where multiple loops exist
|
|
||||||
|
|
||||||
```c
|
|
||||||
int a;
|
|
||||||
|
|
||||||
if (foo) {
|
|
||||||
int b = 10;
|
|
||||||
|
|
||||||
a = get_value();
|
|
||||||
usevalue(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bar) {
|
|
||||||
a = get_value();
|
|
||||||
useit(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
int c = a * 100;
|
|
||||||
useit(c);
|
|
||||||
```
|
|
||||||
|
|
||||||
- avoid uninitialized variables where possible, declare them late instead.
|
|
||||||
Note that most of libinput predates this style, try to stick with the code
|
|
||||||
around you if in doubt.
|
|
||||||
|
|
||||||
wrong:
|
|
||||||
|
|
||||||
```c
|
|
||||||
int *a;
|
|
||||||
int b = 7;
|
|
||||||
|
|
||||||
... some code ...
|
|
||||||
|
|
||||||
a = zalloc(32);
|
|
||||||
```
|
|
||||||
|
|
||||||
right:
|
|
||||||
|
|
||||||
```c
|
|
||||||
int b = 7;
|
|
||||||
... some code ...
|
|
||||||
|
|
||||||
int *a = zalloc(32);
|
|
||||||
```
|
|
||||||
|
|
||||||
- avoid calling non-obvious functions inside declaration blocks for multiple
|
|
||||||
variables.
|
|
||||||
|
|
||||||
bad:
|
|
||||||
|
|
||||||
```c
|
|
||||||
{
|
|
||||||
int a = 7;
|
|
||||||
int b = some_complicated_function();
|
|
||||||
int *c = zalloc(32);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
better:
|
|
||||||
```c
|
|
||||||
{
|
|
||||||
int a = 7;
|
|
||||||
int *c = zalloc(32);
|
|
||||||
|
|
||||||
int b = some_complicated_function();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
There is a bit of gut-feeling involved with this, but the goal is to make
|
|
||||||
the variable values immediately recognizable.
|
|
||||||
|
|
||||||
- Where statements are near-identical and repeated, try to keep them
|
|
||||||
identical:
|
|
||||||
|
|
||||||
bad:
|
|
||||||
```c
|
|
||||||
int a = get_some_value(x++);
|
|
||||||
do_something(a);
|
|
||||||
a = get_some_value(x++);
|
|
||||||
do_something(a);
|
|
||||||
a = get_some_value(x++);
|
|
||||||
do_something(a);
|
|
||||||
```
|
|
||||||
better:
|
|
||||||
|
|
||||||
```c
|
|
||||||
int a;
|
|
||||||
a = = get_some_value(x++);
|
|
||||||
do_something(a);
|
|
||||||
a = get_some_value(x++);
|
|
||||||
do_something(a);
|
|
||||||
a = get_some_value(x++);
|
|
||||||
do_something(a);
|
|
||||||
```
|
|
||||||
|
|
||||||
- if/else: { on the same line, no curly braces if both blocks are a single
|
|
||||||
statement. If either if or else block are multiple statements, both must
|
|
||||||
have curly braces.
|
|
||||||
|
|
||||||
```c
|
|
||||||
if (foo) {
|
|
||||||
blah();
|
|
||||||
bar();
|
|
||||||
} else {
|
|
||||||
a = 10;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- public functions MUST be doxygen-commented, use doxygen's `@foo` rather than
|
|
||||||
`\foo` notation
|
|
||||||
|
|
||||||
- `#include "config.h"` comes first, followed by system headers, followed by
|
|
||||||
external library headers, followed by internal headers.
|
|
||||||
sort alphabetically where it makes sense (specifically system headers)
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <libevdev/libevdev.h>
|
|
||||||
|
|
||||||
#include "libinput-private.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
- goto jumps only to the end of the function, and only for good reasons
|
|
||||||
(usually cleanup). goto never jumps backwards
|
|
||||||
|
|
||||||
- Use stdbool.h's bool for booleans within the library (instead of `int`).
|
|
||||||
Exception: the public API uses int, not bool.
|
|
||||||
|
|
||||||
# Git commit message requirements
|
|
||||||
|
|
||||||
Our CI will check the commit messages for a few requirements. Below is the
|
|
||||||
list of what we expect from a git commit.
|
|
||||||
|
|
||||||
## Commit message content
|
|
||||||
|
|
||||||
A [good commit message](http://who-t.blogspot.com/2009/12/on-commit-messages.html) needs to
|
|
||||||
answer three questions:
|
|
||||||
|
|
||||||
- Why is it necessary? It may fix a bug, it may add a feature, it may
|
|
||||||
improve performance, reliabilty, stability, or just be a change for the
|
|
||||||
sake of correctness.
|
|
||||||
- How does it address the issue? For short obvious patches this part can be
|
|
||||||
omitted, but it should be a high level description of what the approach
|
|
||||||
was.
|
|
||||||
- What effects does the patch have? (In addition to the obvious ones, this
|
|
||||||
may include benchmarks, side effects, etc.)
|
|
||||||
|
|
||||||
These three questions establish the context for the actual code changes, put
|
|
||||||
reviewers and others into the frame of mind to look at the diff and check if
|
|
||||||
the approach chosen was correct. A good commit message also helps
|
|
||||||
maintainers to decide if a given patch is suitable for stable branches or
|
|
||||||
inclusion in a distribution.
|
|
||||||
|
|
||||||
## Commit message format
|
|
||||||
|
|
||||||
The canonical git commit message format is:
|
|
||||||
|
|
||||||
```
|
|
||||||
one line as the subject line with a high-level note
|
|
||||||
|
|
||||||
full explanation of the patch follows after an empty line. This explanation
|
|
||||||
can be multiple paragraphs and is largely free-form. Markdown is not
|
|
||||||
supported.
|
|
||||||
|
|
||||||
You can include extra data where required like:
|
|
||||||
- benchmark one says 10s
|
|
||||||
- benchmark two says 12s
|
|
||||||
```
|
|
||||||
|
|
||||||
The subject line is the first thing everyone sees about this commit, so make
|
|
||||||
sure it's on point.
|
|
||||||
|
|
||||||
## Commit message technical requirements
|
|
||||||
|
|
||||||
- The commit message should use present tense (not past tense). Do write
|
|
||||||
"change foo to bar", not "changed foo to bar".
|
|
||||||
- The text width of the commit should be 78 chars or less, especially the
|
|
||||||
subject line.
|
|
||||||
- The author must be the name you usually identify as and email address. We do
|
|
||||||
not accept the default `@users.noreply` gitlab addresses.
|
|
||||||
```
|
|
||||||
git config --global user.name Your Name
|
|
||||||
git config --global user.email your@email
|
|
||||||
```
|
|
||||||
|
|
@ -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).
|
|
||||||
44
COPYING
|
|
@ -1,34 +1,24 @@
|
||||||
Copyright © 2006-2009 Simon Thum
|
|
||||||
Copyright © 2008-2012 Kristian Høgsberg
|
Copyright © 2008-2012 Kristian Høgsberg
|
||||||
Copyright © 2010-2012 Intel Corporation
|
Copyright © 2010-2012 Intel Corporation
|
||||||
Copyright © 2010-2011 Benjamin Franzke
|
Copyright © 2010-2011 Benjamin Franzke
|
||||||
Copyright © 2011-2012 Collabora, Ltd.
|
Copyright © 2011-2012 Collabora, Ltd.
|
||||||
Copyright © 2013-2014 Jonas Ådahl
|
Copyright © 2013-2014 Jonas Ådahl
|
||||||
Copyright © 2013-2015 Red Hat, Inc.
|
Copyright © 2013-2014 Red Hat, Inc.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
copy of this software and associated documentation files (the "Software"),
|
documentation for any purpose is hereby granted without fee, provided that
|
||||||
to deal in the Software without restriction, including without limitation
|
the above copyright notice appear in all copies and that both that copyright
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
notice and this permission notice appear in supporting documentation, and
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
that the name of the copyright holders not be used in advertising or
|
||||||
Software is furnished to do so, subject to the following conditions:
|
publicity pertaining to distribution of the software without specific,
|
||||||
|
written prior permission. The copyright holders make no representations
|
||||||
|
about the suitability of this software for any purpose. It is provided "as
|
||||||
|
is" without express or implied warranty.
|
||||||
|
|
||||||
The above copyright notice and this permission notice (including the next
|
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
paragraph) shall be included in all copies or substantial portions of the
|
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
Software.
|
EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
OF THIS SOFTWARE.
|
||||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
libinput ships a copy of the GPL-licensed Linux kernel's linux/input.h
|
|
||||||
header file. [1] This does not make libinput GPL.
|
|
||||||
This copy is provided to provide consistent behavior regardless which kernel
|
|
||||||
version libinput is compiled against. The header is used during compilation
|
|
||||||
only, libinput does not link against GPL libraries.
|
|
||||||
|
|
||||||
[1] https://gitlab.freedesktop.org/libinput/libinput/blob/main/include/linux/input.h
|
|
||||||
|
|
|
||||||
6
Makefile.am
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
SUBDIRS = src doc test tools
|
||||||
|
|
||||||
|
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||||
|
|
||||||
|
valgrind:
|
||||||
|
(cd test; $(MAKE) valgrind)
|
||||||
19
README
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
libinput
|
||||||
|
|
||||||
|
libinput is a library that handles input devices for display servers and other
|
||||||
|
applications that need to directly deal with input devices.
|
||||||
|
|
||||||
|
It provides device detection, device handling, input device event processing
|
||||||
|
and abstraction so minimize the amount of custom input code the user of
|
||||||
|
libinput need to provide the common set of functionality that users expect.
|
||||||
|
|
||||||
|
Input event processing includes scaling touch coordinates, generating
|
||||||
|
pointer events from touchpads, pointer acceleration, etc.
|
||||||
|
|
||||||
|
libinput originates from weston, the Wayland reference compositor.
|
||||||
|
|
||||||
|
The source code of libinput can be found at:
|
||||||
|
http://cgit.freedesktop.org/wayland/libinput
|
||||||
|
|
||||||
|
For more information, visit:
|
||||||
|
http://www.freedesktop.org/wiki/Software/libinput/
|
||||||
84
README.md
|
|
@ -1,84 +0,0 @@
|
||||||
libinput
|
|
||||||
========
|
|
||||||
|
|
||||||
libinput is a library that provides a full input stack for display servers
|
|
||||||
and other applications that need to handle input devices provided by the
|
|
||||||
kernel.
|
|
||||||
|
|
||||||
libinput provides device detection, event handling and abstraction to
|
|
||||||
minimize the amount of custom input code the user of libinput needs to
|
|
||||||
provide the common set of functionality that users expect. Input event
|
|
||||||
processing includes scaling touch coordinates, generating
|
|
||||||
relative pointer events from touchpads, pointer acceleration, etc.
|
|
||||||
|
|
||||||
User documentation
|
|
||||||
------------------
|
|
||||||
|
|
||||||
Documentation explaining features available in libinput is available
|
|
||||||
[here](https://wayland.freedesktop.org/libinput/doc/latest/features.html).
|
|
||||||
|
|
||||||
This includes the [FAQ](https://wayland.freedesktop.org/libinput/doc/latest/faqs.html)
|
|
||||||
and the instructions on
|
|
||||||
[reporting bugs](https://wayland.freedesktop.org/libinput/doc/latest/reporting-bugs.html).
|
|
||||||
|
|
||||||
|
|
||||||
Source code
|
|
||||||
-----------
|
|
||||||
|
|
||||||
The source code of libinput can be found at:
|
|
||||||
https://gitlab.freedesktop.org/libinput/libinput
|
|
||||||
|
|
||||||
For a list of current and past releases visit:
|
|
||||||
https://www.freedesktop.org/wiki/Software/libinput/
|
|
||||||
|
|
||||||
Build instructions:
|
|
||||||
https://wayland.freedesktop.org/libinput/doc/latest/building.html
|
|
||||||
|
|
||||||
Reporting Bugs
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Bugs can be filed on freedesktop.org GitLab:
|
|
||||||
https://gitlab.freedesktop.org/libinput/libinput/issues/
|
|
||||||
|
|
||||||
Where possible, please provide the `libinput record` output
|
|
||||||
of the input device and/or the event sequence in question.
|
|
||||||
|
|
||||||
See https://wayland.freedesktop.org/libinput/doc/latest/reporting-bugs.html
|
|
||||||
for more info.
|
|
||||||
|
|
||||||
Documentation
|
|
||||||
-------------
|
|
||||||
|
|
||||||
- Developer API documentation: https://wayland.freedesktop.org/libinput/doc/latest/development.html
|
|
||||||
- High-level documentation about libinput's features:
|
|
||||||
https://wayland.freedesktop.org/libinput/doc/latest/features.html
|
|
||||||
- Build instructions:
|
|
||||||
https://wayland.freedesktop.org/libinput/doc/latest/building.html
|
|
||||||
- Documentation for previous versions of libinput: https://wayland.freedesktop.org/libinput/doc/
|
|
||||||
|
|
||||||
Examples of how to use libinput are the debugging tools in the libinput
|
|
||||||
repository. Developers are encouraged to look at those tools for a
|
|
||||||
real-world (yet simple) example on how to use libinput.
|
|
||||||
|
|
||||||
- A commandline debugging tool: https://gitlab.freedesktop.org/libinput/libinput/tree/main/tools/libinput-debug-events.c
|
|
||||||
- A GTK application that draws cursor/touch/tablet positions: https://gitlab.freedesktop.org/libinput/libinput/tree/main/tools/libinput-debug-gui.c
|
|
||||||
|
|
||||||
License
|
|
||||||
-------
|
|
||||||
|
|
||||||
libinput is licensed under the MIT license.
|
|
||||||
|
|
||||||
> Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
> copy of this software and associated documentation files (the "Software"),
|
|
||||||
> to deal in the Software without restriction, including without limitation
|
|
||||||
> the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
> and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
> Software is furnished to do so, subject to the following conditions: [...]
|
|
||||||
|
|
||||||
See the [COPYING](https://gitlab.freedesktop.org/libinput/libinput/tree/main/COPYING)
|
|
||||||
file for the full license information.
|
|
||||||
|
|
||||||
About
|
|
||||||
-----
|
|
||||||
|
|
||||||
Documentation generated from git commit [__GIT_VERSION__](https://gitlab.freedesktop.org/libinput/libinput/commit/__GIT_VERSION__)
|
|
||||||
9
autogen.sh
Executable file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test -n "$srcdir" || srcdir=`dirname "$0"`
|
||||||
|
test -n "$srcdir" || srcdir=.
|
||||||
|
(
|
||||||
|
cd "$srcdir" &&
|
||||||
|
autoreconf --force -v --install
|
||||||
|
) || exit
|
||||||
|
test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
132
configure.ac
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
AC_PREREQ([2.64])
|
||||||
|
|
||||||
|
m4_define([libinput_major_version], [0])
|
||||||
|
m4_define([libinput_minor_version], [6])
|
||||||
|
m4_define([libinput_micro_version], [0])
|
||||||
|
m4_define([libinput_version],
|
||||||
|
[libinput_major_version.libinput_minor_version.libinput_micro_version])
|
||||||
|
|
||||||
|
AC_INIT([libinput],
|
||||||
|
[libinput_version],
|
||||||
|
[https://bugs.freedesktop.org/enter_bug.cgi?product=Wayland&component=libinput&version=libinput_version],
|
||||||
|
[libinput],
|
||||||
|
[http://www.freedesktop.org/wiki/Software/libinput/])
|
||||||
|
|
||||||
|
AC_SUBST([LIBINPUT_VERSION_MAJOR], [libinput_major_version])
|
||||||
|
AC_SUBST([LIBINPUT_VERSION_MINOR], [libinput_minor_version])
|
||||||
|
AC_SUBST([LIBINPUT_VERSION_MICRO], [libinput_micro_version])
|
||||||
|
AC_SUBST([LIBINPUT_VERSION], [libinput_version])
|
||||||
|
|
||||||
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
|
||||||
|
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz subdir-objects])
|
||||||
|
|
||||||
|
# Before making a release, the LIBINPUT_LT_VERSION string should be
|
||||||
|
# modified.
|
||||||
|
# The string is of the form C:R:A.
|
||||||
|
# - If interfaces have been changed or added, but binary compatibility has
|
||||||
|
# been preserved, change to C+1:0:A+1
|
||||||
|
# - If binary compatibility has been broken (eg removed or changed interfaces)
|
||||||
|
# change to C+1:0:0
|
||||||
|
# - If the interface is the same as the previous version, change to C:R+1:A
|
||||||
|
LIBINPUT_LT_VERSION=5:0:0
|
||||||
|
AC_SUBST(LIBINPUT_LT_VERSION)
|
||||||
|
|
||||||
|
AM_SILENT_RULES([yes])
|
||||||
|
|
||||||
|
# Check for programs
|
||||||
|
AC_PROG_CC_C99
|
||||||
|
AC_PROG_CXX # Only used by build C++ test
|
||||||
|
|
||||||
|
# Initialize libtool
|
||||||
|
LT_PREREQ([2.2])
|
||||||
|
LT_INIT
|
||||||
|
|
||||||
|
AC_CHECK_DECL(EPOLL_CLOEXEC, [],
|
||||||
|
[AC_MSG_ERROR("EPOLL_CLOEXEC is needed to compile libinput")],
|
||||||
|
[[#include <sys/epoll.h>]])
|
||||||
|
AC_CHECK_DECL(TFD_CLOEXEC,[],
|
||||||
|
[AC_MSG_ERROR("TFD_CLOEXEC is needed to compile libinput")],
|
||||||
|
[[#include <sys/timerfd.h>]])
|
||||||
|
AC_CHECK_DECL(CLOCK_MONOTONIC,[],
|
||||||
|
[AC_MSG_ERROR("CLOCK_MONOTONIC is needed to compile libinput")],
|
||||||
|
[[#include <time.h>]])
|
||||||
|
|
||||||
|
PKG_PROG_PKG_CONFIG()
|
||||||
|
PKG_CHECK_MODULES(MTDEV, [mtdev >= 1.1.0])
|
||||||
|
PKG_CHECK_MODULES(LIBUDEV, [libudev])
|
||||||
|
PKG_CHECK_MODULES(LIBEVDEV, [libevdev >= 0.4])
|
||||||
|
AC_CHECK_LIB([m], [atan2])
|
||||||
|
AC_CHECK_LIB([rt], [clock_gettime])
|
||||||
|
|
||||||
|
if test "x$GCC" = "xyes"; then
|
||||||
|
GCC_CXXFLAGS="-Wall -Wextra -Wno-unused-parameter -g -fvisibility=hidden"
|
||||||
|
GCC_CFLAGS="$GCC_CXXFLAGS -Wmissing-prototypes -Wstrict-prototypes"
|
||||||
|
fi
|
||||||
|
AC_SUBST(GCC_CFLAGS)
|
||||||
|
AC_SUBST(GCC_CXXFLAGS)
|
||||||
|
|
||||||
|
AC_PATH_PROG(DOXYGEN, [doxygen])
|
||||||
|
if test "x$DOXYGEN" = "x"; then
|
||||||
|
AC_MSG_WARN([doxygen not found - required for documentation])
|
||||||
|
have_doxygen="no"
|
||||||
|
else
|
||||||
|
have_doxygen="yes"
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$have_doxygen" = "xyes"])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(event-gui,
|
||||||
|
AS_HELP_STRING([--enable-event-gui], [Build the GUI event viewer (default=auto)]),
|
||||||
|
[build_eventgui="$enableval"],
|
||||||
|
[build_eventgui="auto"])
|
||||||
|
PKG_CHECK_EXISTS([cairo glib-2.0 gtk+-3.0], [HAVE_GUILIBS="yes"], [HAVE_GUILIBS="no"])
|
||||||
|
|
||||||
|
if test "x$build_eventgui" = "xauto"; then
|
||||||
|
build_eventgui="$HAVE_GUILIBS"
|
||||||
|
fi
|
||||||
|
if test "x$build_eventgui" = "xyes"; then
|
||||||
|
PKG_CHECK_MODULES(CAIRO, [cairo])
|
||||||
|
PKG_CHECK_MODULES(GTK, [glib-2.0 gtk+-3.0])
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(BUILD_EVENTGUI, [test "x$build_eventgui" = "xyes"])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(tests,
|
||||||
|
AS_HELP_STRING([--enable-tests], [Build the tests (default=auto)]),
|
||||||
|
[build_tests="$enableval"],
|
||||||
|
[build_tests="auto"])
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(CHECK, [check >= 0.9.10], [HAVE_CHECK="yes"], [HAVE_CHECK="no"])
|
||||||
|
|
||||||
|
if test "x$build_tests" = "xauto"; then
|
||||||
|
build_tests="$HAVE_CHECK"
|
||||||
|
fi
|
||||||
|
if test "x$build_tests" = "xyes"; then
|
||||||
|
if test "x$HAVE_CHECK" = "xno"; then
|
||||||
|
AC_MSG_ERROR([Cannot build tests, check is missing])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_PATH_PROG(VALGRIND, [valgrind])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AM_CONDITIONAL(HAVE_VALGRIND, [test "x$VALGRIND" != "x"])
|
||||||
|
AM_CONDITIONAL(BUILD_TESTS, [test "x$build_tests" = "xyes"])
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([Makefile
|
||||||
|
doc/Makefile
|
||||||
|
doc/libinput.doxygen
|
||||||
|
src/Makefile
|
||||||
|
src/libinput.pc
|
||||||
|
src/libinput-version.h
|
||||||
|
test/Makefile
|
||||||
|
tools/Makefile])
|
||||||
|
AC_OUTPUT
|
||||||
|
|
||||||
|
AC_MSG_RESULT([
|
||||||
|
Prefix ${prefix}
|
||||||
|
|
||||||
|
Build documentation ${have_doxygen}
|
||||||
|
Build tests ${build_tests}
|
||||||
|
Tests use valgrind ${VALGRIND}
|
||||||
|
Build GUI event tool ${build_eventgui}
|
||||||
|
])
|
||||||
28
doc/Makefile.am
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
EXTRA_DIST = touchpad-tap-state-machine.svg touchpad-softbutton-state-machine.svg
|
||||||
|
|
||||||
|
if HAVE_DOXYGEN
|
||||||
|
|
||||||
|
noinst_DATA = html/index.html
|
||||||
|
|
||||||
|
header_files = \
|
||||||
|
$(top_srcdir)/src/libinput.h
|
||||||
|
|
||||||
|
html/index.html: libinput.doxygen $(header_files)
|
||||||
|
$(AM_V_GEN)$(DOXYGEN) $<
|
||||||
|
|
||||||
|
clean-local:
|
||||||
|
$(AM_V_at)rm -rf html
|
||||||
|
|
||||||
|
doc_src= $(shell find html -type f -printf "html/%P\n" 2>/dev/null)
|
||||||
|
EXTRA_DIST += $(builddir)/html/index.html $(doc_src)
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
# make sure doc was built before running dist
|
||||||
|
dist-hook:
|
||||||
|
@test -f $(distdir)/html/index.html || (\
|
||||||
|
echo "******************************************************" && \
|
||||||
|
echo "Couldn't find documentation files, refusing make dist." && \
|
||||||
|
echo "Install doxygen to build documentation for tarball." && \
|
||||||
|
echo "******************************************************" && \
|
||||||
|
test )
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
PROJECT_NAME = @PACKAGE_NAME@
|
|
||||||
PROJECT_NUMBER = @PACKAGE_VERSION@
|
|
||||||
PROJECT_BRIEF = "A wrapper library for input devices"
|
|
||||||
JAVADOC_AUTOBRIEF = YES
|
|
||||||
TAB_SIZE = 8
|
|
||||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
|
||||||
EXTRACT_ALL = YES
|
|
||||||
EXTRACT_STATIC = YES
|
|
||||||
MAX_INITIALIZER_LINES = 0
|
|
||||||
WARNINGS = YES
|
|
||||||
QUIET = YES
|
|
||||||
INPUT = "@builddir@"
|
|
||||||
IMAGE_PATH = "@builddir@"
|
|
||||||
OUTPUT_DIRECTORY = doc
|
|
||||||
GENERATE_HTML = YES
|
|
||||||
HTML_OUTPUT = html
|
|
||||||
SEARCHENGINE = NO
|
|
||||||
USE_MATHJAX = YES
|
|
||||||
MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
|
|
||||||
GENERATE_LATEX = NO
|
|
||||||
MACRO_EXPANSION = YES
|
|
||||||
EXPAND_ONLY_PREDEF = YES
|
|
||||||
PREDEFINED = LIBINPUT_ATTRIBUTE_PRINTF(f, a)= \
|
|
||||||
LIBINPUT_ATTRIBUTE_DEPRECATED
|
|
||||||
DOTFILE_DIRS = "@builddir@"
|
|
||||||
EXAMPLE_PATH = "@builddir@"
|
|
||||||
SHOW_NAMESPACES = NO
|
|
||||||
HAVE_DOT = YES
|
|
||||||
|
|
||||||
HTML_HEADER = "@builddir@/header.html"
|
|
||||||
HTML_FOOTER = "@builddir@/footer.html"
|
|
||||||
HTML_EXTRA_STYLESHEET = "@builddir@/bootstrap.css" \
|
|
||||||
"@builddir@/customdoxygen.css" \
|
|
||||||
"@builddir@/libinputdoxygen.css"
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
/**
|
|
||||||
@mainpage
|
|
||||||
|
|
||||||
This is the libinput API reference.
|
|
||||||
|
|
||||||
This documentation is aimed at developers of Wayland compositors. User
|
|
||||||
documentation is available
|
|
||||||
[here](https://wayland.freedesktop.org/libinput/doc/latest).
|
|
||||||
|
|
||||||
@section concepts Concepts
|
|
||||||
|
|
||||||
@subsection concepts_initialization Initialization of a libinput context
|
|
||||||
|
|
||||||
libinput provides two different backends:
|
|
||||||
- a @ref libinput_udev_create_context "udev backend" where notifications
|
|
||||||
about new and removed devices are provided by udev, and
|
|
||||||
- a @ref libinput_path_create_context "path backend" where
|
|
||||||
@ref libinput_path_add_device "device addition" and
|
|
||||||
@ref libinput_path_remove_device "device removal" need to be handled by
|
|
||||||
the caller.
|
|
||||||
|
|
||||||
See section @ref base for information about initializing a libinput context.
|
|
||||||
|
|
||||||
@subsection concepts_events Monitoring for events
|
|
||||||
|
|
||||||
libinput exposes a single @ref libinput_get_fd "file descriptor" to the
|
|
||||||
caller. This file descriptor should be monitored by the caller, whenever
|
|
||||||
data is available the caller **must** immediately call libinput_dispatch().
|
|
||||||
Failure to do so will result in erroneous behavior.
|
|
||||||
|
|
||||||
libinput_dispatch() may result in one or more events being available to the
|
|
||||||
caller. After libinput_dispatch() a caller **should** call
|
|
||||||
libinput_get_event() to retrieve and process this event. Whenever
|
|
||||||
libinput_get_event() returns `NULL`, no further events are available.
|
|
||||||
|
|
||||||
See section @ref event for more information about events.
|
|
||||||
|
|
||||||
@subsection concepts_seats Device grouping into seats
|
|
||||||
|
|
||||||
All devices are grouped into physical and logical seats. Button and key
|
|
||||||
states are available per-device and per-seat. See @ref seat for more
|
|
||||||
information.
|
|
||||||
|
|
||||||
@subsection concepts_devices Device capabilities
|
|
||||||
|
|
||||||
libinput does not use device types. All devices have @ref
|
|
||||||
libinput_device_has_capability "capabilities" that define which events may
|
|
||||||
be generated. See @ref device for more information about devices.
|
|
||||||
|
|
||||||
Specific event types include:
|
|
||||||
- @ref event_keyboard
|
|
||||||
- @ref event_pointer
|
|
||||||
- @ref event_touch
|
|
||||||
- @ref event_gesture
|
|
||||||
- @ref event_tablet
|
|
||||||
- @ref event_tablet_pad
|
|
||||||
- @ref event_switch
|
|
||||||
|
|
||||||
|
|
||||||
@subsection concepts_configuration Device configuration
|
|
||||||
|
|
||||||
libinput relies on the caller for device configuration. See
|
|
||||||
@ref config for more information.
|
|
||||||
|
|
||||||
@subsection example An example libinput program
|
|
||||||
|
|
||||||
The simplest libinput program looks like this:
|
|
||||||
|
|
||||||
@code
|
|
||||||
static int open_restricted(const char *path, int flags, void *user_data)
|
|
||||||
{
|
|
||||||
int fd = open(path, flags);
|
|
||||||
return fd < 0 ? -errno : fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void close_restricted(int fd, void *user_data)
|
|
||||||
{
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
const static struct libinput_interface interface = {
|
|
||||||
.open_restricted = open_restricted,
|
|
||||||
.close_restricted = close_restricted,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
struct libinput *li;
|
|
||||||
struct libinput_event *event;
|
|
||||||
|
|
||||||
li = libinput_udev_create_context(&interface, NULL, udev);
|
|
||||||
libinput_udev_assign_seat(li, "seat0");
|
|
||||||
libinput_dispatch(li);
|
|
||||||
|
|
||||||
while ((event = libinput_get_event(li)) != NULL) {
|
|
||||||
|
|
||||||
// handle the event here
|
|
||||||
|
|
||||||
libinput_event_destroy(event);
|
|
||||||
libinput_dispatch(li);
|
|
||||||
}
|
|
||||||
|
|
||||||
libinput_unref(li);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
@section building_against Building against libinput
|
|
||||||
|
|
||||||
libinput provides a
|
|
||||||
[pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/) file.
|
|
||||||
Software that uses libinput should use pkg-config and the
|
|
||||||
`PKG_CHECK_MODULES` autoconf macro.
|
|
||||||
Otherwise, the most rudimentary way to compile and link a program against
|
|
||||||
libinput is:
|
|
||||||
|
|
||||||
@verbatim
|
|
||||||
gcc -o myprogram myprogram.c `pkg-config --cflags --libs libinput`
|
|
||||||
@endverbatim
|
|
||||||
|
|
||||||
For further information on using pkgconfig see the pkg-config documentation.
|
|
||||||
|
|
||||||
@section stability Backwards-compatibility
|
|
||||||
|
|
||||||
libinput promises backwards-compatibility across all the 1.x.y version. An
|
|
||||||
application built against libinput 1.x.y will work with any future 1.*.*
|
|
||||||
release.
|
|
||||||
|
|
||||||
@section About
|
|
||||||
|
|
||||||
Documentation generated from git commit [__GIT_VERSION__](https://gitlab.freedesktop.org/libinput/libinput/commit/__GIT_VERSION__)
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
prg_install = find_program('install')
|
|
||||||
|
|
||||||
doxygen = find_program('doxygen', required : false)
|
|
||||||
if not doxygen.found()
|
|
||||||
error('Program "doxygen" not found or not executable. Try building with -Ddocumentation=false')
|
|
||||||
endif
|
|
||||||
dot = find_program('dot', required : false)
|
|
||||||
if not dot.found()
|
|
||||||
error('Program "dot" not found or not executable. Try building with -Ddocumentation=false')
|
|
||||||
endif
|
|
||||||
|
|
||||||
mainpage = vcs_tag(command : ['git', 'log', '-1', '--format=%h'],
|
|
||||||
fallback : 'unknown',
|
|
||||||
input : 'mainpage.dox',
|
|
||||||
output : 'mainpage.dox',
|
|
||||||
replace_string: '__GIT_VERSION__')
|
|
||||||
|
|
||||||
src_doxygen = files(
|
|
||||||
# source files
|
|
||||||
'../../src/libinput.h',
|
|
||||||
# style files
|
|
||||||
'style/header.html',
|
|
||||||
'style/footer.html',
|
|
||||||
'style/customdoxygen.css',
|
|
||||||
'style/bootstrap.css',
|
|
||||||
'style/libinputdoxygen.css',
|
|
||||||
)
|
|
||||||
|
|
||||||
doxyfiles = []
|
|
||||||
foreach f : src_doxygen
|
|
||||||
df = configure_file(input: f,
|
|
||||||
output: '@PLAINNAME@',
|
|
||||||
copy : true)
|
|
||||||
doxyfiles += [ df ]
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
doc_config = configuration_data()
|
|
||||||
doc_config.set('PACKAGE_NAME', meson.project_name())
|
|
||||||
doc_config.set('PACKAGE_VERSION', meson.project_version())
|
|
||||||
doc_config.set('builddir', meson.current_build_dir())
|
|
||||||
|
|
||||||
doxyfile = configure_file(input : 'libinput.doxygen.in',
|
|
||||||
output : 'libinput.doxygen',
|
|
||||||
configuration : doc_config)
|
|
||||||
|
|
||||||
custom_target('doxygen',
|
|
||||||
input : [ doxyfiles, doxyfile, mainpage ] + src_doxygen,
|
|
||||||
output : [ 'html' ],
|
|
||||||
command : [ doxygen, doxyfile ],
|
|
||||||
install : false,
|
|
||||||
depends: [ mainpage ],
|
|
||||||
build_by_default : true)
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
/**
|
|
||||||
|
|
||||||
@page Tablets
|
|
||||||
|
|
||||||
- @subpage tablet serial numbers
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
@ -1,229 +0,0 @@
|
||||||
These licenses apply to the doxygen documentation HTML style only. They do
|
|
||||||
not apply or affect libinput itself.
|
|
||||||
|
|
||||||
Apache: https://github.com/Velron/doxygen-bootstrapped/
|
|
||||||
MIT: https://bootswatch.com/paper/bootstrap.css
|
|
||||||
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright {yyyy} {name of copyright owner}
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
|
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2011-2015 Twitter, Inc
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to
|
|
||||||
deal in the Software without restriction, including without limitation the
|
|
||||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
IN THE SOFTWARE.
|
|
||||||
7500
doc/api/style/bootstrap.css
vendored
|
|
@ -1,254 +0,0 @@
|
||||||
h1, .h1, h2, .h2, h3, .h3{
|
|
||||||
font-weight: 200 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#navrow1, #navrow2, #navrow3, #navrow4, #navrow5{
|
|
||||||
border-bottom: 1px solid #EEEEEE;
|
|
||||||
}
|
|
||||||
|
|
||||||
.adjust-right {
|
|
||||||
margin-left: 30px !important;
|
|
||||||
font-size: 1.15em !important;
|
|
||||||
}
|
|
||||||
.navbar{
|
|
||||||
border: 0px solid #222 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Sticky footer styles
|
|
||||||
-------------------------------------------------- */
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
height: 100%;
|
|
||||||
/* The html and body elements cannot have any padding or margin. */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wrapper for page content to push down footer */
|
|
||||||
#wrap {
|
|
||||||
min-height: 100%;
|
|
||||||
height: auto;
|
|
||||||
/* Negative indent footer by its height */
|
|
||||||
margin: 0 auto -60px;
|
|
||||||
/* Pad bottom by footer height */
|
|
||||||
padding: 0 0 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the fixed height of the footer here */
|
|
||||||
#footer {
|
|
||||||
font-size: 0.9em;
|
|
||||||
padding: 8px 0px;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-row {
|
|
||||||
line-height: 44px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#footer > .container {
|
|
||||||
padding-left: 15px;
|
|
||||||
padding-right: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-follow-icon {
|
|
||||||
margin-left: 3px;
|
|
||||||
text-decoration: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-follow-icon img {
|
|
||||||
width: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-link {
|
|
||||||
padding-top: 5px;
|
|
||||||
display: inline-block;
|
|
||||||
color: #999999;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-copyright {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@media (min-width: 992px) {
|
|
||||||
.footer-row {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-icons {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (max-width: 991px) {
|
|
||||||
.footer-row {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-icons {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* DOXYGEN Code Styles
|
|
||||||
----------------------------------- */
|
|
||||||
|
|
||||||
|
|
||||||
a.qindex {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.qindexHL {
|
|
||||||
font-weight: bold;
|
|
||||||
background-color: #9CAFD4;
|
|
||||||
color: #ffffff;
|
|
||||||
border: 1px double #869DCA;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contents a.qindexHL:visited {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.code, a.code:visited, a.line, a.line:visited {
|
|
||||||
color: #4665A2;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
|
|
||||||
color: #4665A2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* @end */
|
|
||||||
|
|
||||||
dl.el {
|
|
||||||
margin-left: -1cm;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre.fragment {
|
|
||||||
border: 1px solid #C4CFE5;
|
|
||||||
background-color: #FBFCFD;
|
|
||||||
padding: 4px 6px;
|
|
||||||
margin: 4px 8px 4px 2px;
|
|
||||||
overflow: auto;
|
|
||||||
word-wrap: break-word;
|
|
||||||
font-size: 9pt;
|
|
||||||
line-height: 125%;
|
|
||||||
font-family: monospace, fixed;
|
|
||||||
font-size: 105%;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.fragment {
|
|
||||||
padding: 4px 6px;
|
|
||||||
margin: 4px 8px 4px 2px;
|
|
||||||
border: 1px solid #C4CFE5;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.line {
|
|
||||||
font-family: monospace, fixed;
|
|
||||||
font-size: 13px;
|
|
||||||
min-height: 13px;
|
|
||||||
line-height: 1.0;
|
|
||||||
text-wrap: unrestricted;
|
|
||||||
white-space: -moz-pre-wrap; /* Moz */
|
|
||||||
white-space: -pre-wrap; /* Opera 4-6 */
|
|
||||||
white-space: -o-pre-wrap; /* Opera 7 */
|
|
||||||
white-space: pre-wrap; /* CSS3 */
|
|
||||||
word-wrap: break-word; /* IE 5.5+ */
|
|
||||||
text-indent: -53px;
|
|
||||||
padding-left: 53px;
|
|
||||||
padding-bottom: 0px;
|
|
||||||
margin: 0px;
|
|
||||||
-webkit-transition-property: background-color, box-shadow;
|
|
||||||
-webkit-transition-duration: 0.5s;
|
|
||||||
-moz-transition-property: background-color, box-shadow;
|
|
||||||
-moz-transition-duration: 0.5s;
|
|
||||||
-ms-transition-property: background-color, box-shadow;
|
|
||||||
-ms-transition-duration: 0.5s;
|
|
||||||
-o-transition-property: background-color, box-shadow;
|
|
||||||
-o-transition-duration: 0.5s;
|
|
||||||
transition-property: background-color, box-shadow;
|
|
||||||
transition-duration: 0.5s;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.line.glow {
|
|
||||||
background-color: cyan;
|
|
||||||
box-shadow: 0 0 10px cyan;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
span.lineno {
|
|
||||||
padding-right: 4px;
|
|
||||||
text-align: right;
|
|
||||||
border-right: 2px solid #0F0;
|
|
||||||
background-color: #E8E8E8;
|
|
||||||
white-space: pre;
|
|
||||||
}
|
|
||||||
span.lineno a {
|
|
||||||
background-color: #D8D8D8;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.lineno a:hover {
|
|
||||||
background-color: #C8C8C8;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.groupHeader {
|
|
||||||
margin-left: 16px;
|
|
||||||
margin-top: 12px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.groupText {
|
|
||||||
margin-left: 16px;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* @group Code Colorization */
|
|
||||||
|
|
||||||
span.keyword {
|
|
||||||
color: #008000
|
|
||||||
}
|
|
||||||
|
|
||||||
span.keywordtype {
|
|
||||||
color: #604020
|
|
||||||
}
|
|
||||||
|
|
||||||
span.keywordflow {
|
|
||||||
color: #e08000
|
|
||||||
}
|
|
||||||
|
|
||||||
span.comment {
|
|
||||||
color: #800000
|
|
||||||
}
|
|
||||||
|
|
||||||
span.preprocessor {
|
|
||||||
color: #806020
|
|
||||||
}
|
|
||||||
|
|
||||||
span.stringliteral {
|
|
||||||
color: #002080
|
|
||||||
}
|
|
||||||
|
|
||||||
span.charliteral {
|
|
||||||
color: #008080
|
|
||||||
}
|
|
||||||
|
|
||||||
span.vhdldigit {
|
|
||||||
color: #ff00ff
|
|
||||||
}
|
|
||||||
|
|
||||||
span.vhdlchar {
|
|
||||||
color: #000000
|
|
||||||
}
|
|
||||||
|
|
||||||
span.vhdlkeyword {
|
|
||||||
color: #700070
|
|
||||||
}
|
|
||||||
|
|
||||||
span.vhdllogic {
|
|
||||||
color: #ff0000
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
|
||||||
background-color: #F7F8FB;
|
|
||||||
border-left: 2px solid #9CAFD4;
|
|
||||||
margin: 0 24px 0 4px;
|
|
||||||
padding: 0 12px 0 16px;
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
<!-- HTML footer for doxygen 1.8.8-->
|
|
||||||
<!-- start footer part -->
|
|
||||||
<!--BEGIN GENERATE_TREEVIEW-->
|
|
||||||
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
|
|
||||||
<ul>
|
|
||||||
$navpath
|
|
||||||
<li class="footer">$generatedby
|
|
||||||
<a href="http://www.doxygen.org/index.html">
|
|
||||||
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<!--END GENERATE_TREEVIEW-->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!--BEGIN !GENERATE_TREEVIEW-->
|
|
||||||
<hr class="footer"/><address class="footer"><small>
|
|
||||||
$generatedby  <a href="http://www.doxygen.org/index.html">
|
|
||||||
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
|
|
||||||
</a> $doxygenversion
|
|
||||||
</small></address>
|
|
||||||
<!--END !GENERATE_TREEVIEW-->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
<!-- HTML header for doxygen 1.8.8-->
|
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<!-- For Mobile Devices -->
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
|
|
||||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
|
||||||
<meta name="generator" content="Doxygen $doxygenversion"/>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
|
||||||
|
|
||||||
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
|
|
||||||
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
|
|
||||||
<!--<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>-->
|
|
||||||
<script type="text/javascript" src="$relpath^dynsections.js"></script>
|
|
||||||
$treeview
|
|
||||||
$search
|
|
||||||
$mathjax
|
|
||||||
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
|
||||||
$extrastylesheet
|
|
||||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
|
|
||||||
<script type="text/javascript" src="doxy-boot.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav class="navbar navbar-default" role="navigation">
|
|
||||||
<div class="container">
|
|
||||||
<div class="navbar-header">
|
|
||||||
<a class="navbar-brand">$projectname $projectnumber</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
|
||||||
<div class="content" id="content">
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-12 panel panel-default" style="padding-bottom: 15px;">
|
|
||||||
<div style="margin-bottom: 15px;">
|
|
||||||
<!-- end header part -->
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
@import url("https://fonts.googleapis.com/css?family=Roboto+Mono");
|
|
||||||
|
|
||||||
dd {
|
|
||||||
margin-left: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 200%;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title .ingroups {
|
|
||||||
font-size: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 150%;
|
|
||||||
color: #354C7B;
|
|
||||||
background: none;
|
|
||||||
border-bottom: 1px solid #879ECB;
|
|
||||||
font-size: 150%;
|
|
||||||
font-weight: normal;
|
|
||||||
padding-top: 8px;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
padding-left: 0px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: 120%;
|
|
||||||
color: #354C7B;
|
|
||||||
background: none;
|
|
||||||
border-bottom: 1px solid #879ECB;
|
|
||||||
font-size: 150%;
|
|
||||||
font-weight: normal;
|
|
||||||
padding-top: 8px;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
padding-left: 0px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sm-dox li {
|
|
||||||
float:left;
|
|
||||||
border-top: 0;
|
|
||||||
padding-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sm li, .sm a {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sm, .sm ul, .sm li {
|
|
||||||
list-style: none;
|
|
||||||
display: block;
|
|
||||||
line-height: normal;
|
|
||||||
direction: ltr;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sm, .sm *, .sm *::before, .sm *::after {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main-nav {
|
|
||||||
padding: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Main menu sub-items like file-list, etc */
|
|
||||||
#main-menu li ul {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.paramname {
|
|
||||||
padding-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.memtitle {
|
|
||||||
background-image: none;
|
|
||||||
background-color: #F0F0F0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.memproto {
|
|
||||||
background-color: #F0F0F0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headertitle {
|
|
||||||
background-image: none;
|
|
||||||
background-color: #F0F0F0;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.header {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
td.fieldname {
|
|
||||||
font-family: 'Roboto Mono', monospace;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fieldtable th {
|
|
||||||
background-image: none;
|
|
||||||
background-color: #F0F0F0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
letter-spacing: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams {
|
|
||||||
background-color: #F0F0F0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #2873b0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.navpath ul {
|
|
||||||
background-image: none;
|
|
||||||
background-color: #F0F0F0;
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 97 KiB |
|
|
@ -1,50 +0,0 @@
|
||||||
# Source for the button debouncing wave diagram
|
|
||||||
# Paste into http://wavedrom.com/editor.html
|
|
||||||
{signal: [
|
|
||||||
{name:'current mode', wave: '3............', data: ['normal button press and release']},
|
|
||||||
{name:'physical button', wave: '01......0....'},
|
|
||||||
{name:'application ', wave: '01......0....'},
|
|
||||||
{},
|
|
||||||
['bounce mode',
|
|
||||||
{name:'current mode', wave: '4............', data: ['debounced button press']},
|
|
||||||
{name:'physical button', wave: '0101...0.....'},
|
|
||||||
{name: 'timeouts', wave: '01...0.1...0.'},
|
|
||||||
{name:'application ', wave: '01.....0.....'},
|
|
||||||
{},
|
|
||||||
{name:'current mode', wave: '4............', data: ['debounced button release']},
|
|
||||||
{name:'physical button', wave: '1...010......'},
|
|
||||||
{name: 'timeouts', wave: '0...1...0....'},
|
|
||||||
{name:'application ', wave: '1...0........'},
|
|
||||||
{},
|
|
||||||
{name:'current mode', wave: '5............', data: ['delayed button press']},
|
|
||||||
{name:'physical button', wave: '1...01.......'},
|
|
||||||
{name: 'timeouts', wave: '0...1...0....'},
|
|
||||||
{name:'application ', wave: '1...0...1....'},
|
|
||||||
{},
|
|
||||||
{name:'current mode', wave: '5............', data: ['delayed button release']},
|
|
||||||
{name:'physical button', wave: '0...10.......'},
|
|
||||||
{name: 'timeouts', wave: '0...1...0....'},
|
|
||||||
{name:'application ', wave: '0...1...0....'},
|
|
||||||
],
|
|
||||||
{},
|
|
||||||
['spurious mode',
|
|
||||||
{name:'current mode', wave: '3............', data: ['first spurious button release ']},
|
|
||||||
{name:'physical button', wave: '1.......01...'},
|
|
||||||
{name:'application ', wave: '1.......01...'},
|
|
||||||
{},
|
|
||||||
{name:'current mode', wave: '3............', data: ['later spurious button release ']},
|
|
||||||
{name:'physical button', wave: '1....01......'},
|
|
||||||
{name: 'timeouts', wave: '0....1..0....'},
|
|
||||||
{name:'application ', wave: '1............'},
|
|
||||||
{},
|
|
||||||
{name:'current mode', wave: '3............', data: ['delayed release in spurious mode ']},
|
|
||||||
{name:'physical button', wave: '1....0.......'},
|
|
||||||
{name: 'timeouts', wave: '0....1..0....'},
|
|
||||||
{name:'application ', wave: '1.......0....'}
|
|
||||||
],
|
|
||||||
|
|
||||||
],
|
|
||||||
head:{
|
|
||||||
text:'Button Debouncing Scenarios',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
1854
doc/libinput.doxygen.in
Normal file
|
Before Width: | Height: | Size: 112 KiB |
|
|
@ -1,262 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1490px" height="1399px" version="1.1">
|
|
||||||
<defs/>
|
|
||||||
<g transform="translate(0.5,0.5)">
|
|
||||||
<ellipse cx="261" cy="143" rx="63" ry="45.5" fill="#ccccff" stroke="#000000" stroke-width="2" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="261" y="126">NONE</text>
|
|
||||||
<text x="261" y="140">on-entry:</text>
|
|
||||||
<text x="261" y="154">edge = none</text>
|
|
||||||
<text x="261" y="168">threshold = def</text>
|
|
||||||
</g>
|
|
||||||
<rect x="30" y="386" width="150" height="101" rx="6" ry="6" fill="#ccffcc" stroke="#000000" stroke-width="2" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="105" y="419">EDGE_NEW</text>
|
|
||||||
<text x="105" y="433">on-entry:</text>
|
|
||||||
<text x="105" y="447">edge = get_edge()</text>
|
|
||||||
<text x="105" y="461">set_timer()</text>
|
|
||||||
</g>
|
|
||||||
<rect x="348" y="386" width="130" height="100" rx="6" ry="6" fill="#ccffcc" stroke="#000000" stroke-width="2" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="413" y="419">AREA</text>
|
|
||||||
<text x="413" y="433">on-entry:</text>
|
|
||||||
<text x="413" y="447">edge = none</text>
|
|
||||||
<text x="413" y="461">set_pointer()</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 237 7 C 239 4 243 2 246 2 L 275 2 C 278 2 282 4 284 7 L 301 30 C 301 31 301 33 301 34 L 284 57 C 282 60 278 62 275 62 L 246 62 C 243 62 239 60 237 57 L 220 34 C 220 33 220 31 220 30 L 237 7 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="261" y="36">release</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 237 222 C 239 219 243 217 246 217 L 276 217 C 279 217 283 219 285 222 L 303 245 C 303 246 303 248 303 249 L 285 272 C 283 275 279 277 276 277 L 246 277 C 243 277 239 275 237 272 L 219 249 C 219 248 219 246 219 245 L 237 222 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="261" y="251">touch</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 261 188 L 261 211" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 261 216 L 258 209 L 261 211 L 265 209 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 218 535 C 223 531 229 528 235 528 L 285 528 C 291 528 297 531 302 535 L 331 570 C 332 571 332 574 331 575 L 302 610 C 297 614 291 617 285 617 L 235 617 C 229 617 223 614 218 610 L 189 575 C 188 574 188 571 189 570 L 218 535 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="260" y="563">touch,</text>
|
|
||||||
<text x="260" y="577">edge &= get_edge()</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 220 526 L 158 487" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 224 529 L 217 528 L 220 526 L 220 522 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 105 617 L 105 650" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 105 656 L 101 649 L 105 650 L 108 649 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 478 436 L 498 436 Q 508 436 508 426 L 508 42 Q 508 32 498 32 L 307 32" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 302 32 L 309 29 L 307 32 L 309 36 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 261 62 L 261 71 Q 261 80 261 85 L 261 91" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 261 96 L 257 89 L 261 91 L 264 89 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<ellipse cx="1133" cy="67" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<path d="M 1133 82 L 1133 110 Q 1133 120 1133 130 L 1133 155" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1129 147 L 1133 156 L 1138 147" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<rect x="1083" y="12" width="100" height="40" fill="none" stroke="none" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="1133" y="36">tp_edge_scroll_post_events()</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1133 212 L 1193 242 L 1133 272 L 1073 242 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="1133" y="246">dirty?</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1193 242 L 1278 242 Q 1288 242 1298 242 L 1456 242" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1448 247 L 1457 242 L 1448 238" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="1225" y="223" width="18" height="18" stroke-width="0"/>
|
|
||||||
<text x="1226" y="236">no</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1133 272 L 1133 285 Q 1133 295 1133 305 L 1133 316" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1129 308 L 1133 317 L 1138 308" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="1150" y="292" width="24" height="18" stroke-width="0"/>
|
|
||||||
<text x="1150" y="302">yes</text>
|
|
||||||
</g>
|
|
||||||
<ellipse cx="1473" cy="242" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<ellipse cx="1473" cy="242" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<rect x="1033" y="97" width="200" height="70" rx="28" ry="28" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="1133" y="115">current = buttons.state & 0x01</text>
|
|
||||||
<text x="1133" y="129">old = buttons.old_state & 0x01</text>
|
|
||||||
<text x="1133" y="143">button = 0</text>
|
|
||||||
<text x="1133" y="157">is_top = 0</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1133 167 L 1133 180 Q 1133 190 1133 200 L 1133 210" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1129 202 L 1133 211 L 1138 202" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<rect x="1237" y="436" width="188" height="50" rx="20" ry="20" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="1331" y="458">notify_axis(last_axis, 0.0)</text>
|
|
||||||
<text x="1331" y="472">last_axis = -1</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1134 516 L 1194 552 L 1134 587 L 1073 552 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="1134" y="556">edge == right</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1194 552 L 1268 552 Q 1278 552 1278 553 L 1278 554 Q 1278 554 1268 554 L 1250 554" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1258 550 L 1249 554 L 1258 559" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="1202" y="559" width="24" height="18" stroke-width="0"/>
|
|
||||||
<text x="1203" y="569">yes</text>
|
|
||||||
</g>
|
|
||||||
<rect x="1248" y="534" width="160" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="1328" y="551">axis = scroll_vertical</text>
|
|
||||||
<text x="1328" y="565">delta = dy</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1408 554 L 1468 554 Q 1478 554 1478 564 L 1478 952 Q 1478 962 1468 962 L 1233 962" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1241 958 L 1232 962 L 1241 967" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1133 318 L 1196 352 L 1133 387 L 1071 352 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="1133" y="356">edge == none</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1134 386 L 1134 441 Q 1134 451 1134 461 L 1134 514" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1129 506 L 1134 515 L 1138 506" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="1135" y="449" width="18" height="18" stroke-width="0"/>
|
|
||||||
<text x="1136" y="458">no</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1133 657 L 1194 692 L 1133 727 L 1072 692 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="1133" y="696">edge == bottom</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1194 692 L 1208 692 Q 1218 692 1228 692 L 1249 692" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1241 697 L 1250 692 L 1241 688" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="1213" y="700" width="24" height="18" stroke-width="0"/>
|
|
||||||
<text x="1214" y="709">yes</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1134 587 L 1133 587 Q 1133 587 1133 597 L 1133 647 Q 1133 657 1133 656 L 1133 655" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1129 647 L 1133 656 L 1138 647" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="1135" y="607" width="18" height="18" stroke-width="0"/>
|
|
||||||
<text x="1135" y="621">no</text>
|
|
||||||
</g>
|
|
||||||
<rect x="1251" y="672" width="160" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="1331" y="689">axis = scroll_horizontal</text>
|
|
||||||
<text x="1331" y="703">delta = dx</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1133 727 L 1133 727 Q 1134 727 1134 737 L 1134 807 Q 1134 817 1134 816 L 1134 815" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1129 807 L 1134 816 L 1138 807" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="1135" y="756" width="18" height="18" stroke-width="0"/>
|
|
||||||
<text x="1136" y="770">no</text>
|
|
||||||
</g>
|
|
||||||
<rect x="1036" y="917" width="195" height="90" rx="36" ry="36" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="1134" y="966">get_delta()</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1134 1007 L 1134 1037 Q 1134 1047 1134 1057 L 1134 1070" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1129 1062 L 1134 1071 L 1138 1062" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1411 692 L 1468 692 Q 1478 692 1478 702 L 1478 952 Q 1478 962 1468 962 L 1233 962" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1241 958 L 1232 962 L 1241 967" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<rect x="1031" y="1197" width="205" height="90" rx="36" ry="36" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="1134" y="1232">notify_axis(axis, delta)</text>
|
|
||||||
<text x="1134" y="1246">last_axis = axis</text>
|
|
||||||
<text x="1134" y="1260">emit(scroll_event_posted)</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1134 1072 L 1200 1107 L 1134 1142 L 1067 1107 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="1134" y="1111">delta < threshold</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1200 1107 L 1318 1107 Q 1328 1107 1338 1107 L 1456 1107" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1448 1112 L 1457 1107 L 1448 1103" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="1259" y="1118" width="24" height="18" stroke-width="0"/>
|
|
||||||
<text x="1260" y="1131">yes</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1134 1142 L 1134 1160 Q 1134 1170 1134 1180 L 1134 1195" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1129 1187 L 1134 1196 L 1138 1187" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="1135" y="1150" width="18" height="18" stroke-width="0"/>
|
|
||||||
<text x="1136" y="1159">no</text>
|
|
||||||
</g>
|
|
||||||
<ellipse cx="1473" cy="1107" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<ellipse cx="1473" cy="1107" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<ellipse cx="1473" cy="352" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<ellipse cx="1473" cy="352" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<path d="M 1331 318 L 1394 352 L 1331 387 L 1269 352 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="1331" y="356">last_axis != -1</text>
|
|
||||||
</g>
|
|
||||||
<rect x="30" y="657" width="150" height="101" rx="6" ry="6" fill="#ccffcc" stroke="#000000" stroke-width="2" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="105" y="697">EDGE</text>
|
|
||||||
<text x="105" y="711">on-entry:</text>
|
|
||||||
<text x="105" y="725">threshold = 0.01</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 30 707 L 18 707 Q 8 707 8 697 L 8 42 Q 8 32 18 32 L 214 32" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 219 32 L 212 36 L 214 32 L 212 29 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 30 436 L 18 436 Q 8 436 8 426 L 8 42 Q 8 32 18 32 L 214 32" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 219 32 L 212 36 L 214 32 L 212 29 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 64 535 C 68 531 74 528 80 528 L 130 528 C 136 528 142 531 146 535 L 175 570 C 176 571 176 574 175 575 L 146 610 C 142 614 136 617 130 617 L 80 617 C 74 617 68 614 64 610 L 35 575 C 34 574 34 571 35 570 L 64 535 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="105" y="563">timeout ||</text>
|
|
||||||
<text x="105" y="577">scroll_event_posted</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 105 487 L 105 522" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 105 527 L 102 520 L 105 522 L 109 520 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 260 528 L 261 472" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 261 467 L 264 474 L 261 472 L 257 474 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1196 352 L 1222 352 Q 1232 352 1242 352 L 1266 352" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1258 357 L 1267 352 L 1258 348" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="1224" y="360" width="24" height="18" stroke-width="0"/>
|
|
||||||
<text x="1224" y="369">yes</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1331 387 L 1331 401 Q 1331 411 1331 421 L 1331 434" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1327 426 L 1331 435 L 1336 426" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="1333" y="394" width="24" height="18" stroke-width="0"/>
|
|
||||||
<text x="1333" y="403">yes</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1394 352 L 1408 352 Q 1418 352 1428 352 L 1456 352" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1448 357 L 1457 352 L 1448 348" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="1417" y="360" width="18" height="18" stroke-width="0"/>
|
|
||||||
<text x="1418" y="369">no</text>
|
|
||||||
</g>
|
|
||||||
<ellipse cx="1473" cy="461" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<ellipse cx="1473" cy="461" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<path d="M 1425 461 L 1438 461 Q 1448 461 1452 461 L 1456 461" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1448 466 L 1457 461 L 1448 457" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<ellipse cx="1134" cy="832" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<ellipse cx="1134" cy="832" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<ellipse cx="1134" cy="1382" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<ellipse cx="1134" cy="1382" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<path d="M 1134 1287 L 1134 1365" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1130 1359 L 1134 1366 L 1137 1359" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 261 277 L 261 299" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 261 304 L 258 297 L 261 299 L 265 297 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 208 337 L 115 337 Q 105 337 105 347 L 105 376 Q 105 386 105 382 L 105 378" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 105 385 L 100 376 L 105 378 L 109 376 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="174" y="345" width="24" height="18" stroke-width="0"/>
|
|
||||||
<text x="175" y="354">yes</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 314 337 L 403 337 Q 413 337 413 347 L 413 376 Q 413 386 413 382 L 413 378" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 413 385 L 408 376 L 413 378 L 417 376 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="350" y="345" width="18" height="18" stroke-width="0"/>
|
|
||||||
<text x="350" y="354">no</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 261 305 L 314 337 L 261 369 L 208 337 Z" fill="#ffd966" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="261" y="341">get_edge()</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 261 406 L 309 436 L 261 466 L 213 436 Z" fill="#ffd966" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="261" y="440">edge</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 309 436 L 319 436 Q 328 436 334 436 L 340 436" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 347 436 L 338 441 L 340 436 L 338 432 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="311" y="444" width="18" height="18" stroke-width="0"/>
|
|
||||||
<text x="311" y="453">no</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 213 436 L 211 436 Q 208 436 198 436 L 188 436" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 181 436 L 190 432 L 188 436 L 190 441 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="189" y="444" width="24" height="18" stroke-width="0"/>
|
|
||||||
<text x="190" y="453">yes</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 147 KiB |
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="2180px" height="1624px" version="1.1">
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="2190px" height="1624px" version="1.1">
|
||||||
<defs/>
|
<defs/>
|
||||||
<g transform="translate(0.5,0.5)">
|
<g transform="translate(0.5,0.5)">
|
||||||
<path d="M 862 441 L 894 441" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 862 441 L 894 441" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
|
|
@ -68,13 +68,13 @@
|
||||||
<path d="M 712 441 L 668 441 Q 658 441 658 451 L 658 762" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 712 441 L 668 441 Q 658 441 658 451 L 658 762" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 786 62 L 786 81 Q 786 91 786 101 L 786 114" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 786 62 L 786 81 Q 786 91 786 101 L 786 114" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 786 120 L 783 113 L 786 114 L 790 113 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 786 120 L 783 113 L 786 114 L 790 113 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<rect x="1753" y="412" width="120" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
<rect x="1753" y="472" width="120" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
<text x="1813" y="429">Check state of</text>
|
<text x="1813" y="489">Check state of</text>
|
||||||
<text x="1813" y="443">all touches</text>
|
<text x="1813" y="503">all touches</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1813 452 L 1813 458 Q 1813 465 1813 470 L 1813 475" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1813 512 L 1813 518 Q 1813 524 1813 529 L 1813 534" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1809 467 L 1813 476 L 1818 467" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1809 526 L 1813 535 L 1818 526" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<ellipse cx="1813" cy="72" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
<ellipse cx="1813" cy="72" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
||||||
<path d="M 1813 87 L 1813 115 Q 1813 125 1813 135 L 1813 160" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1813 87 L 1813 115 Q 1813 125 1813 135 L 1813 160" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1809 152 L 1813 161 L 1818 152" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1809 152 L 1813 161 L 1818 152" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
|
|
@ -82,89 +82,88 @@
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
<text x="1813" y="41">tp_post_softbutton_buttons()</text>
|
<text x="1813" y="41">tp_post_softbutton_buttons()</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1813 192 L 1908 247 L 1813 302 L 1718 247 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1813 212 L 1908 267 L 1813 322 L 1718 267 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
<text x="1813" y="244">!buttons.click_pend</text>
|
<text x="1813" y="264">!buttons.click_pend</text>
|
||||||
<text x="1813" y="258">&& current == old</text>
|
<text x="1813" y="278">&& current == old</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1908 247 L 1968 247 Q 1978 247 1988 247 L 2056 247" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1908 267 L 1968 267 Q 1978 267 1988 267 L 2056 267" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 2048 252 L 2057 247 L 2048 243" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 2048 272 L 2057 267 L 2048 263" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||||
<rect fill="#ffffff" stroke="none" x="1998" y="228" width="24" height="18" stroke-width="0"/>
|
<rect fill="#ffffff" stroke="none" x="1998" y="252" width="18" height="14" stroke-width="0"/>
|
||||||
<text x="1999" y="241">yes</text>
|
<text x="1999" y="261">yes</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1813 302 L 1813 307 Q 1813 313 1813 317 L 1813 321" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1813 322 L 1813 332 Q 1813 342 1813 351 L 1813 360" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1809 313 L 1813 322 L 1818 313" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1809 352 L 1813 361 L 1818 352" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||||
<rect fill="#ffffff" stroke="none" x="1830" y="310" width="18" height="18" stroke-width="0"/>
|
<rect fill="#ffffff" stroke="none" x="1815" y="330" width="15" height="14" stroke-width="0"/>
|
||||||
<text x="1830" y="319">no</text>
|
<text x="1815" y="339">no</text>
|
||||||
</g>
|
</g>
|
||||||
<ellipse cx="2073" cy="247" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
<ellipse cx="2073" cy="267" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
||||||
<ellipse cx="2073" cy="247" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
|
<ellipse cx="2073" cy="267" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
|
||||||
<rect x="1713" y="102" width="200" height="70" rx="28" ry="28" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
<rect x="1708" y="112" width="200" height="60" rx="24" ry="24" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
<text x="1813" y="120">current = buttons.state & 0x01</text>
|
<text x="1808" y="132">current = buttons.state & 0x01</text>
|
||||||
<text x="1813" y="134">old = buttons.old_state & 0x01</text>
|
<text x="1808" y="146">old = buttons.old_state & 0x01</text>
|
||||||
<text x="1813" y="148">button = 0</text>
|
<text x="1808" y="160">button = 0</text>
|
||||||
<text x="1813" y="162">is_top = 0</text>
|
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1813 172 L 1813 177 Q 1813 182 1813 186 L 1813 190" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1813 172 L 1813 182 Q 1813 192 1813 201 L 1813 210" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1809 182 L 1813 191 L 1818 182" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1809 202 L 1813 211 L 1818 202" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1813 568 L 1918 626 L 1813 684 L 1708 626 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1813 536 L 1928 607 L 1813 678 L 1698 607 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
<text x="1813" y="630">All touches are in state none</text>
|
<text x="1813" y="611">All touches are in state none</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1813 684 L 1813 691 Q 1813 697 1813 702 L 1813 708" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1813 678 L 1813 684 Q 1813 690 1813 695 L 1813 700" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1809 700 L 1813 709 L 1818 700" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1809 692 L 1813 701 L 1818 692" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||||
<rect fill="#ffffff" stroke="none" x="1820" y="691" width="18" height="18" stroke-width="0"/>
|
<rect fill="#ffffff" stroke="none" x="1820" y="687" width="15" height="14" stroke-width="0"/>
|
||||||
<text x="1820" y="704">no</text>
|
<text x="1820" y="696">no</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1918 626 L 1936 626 Q 1946 626 1955 626 L 1971 626" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1928 607 L 1938 607 Q 1948 607 1957 607 L 1966 607" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1963 631 L 1972 626 L 1963 622" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1958 612 L 1967 607 L 1958 603" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||||
<rect fill="#ffffff" stroke="none" x="1920" y="634" width="24" height="18" stroke-width="0"/>
|
<rect fill="#ffffff" stroke="none" x="1930" y="615" width="18" height="14" stroke-width="0"/>
|
||||||
<text x="1920" y="643">yes</text>
|
<text x="1930" y="624">yes</text>
|
||||||
</g>
|
</g>
|
||||||
<rect x="1973" y="606" width="150" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
<rect x="1968" y="587" width="150" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
<text x="2048" y="630">buttons.click_pend = 1</text>
|
<text x="2043" y="611">buttons.click_pend = 1</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 2123 626 L 2128 626 Q 2133 626 2137 626 L 2141 626" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 2118 607 L 2128 607 Q 2138 607 2147 607 L 2156 607" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 2133 631 L 2142 626 L 2133 622" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 2148 612 L 2157 607 L 2148 603" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1813 710 L 1938 795 L 1813 880 L 1688 795 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1813 702 L 1938 787 L 1813 872 L 1688 787 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
<text x="1813" y="785">(Some touches are in middle) ||</text>
|
<text x="1813" y="777">(Some touches are in middle) ||</text>
|
||||||
<text x="1813" y="799">((Some touches are in right) &&</text>
|
<text x="1813" y="791">((Some touches are in right) &&</text>
|
||||||
<text x="1813" y="813">(Some touches are in left))</text>
|
<text x="1813" y="805">(Some touches are in left))</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1938 795 L 1943 795 Q 1948 795 1957 795 L 1966 795" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1938 787 L 1943 787 Q 1948 787 1957 787 L 1966 787" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1958 800 L 1967 795 L 1958 791" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1958 792 L 1967 787 L 1958 783" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||||
<rect fill="#ffffff" stroke="none" x="1941" y="803" width="24" height="18" stroke-width="0"/>
|
<rect fill="#ffffff" stroke="none" x="1941" y="795" width="18" height="14" stroke-width="0"/>
|
||||||
<text x="1942" y="812">yes</text>
|
<text x="1942" y="804">yes</text>
|
||||||
</g>
|
</g>
|
||||||
<rect x="1968" y="775" width="160" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
<rect x="1968" y="767" width="160" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
<text x="2048" y="799">button = BTN_MIDDLE</text>
|
<text x="2048" y="791">button = BTN_MIDDLE</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 2128 795 L 2158 795 Q 2168 795 2168 805 L 2168 1197 Q 2168 1207 2158 1207 L 1913 1207" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 2128 787 L 2158 787 Q 2168 787 2168 797 L 2168 1207 Q 2168 1217 2158 1217 L 1913 1217" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1921 1203 L 1912 1207 L 1921 1212" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1921 1213 L 1912 1217 L 1921 1222" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1813 323 L 1876 357 L 1813 392 L 1751 357 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1813 362 L 1876 396 L 1813 431 L 1751 396 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
<text x="1813" y="361">current</text>
|
<text x="1813" y="400">current</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1751 357 L 1606 357 Q 1596 357 1596 367 L 1596 1160" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1751 396 L 1601 396 Q 1591 396 1591 406 L 1591 1172 Q 1591 1182 1591 1182 L 1592 1182" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1592 1152 L 1596 1161 L 1601 1152" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1596 1180 L 1591 1182 L 1596 1184" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||||
<rect fill="#ffffff" stroke="none" x="1687" y="338" width="18" height="18" stroke-width="0"/>
|
<rect fill="#ffffff" stroke="none" x="1688" y="381" width="15" height="14" stroke-width="0"/>
|
||||||
<text x="1687" y="351">no</text>
|
<text x="1688" y="390">no</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1813 392 L 1813 397 Q 1813 402 1813 406 L 1813 410" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1813 431 L 1813 441 Q 1813 451 1813 461 L 1813 470" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1809 402 L 1813 411 L 1818 402" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1809 462 L 1813 471 L 1818 462" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||||
<rect fill="#ffffff" stroke="none" x="1830" y="390" width="24" height="18" stroke-width="0"/>
|
<rect fill="#ffffff" stroke="none" x="1815" y="438" width="18" height="14" stroke-width="0"/>
|
||||||
<text x="1830" y="399">yes</text>
|
<text x="1815" y="448">yes</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1813 902 L 1909 967 L 1813 1032 L 1717 967 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1813 902 L 1909 967 L 1813 1032 L 1717 967 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
|
|
@ -173,13 +172,13 @@
|
||||||
<path d="M 1909 967 L 1928 967 Q 1938 967 1948 967 L 1966 967" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1909 967 L 1928 967 Q 1938 967 1948 967 L 1966 967" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1958 972 L 1967 967 L 1958 963" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1958 972 L 1967 967 L 1958 963" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||||
<rect fill="#ffffff" stroke="none" x="1930" y="975" width="24" height="18" stroke-width="0"/>
|
<rect fill="#ffffff" stroke="none" x="1930" y="975" width="18" height="14" stroke-width="0"/>
|
||||||
<text x="1930" y="984">yes</text>
|
<text x="1930" y="984">yes</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1813 880 L 1813 886 Q 1813 891 1813 895 L 1813 900" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1813 872 L 1813 880 Q 1813 887 1813 893 L 1813 900" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1809 892 L 1813 901 L 1818 892" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1809 892 L 1813 901 L 1818 892" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||||
<rect fill="#ffffff" stroke="none" x="1820" y="883" width="18" height="18" stroke-width="0"/>
|
<rect fill="#ffffff" stroke="none" x="1820" y="887" width="15" height="14" stroke-width="0"/>
|
||||||
<text x="1820" y="896">no</text>
|
<text x="1820" y="896">no</text>
|
||||||
</g>
|
</g>
|
||||||
<rect x="1968" y="947" width="160" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
<rect x="1968" y="947" width="160" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||||
|
|
@ -193,28 +192,25 @@
|
||||||
<path d="M 1813 1032 L 1813 1047 Q 1813 1057 1813 1067 L 1813 1080" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1813 1032 L 1813 1047 Q 1813 1057 1813 1067 L 1813 1080" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1809 1072 L 1813 1081 L 1818 1072" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1809 1072 L 1813 1081 L 1818 1072" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||||
<rect fill="#ffffff" stroke="none" x="1815" y="1040" width="18" height="18" stroke-width="0"/>
|
<rect fill="#ffffff" stroke="none" x="1815" y="1044" width="15" height="14" stroke-width="0"/>
|
||||||
<text x="1815" y="1053">no</text>
|
<text x="1815" y="1053">no</text>
|
||||||
</g>
|
</g>
|
||||||
<rect x="1716" y="1162" width="195" height="90" rx="36" ry="36" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
<rect x="1716" y="1182" width="195" height="70" rx="28" ry="28" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
<text x="1814" y="1197">buttons.active = button</text>
|
<text x="1813" y="1214">buttons.active = button</text>
|
||||||
<text x="1814" y="1211">buttons.active_is_top = is_top</text>
|
<text x="1813" y="1228">state = BUTTON_PRESSED</text>
|
||||||
<text x="1814" y="1225">state = BUTTON_PRESSED</text>
|
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1814 1252 L 1814 1282 Q 1814 1292 1804 1292 L 1713 1292 Q 1703 1292 1703 1302 L 1703 1330" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1813 1252 L 1813 1282 Q 1813 1292 1803 1292 L 1713 1292 Q 1703 1292 1703 1302 L 1703 1330" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1699 1322 L 1703 1331 L 1708 1322" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1699 1322 L 1703 1331 L 1708 1322" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1813 1122 L 1813 1122 Q 1813 1122 1813 1132 L 1813 1152 Q 1813 1162 1813 1161 L 1813 1160" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1813 1122 L 1813 1142 Q 1813 1152 1813 1162 L 1813 1180" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1809 1152 L 1813 1161 L 1818 1152" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1809 1172 L 1813 1181 L 1818 1172" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 2128 967 L 2158 967 Q 2168 967 2168 977 L 2168 1197 Q 2168 1207 2158 1207 L 1913 1207" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 2128 967 L 2158 967 Q 2168 967 2168 977 L 2168 1207 Q 2168 1217 2158 1217 L 1913 1217" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1921 1203 L 1912 1207 L 1921 1212" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1921 1213 L 1912 1217 L 1921 1222" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<rect x="1493" y="1162" width="205" height="90" rx="36" ry="36" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
<rect x="1493" y="1182" width="195" height="70" rx="28" ry="28" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
<text x="1596" y="1183">button = buttons.active</text>
|
<text x="1591" y="1207">button = buttons.active</text>
|
||||||
<text x="1596" y="1197">is_top = buttons.active_is_top</text>
|
<text x="1591" y="1221">buttons.active = 0</text>
|
||||||
<text x="1596" y="1211">buttons.active = 0</text>
|
<text x="1591" y="1235">state = BUTTON_RELEASED</text>
|
||||||
<text x="1596" y="1225">buttons.active_is_top = 0</text>
|
|
||||||
<text x="1596" y="1239">state = BUTTON_RELEASED</text>
|
|
||||||
</g>
|
</g>
|
||||||
<rect x="1628" y="1332" width="150" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
<rect x="1628" y="1332" width="150" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
|
|
@ -222,7 +218,7 @@
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1703 1372 L 1703 1380 Q 1703 1387 1703 1393 L 1703 1400" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1703 1372 L 1703 1380 Q 1703 1387 1703 1393 L 1703 1400" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1699 1392 L 1703 1401 L 1708 1392" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1699 1392 L 1703 1401 L 1708 1392" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1596 1252 L 1596 1282 Q 1596 1292 1606 1292 L 1693 1292 Q 1703 1292 1703 1302 L 1703 1330" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1591 1252 L 1591 1282 Q 1591 1292 1601 1292 L 1693 1292 Q 1703 1292 1703 1302 L 1703 1330" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1699 1322 L 1703 1331 L 1708 1322" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1699 1322 L 1703 1331 L 1708 1322" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1703 1402 L 1743 1422 L 1703 1442 L 1663 1422 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1703 1402 L 1743 1422 L 1703 1442 L 1663 1422 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
|
|
@ -231,26 +227,26 @@
|
||||||
<path d="M 1743 1422 L 1808 1422 Q 1818 1422 1818 1432 L 1818 1597 Q 1818 1607 1808 1607 L 1720 1607" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1743 1422 L 1808 1422 Q 1818 1422 1818 1432 L 1818 1597 Q 1818 1607 1808 1607 L 1720 1607" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1728 1603 L 1719 1607 L 1728 1612" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1728 1603 L 1719 1607 L 1728 1612" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||||
<rect fill="#ffffff" stroke="none" x="1745" y="1403" width="18" height="18" stroke-width="0"/>
|
<rect fill="#ffffff" stroke="none" x="1745" y="1407" width="15" height="14" stroke-width="0"/>
|
||||||
<text x="1745" y="1416">no</text>
|
<text x="1745" y="1416">no</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1703 1442 L 1703 1452 Q 1703 1462 1703 1471 L 1703 1480" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1703 1442 L 1703 1452 Q 1703 1462 1703 1471 L 1703 1480" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1699 1472 L 1703 1481 L 1708 1472" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1699 1472 L 1703 1481 L 1708 1472" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||||
<rect fill="#ffffff" stroke="none" x="1705" y="1450" width="24" height="18" stroke-width="0"/>
|
<rect fill="#ffffff" stroke="none" x="1705" y="1450" width="18" height="14" stroke-width="0"/>
|
||||||
<text x="1705" y="1459">yes</text>
|
<text x="1705" y="1459">yes</text>
|
||||||
</g>
|
</g>
|
||||||
<rect x="1618" y="1482" width="170" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
<rect x="1618" y="1482" width="170" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
<text x="1703" y="1499">tp_notify_softbutton(</text>
|
<text x="1703" y="1499">pointer_notify_button(</text>
|
||||||
<text x="1703" y="1513">button, is_top, state)</text>
|
<text x="1703" y="1513">button, state)</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 1703 1522 L 1703 1542 Q 1703 1552 1703 1562 L 1703 1590" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1703 1522 L 1703 1542 Q 1703 1552 1703 1562 L 1703 1590" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1699 1582 L 1703 1591 L 1708 1582" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 1699 1582 L 1703 1591 L 1708 1582" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<ellipse cx="1703" cy="1607" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
<ellipse cx="1703" cy="1607" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
||||||
<ellipse cx="1703" cy="1607" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
|
<ellipse cx="1703" cy="1607" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
|
||||||
<ellipse cx="2158" cy="626" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
<ellipse cx="2173" cy="607" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
||||||
<ellipse cx="2158" cy="626" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
|
<ellipse cx="2173" cy="607" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
|
||||||
<path d="M 456 232 C 458 229 461 227 464 227 L 490 227 C 493 227 496 229 498 232 L 514 256 C 514 257 514 259 514 260 L 498 284 C 496 287 493 289 490 289 L 464 289 C 461 289 458 287 456 284 L 440 260 C 440 259 440 257 440 256 L 456 232 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 456 232 C 458 229 461 227 464 227 L 490 227 C 493 227 496 229 498 232 L 514 256 C 514 257 514 259 514 260 L 498 284 C 496 287 493 289 490 289 L 464 289 C 461 289 458 287 456 284 L 440 260 C 440 259 440 257 440 256 L 456 232 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
<text x="477" y="255">finger in</text>
|
<text x="477" y="255">finger in</text>
|
||||||
|
|
@ -265,8 +261,8 @@
|
||||||
<text x="477" y="453">curr = button</text>
|
<text x="477" y="453">curr = button</text>
|
||||||
<text x="477" y="467">start enter timeout</text>
|
<text x="477" y="467">start enter timeout</text>
|
||||||
</g>
|
</g>
|
||||||
<path d="M 477 289 L 477 330 Q 477 340 477 350 L 477 385" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 477 289 L 477 385" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 477 391 L 473 384 L 477 385 L 480 384 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 477 391 L 474 384 L 477 385 L 481 384 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 552 442 L 648 442 Q 658 442 658 452 L 658 762" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 552 442 L 648 442 Q 658 442 658 452 L 658 762" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<rect x="412" y="712" width="130" height="100" rx="6" ry="6" fill="#ccffcc" stroke="#000000" stroke-width="2" pointer-events="none"/>
|
<rect x="412" y="712" width="130" height="100" rx="6" ry="6" fill="#ccffcc" stroke="#000000" stroke-width="2" pointer-events="none"/>
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||||
|
|
@ -360,27 +356,5 @@
|
||||||
<path d="M 737 32 L 730 36 L 732 32 L 730 29 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 737 32 L 730 36 L 732 32 L 730 29 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 66 762 L 18 762 Q 8 762 8 752 L 8 42 Q 8 32 18 32 L 732 32" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 66 762 L 18 762 Q 8 762 8 752 L 8 42 Q 8 32 18 32 L 732 32" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 737 32 L 730 36 L 732 32 L 730 29 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
<path d="M 737 32 L 730 36 L 732 32 L 730 29 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
<path d="M 1813 477 L 1876 511 L 1813 546 L 1751 511 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="1813" y="515">touches in top?</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1876 511 L 1928 511 Q 1938 511 1938 518 L 1938 524" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1934 516 L 1938 525 L 1943 516" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="1890" y="500" width="24" height="18" stroke-width="0"/>
|
|
||||||
<text x="1890" y="509">yes</text>
|
|
||||||
</g>
|
|
||||||
<rect x="1898" y="526" width="80" height="30" rx="12" ry="12" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
|
||||||
<text x="1938" y="545">is_top = 1</text>
|
|
||||||
</g>
|
|
||||||
<path d="M 1938 556 L 1938 562 Q 1938 568 1928 568 L 1815 568" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1823 564 L 1814 568 L 1823 573" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1813 546 L 1813 554 Q 1813 562 1813 564 L 1813 566" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<path d="M 1809 558 L 1813 567 L 1818 558" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
|
||||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
|
||||||
<rect fill="#ffffff" stroke="none" x="1820" y="550" width="18" height="18" stroke-width="0"/>
|
|
||||||
<text x="1820" y="559">no</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 489 KiB After Width: | Height: | Size: 81 KiB |
|
|
@ -1,9 +0,0 @@
|
||||||
:orphan:
|
|
||||||
|
|
||||||
===
|
|
||||||
404
|
|
||||||
===
|
|
||||||
|
|
||||||
This page has permanently moved, probably to `<@TARGET@>`_
|
|
||||||
|
|
||||||
This placeholder page will be removed soon.
|
|
||||||
|
|
@ -1,144 +0,0 @@
|
||||||
.. _absolute_axes:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Absolute axes
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
Devices with absolute axes are those that send positioning data for an axis in
|
|
||||||
a device-specific coordinate range, defined by a minimum and a maximum value.
|
|
||||||
Compare this to relative devices (e.g. a mouse) that can only detect
|
|
||||||
directional data, not positional data.
|
|
||||||
|
|
||||||
libinput supports three types of devices with absolute axes:
|
|
||||||
|
|
||||||
- multi-touch screens
|
|
||||||
- single-touch screens
|
|
||||||
- :ref:`graphics tablets <tablet-support>`
|
|
||||||
|
|
||||||
Touchpads are technically absolute devices but libinput converts the axis values
|
|
||||||
to directional motion and posts events as relative events. Touchpads do not count
|
|
||||||
as absolute devices in libinput.
|
|
||||||
|
|
||||||
For all absolute devices in libinput, the default unit for x/y coordinates is
|
|
||||||
in mm off the top left corner on the device, or more specifically off the
|
|
||||||
device's sensor. If the device is physically rotated from its natural
|
|
||||||
position and this rotation was communicated to libinput (e.g. by setting
|
|
||||||
the device left-handed),
|
|
||||||
the coordinate origin is the top left corner in the current rotation.
|
|
||||||
|
|
||||||
.. _absolute_axes_handling:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Handling of absolute coordinates
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
In most use-cases, absolute input devices are mapped to a single screen. For
|
|
||||||
direct input devices such as touchscreens the aspect ratio of the screen and
|
|
||||||
the device match. Mapping the input device position to the output position is
|
|
||||||
thus a simple mapping between two coordinates. libinput provides the API for
|
|
||||||
this with
|
|
||||||
|
|
||||||
- **libinput_event_pointer_get_absolute_x_transformed()** for pointer events
|
|
||||||
- **libinput_event_touch_get_x_transformed()** for touch events
|
|
||||||
|
|
||||||
libinput's API only provides the call to map into a single coordinate range.
|
|
||||||
If the coordinate range has an offset, the compositor is responsible for
|
|
||||||
applying that offset after the mapping. For example, if the device is mapped
|
|
||||||
to the right of two outputs, add the output offset to the transformed
|
|
||||||
coordinate.
|
|
||||||
|
|
||||||
.. _absolute_axes_nores:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Devices without x/y resolution
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
An absolute device that does not provide a valid resolution is considered
|
|
||||||
buggy and must be fixed in the kernel. Some touchpad devices do not
|
|
||||||
provide resolution, those devices are correctly handled within libinput
|
|
||||||
(touchpads are not absolute devices, as mentioned above).
|
|
||||||
|
|
||||||
.. _calibration:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Calibration of absolute devices
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Absolute devices may require calibration to map precisely into the output
|
|
||||||
range required. This is done by setting a transformation matrix, see
|
|
||||||
**libinput_device_config_calibration_set_matrix()** which is applied to
|
|
||||||
each input coordinate.
|
|
||||||
|
|
||||||
.. math::
|
|
||||||
\begin{pmatrix}
|
|
||||||
cos\theta & -sin\theta & xoff \\
|
|
||||||
sin\theta & cos\theta & yoff \\
|
|
||||||
0 & 0 & 1
|
|
||||||
\end{pmatrix} \begin{pmatrix}
|
|
||||||
x \\ y \\ 1
|
|
||||||
\end{pmatrix}
|
|
||||||
|
|
||||||
:math:`\theta` is the rotation angle. The offsets :math:`xoff` and :math:`yoff` are
|
|
||||||
specified in device dimensions, i.e. a value of 1 equals one device width or
|
|
||||||
height. Note that rotation applies to the device's origin, rotation usually
|
|
||||||
requires an offset to move the coordinates back into the original range.
|
|
||||||
|
|
||||||
The most common matrices are:
|
|
||||||
|
|
||||||
- 90 degree clockwise:
|
|
||||||
.. math::
|
|
||||||
\begin{pmatrix}
|
|
||||||
0 & -1 & 1 \\
|
|
||||||
1 & 0 & 0 \\
|
|
||||||
0 & 0 & 1
|
|
||||||
\end{pmatrix}
|
|
||||||
- 180 degree clockwise:
|
|
||||||
.. math::
|
|
||||||
\begin{pmatrix}
|
|
||||||
-1 & 0 & 1 \\
|
|
||||||
0 & -1 & 1 \\
|
|
||||||
0 & 0 & 1
|
|
||||||
\end{pmatrix}
|
|
||||||
- 270 degree clockwise:
|
|
||||||
.. math::
|
|
||||||
\begin{pmatrix}
|
|
||||||
0 & 1 & 0 \\
|
|
||||||
-1 & 0 & 1 \\
|
|
||||||
0 & 0 & 1
|
|
||||||
\end{pmatrix}
|
|
||||||
- reflection along y axis:
|
|
||||||
.. math::
|
|
||||||
\begin{pmatrix}
|
|
||||||
-1 & 0 & 1 \\
|
|
||||||
1 & 0 & 0 \\
|
|
||||||
0 & 0 & 1
|
|
||||||
\end{pmatrix}
|
|
||||||
|
|
||||||
See Wikipedia's
|
|
||||||
`Transformation Matrix article <http://en.wikipedia.org/wiki/Transformation_matrix>`_
|
|
||||||
for more information on the matrix maths. See
|
|
||||||
**libinput_device_config_calibration_get_default_matrix()** for how these
|
|
||||||
matrices must be supplied to libinput.
|
|
||||||
|
|
||||||
Once applied, any x and y axis value has the calibration applied before it
|
|
||||||
is made available to the caller. libinput does not provide access to the
|
|
||||||
raw coordinates before the calibration is applied.
|
|
||||||
|
|
||||||
.. _absolute_axes_nonorm:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Why x/y coordinates are not normalized
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
x/y are not given in :ref:`normalized coordinates <motion_normalization>`
|
|
||||||
([0..1]) for one simple reason: the aspect ratio of virtually all current
|
|
||||||
devices is something other than 1:1. A normalized axes thus is only useful to
|
|
||||||
determine that the stylus is e.g. at 78% from the left, 34% from the top of
|
|
||||||
the device. Without knowing the per-axis resolution, these numbers are
|
|
||||||
meaningless. Worse, calculation based on previous coordinates is simply wrong:
|
|
||||||
a movement from 0/0 to 50%/50% is not a 45-degree line.
|
|
||||||
|
|
||||||
This could be alleviated by providing resolution and information about the
|
|
||||||
aspect ratio to the caller. Which shifts processing and likely errors into the
|
|
||||||
caller for little benefit. Providing the x/y axes in mm from the outset
|
|
||||||
removes these errors.
|
|
||||||
|
|
@ -1,153 +0,0 @@
|
||||||
.. _absolute_coordinate_ranges:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Coordinate ranges for absolute axes
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
libinput requires that all touchpads provide a correct axis range and
|
|
||||||
resolution. These are used to enable or disable certain features or adapt
|
|
||||||
the interaction with the touchpad. For example, the software button area is
|
|
||||||
narrower on small touchpads to avoid reducing the interactive surface too
|
|
||||||
much. Likewise, palm detection works differently on small touchpads as palm
|
|
||||||
interference is less likely to happen.
|
|
||||||
|
|
||||||
Touchpads with incorrect axis ranges generate error messages
|
|
||||||
in the form:
|
|
||||||
<blockquote>
|
|
||||||
Axis 0x35 value 4000 is outside expected range [0, 3000]
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
This error message indicates that the ABS_MT_POSITION_X axis (i.e. the x
|
|
||||||
axis) generated an event outside the expected range of 0-3000. In this case
|
|
||||||
the value was 4000.
|
|
||||||
This discrepancy between the coordinate range the kernels advertises vs.
|
|
||||||
what the touchpad sends can be the source of a number of perceived
|
|
||||||
bugs in libinput.
|
|
||||||
|
|
||||||
.. _absolute_coordinate_ranges_fix:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Measuring and fixing touchpad ranges
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
To fix the touchpad you need to:
|
|
||||||
|
|
||||||
#. measure the physical size of your touchpad in mm
|
|
||||||
#. run the ``libinput measure touchpad-size`` tool
|
|
||||||
#. verify the hwdb entry provided by this tool
|
|
||||||
#. test locally
|
|
||||||
#. send a patch to the `systemd project <https://github.com/systemd/systemd>`_.
|
|
||||||
|
|
||||||
Detailed explanations are below.
|
|
||||||
|
|
||||||
The ``libinput measure touchpad-size`` tool is an interactive tool. It must
|
|
||||||
be called with the physical dimensions of the touchpad in mm. In the example
|
|
||||||
below, we use 100mm wide and 55mm high. The tool will find the touchpad device
|
|
||||||
automatically.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$> sudo libinput measure touchpad-size 100x55
|
|
||||||
Using "Touchpad SynPS/2 Synaptics TouchPad": /dev/input/event4
|
|
||||||
|
|
||||||
Kernel specified touchpad size: 99.7x75.9mm
|
|
||||||
User specified touchpad size: 100.0x55.0mm
|
|
||||||
|
|
||||||
Kernel axis range: x [1024..5112], y [2024..4832]
|
|
||||||
Detected axis range: x [ 0.. 0], y [ 0.. 0]
|
|
||||||
|
|
||||||
Move one finger along all edges of the touchpad
|
|
||||||
until the detected axis range stops changing.
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
Move the finger around until the detected axis range matches the data sent
|
|
||||||
by the device. ``Ctrl+C`` terminates the tool and prints a
|
|
||||||
suggested hwdb entry. ::
|
|
||||||
|
|
||||||
...
|
|
||||||
Kernel axis range: x [1024..5112], y [2024..4832]
|
|
||||||
^C
|
|
||||||
Detected axis range: x [2072..4880], y [2159..4832]
|
|
||||||
Resolutions calculated based on user-specified size: x 28, y 49 units/mm
|
|
||||||
|
|
||||||
Suggested hwdb entry:
|
|
||||||
Note: the dmi modalias match is a guess based on your machine's modalias:
|
|
||||||
dmi:bvnLENOVO:bvrGJET72WW(2.22):bd02/21/2014:svnLENOVO:pn20ARS25701:pvrThinkPadT440s:rvnLENOVO:rn20ARS25701:rvrSDK0E50512STD:cvnLENOVO:ct10:cvrNotAvailable:
|
|
||||||
Please verify that this is the most sensible match and adjust if necessary.
|
|
||||||
-8<--------------------------
|
|
||||||
# Laptop model description (e.g. Lenovo X1 Carbon 5th)
|
|
||||||
evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrThinkPadT440s*
|
|
||||||
EVDEV_ABS_00=2072:4880:28
|
|
||||||
EVDEV_ABS_01=2159:4832:49
|
|
||||||
EVDEV_ABS_35=2072:4880:28
|
|
||||||
EVDEV_ABS_36=2159:4832:49
|
|
||||||
-8<--------------------------
|
|
||||||
Instructions on what to do with this snippet are in /usr/lib/udev/hwdb.d/60-evdev.hwdb
|
|
||||||
|
|
||||||
|
|
||||||
If there are discrepancies between the coordinate range the kernels
|
|
||||||
advertises and what the touchpad sends, the hwdb entry should be added to the
|
|
||||||
``60-evdev.hwdb`` file provided by the `systemd project <https://github.com/systemd/systemd>`_.
|
|
||||||
An example commit can be found
|
|
||||||
`here <https://github.com/systemd/systemd/commit/26f667eac1c5e89b689aa0a1daef6a80f473e045>`_.
|
|
||||||
|
|
||||||
The ``libinput measure touchpad-size`` tool attempts to provide the correct
|
|
||||||
dmi match but it does require user verification.
|
|
||||||
|
|
||||||
In most cases the dmi match can and should be trimmed to the system vendor (``svn``)
|
|
||||||
and the product version (``pvr``) or product name (``pn``), with everything else
|
|
||||||
replaced by a wildcard (``*``). In the above case, the match string is:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrThinkPadT440s*
|
|
||||||
|
|
||||||
As a general rule: for Lenovo devices use ``pvr`` and for all others use
|
|
||||||
``pn``.
|
|
||||||
|
|
||||||
.. note:: hwdb match strings only allow for alphanumeric ascii characters. Use a
|
|
||||||
wildcard (* or ?, whichever appropriate) for special characters.
|
|
||||||
|
|
||||||
The actual axis overrides are in the form:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
# axis number=min:max:resolution
|
|
||||||
EVDEV_ABS_00=2072:4880:28
|
|
||||||
|
|
||||||
or, if the range is correct but the resolution is wrong
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
# axis number=::resolution
|
|
||||||
EVDEV_ABS_00=::28
|
|
||||||
|
|
||||||
|
|
||||||
Note the leading single space. The axis numbers are in hex and can be found
|
|
||||||
in ``linux/input-event-codes.h``. For touchpads ``ABS_X``, ``ABS_Y``,
|
|
||||||
``ABS_MT_POSITION_X`` and ``ABS_MT_POSITION_Y`` are required.
|
|
||||||
|
|
||||||
.. note:: The touchpad's ranges and/or resolution should only be fixed when
|
|
||||||
there is a significant discrepancy. A few units do not make a
|
|
||||||
difference and a resolution that is off by 2 or less usually does
|
|
||||||
not matter either.
|
|
||||||
|
|
||||||
Once a match and override rule has been found, follow the instructions at
|
|
||||||
the top of the
|
|
||||||
`60-evdev.hwdb <https://github.com/systemd/systemd/blob/main/hwdb.d/60-evdev.hwdb>`_
|
|
||||||
file to save it locally and trigger the udev hwdb reload. Rebooting is
|
|
||||||
always a good idea. If the match string is correct, the new properties will
|
|
||||||
show up in the
|
|
||||||
output of
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
udevadm info /sys/class/input/event4
|
|
||||||
|
|
||||||
|
|
||||||
Adjust the command for the event node of your touchpad.
|
|
||||||
A udev builtin will apply the new axis ranges automatically.
|
|
||||||
|
|
||||||
When the axis override is confirmed to work, please submit it as a pull
|
|
||||||
request to the `systemd project <https://github.com/systemd/systemd>`_.
|
|
||||||
|
|
@ -1,416 +0,0 @@
|
||||||
.. _architecture:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
libinput's internal architecture
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
This page provides an outline of libinput's internal architecture. The goal
|
|
||||||
here is to get the high-level picture across and point out the components
|
|
||||||
and their interplay to new developers.
|
|
||||||
|
|
||||||
The public facing API is in ``libinput.c``, this file is thus the entry point
|
|
||||||
for almost all API calls. General device handling is in ``evdev.c`` with the
|
|
||||||
device-type-specific implementations in ``evdev-<type>.c``. It is not
|
|
||||||
necessary to understand all of libinput to contribute a patch.
|
|
||||||
|
|
||||||
As of libinput 1.29 libinput has an internal plugin pipeline that modifies
|
|
||||||
the event stream before libinput proper sees it, see
|
|
||||||
:ref:`architecture-plugins`.
|
|
||||||
|
|
||||||
:ref:`architecture-contexts` is the only user-visible implementation detail,
|
|
||||||
everything else is purely internal implementation and may change when
|
|
||||||
required.
|
|
||||||
|
|
||||||
.. _architecture-contexts:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
The udev and path contexts
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The first building block is the "context" which can be one of
|
|
||||||
two types, "path" and "udev". See **libinput_path_create_context()** and
|
|
||||||
**libinput_udev_create_context()**. The path/udev specific bits are in
|
|
||||||
``path-seat.c`` and ``udev-seat.c``. This includes the functions that add new
|
|
||||||
devices to a context.
|
|
||||||
|
|
||||||
|
|
||||||
.. graphviz::
|
|
||||||
|
|
||||||
|
|
||||||
digraph context
|
|
||||||
{
|
|
||||||
compound=true;
|
|
||||||
rankdir="LR";
|
|
||||||
node [
|
|
||||||
shape="box";
|
|
||||||
]
|
|
||||||
|
|
||||||
libudev [label="libudev 'add' event"]
|
|
||||||
udev [label="**libinput_udev_create_context()**"];
|
|
||||||
udev_backend [label="udev-specific backend"];
|
|
||||||
context [label="libinput context"]
|
|
||||||
udev -> udev_backend;
|
|
||||||
libudev -> udev_backend;
|
|
||||||
udev_backend -> context;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
The udev context provides automatic device hotplugging as udev's "add"
|
|
||||||
events are handled directly by libinput. The path context requires that the
|
|
||||||
caller adds devices.
|
|
||||||
|
|
||||||
|
|
||||||
.. graphviz::
|
|
||||||
|
|
||||||
|
|
||||||
digraph context
|
|
||||||
{
|
|
||||||
compound=true;
|
|
||||||
rankdir="LR";
|
|
||||||
node [
|
|
||||||
shape="box";
|
|
||||||
]
|
|
||||||
|
|
||||||
path [label="**libinput_path_create_context()**"];
|
|
||||||
path_backend [label="path-specific backend"];
|
|
||||||
xdriver [label="**libinput_path_add_device()**"]
|
|
||||||
context [label="libinput context"]
|
|
||||||
path -> path_backend;
|
|
||||||
xdriver -> path_backend;
|
|
||||||
path_backend -> context;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
As a general rule: all Wayland compositors use a udev context, the X.org
|
|
||||||
stack uses a path context.
|
|
||||||
|
|
||||||
Which context was initialized only matters for creating/destroying a context
|
|
||||||
and adding devices. The device handling itself is the same for both types of
|
|
||||||
context.
|
|
||||||
|
|
||||||
.. _architecture-device:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Device initialization
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
libinput only supports evdev devices, all the device initialization is done
|
|
||||||
in ``evdev.c``. Much of the libinput public API is also a thin wrapper around
|
|
||||||
the matching implementation in the evdev device.
|
|
||||||
|
|
||||||
There is a 1:1 mapping between libinput devices and ``/dev/input/eventX``
|
|
||||||
device nodes.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. graphviz::
|
|
||||||
|
|
||||||
|
|
||||||
digraph context
|
|
||||||
{
|
|
||||||
compound=true;
|
|
||||||
rankdir="LR";
|
|
||||||
node [
|
|
||||||
shape="box";
|
|
||||||
]
|
|
||||||
|
|
||||||
devnode [label="/dev/input/event0"]
|
|
||||||
|
|
||||||
libudev [label="libudev 'add' event"]
|
|
||||||
xdriver [label="**libinput_path_add_device()**"]
|
|
||||||
context [label="libinput context"]
|
|
||||||
|
|
||||||
evdev [label="evdev_device_create()"]
|
|
||||||
|
|
||||||
devnode -> xdriver;
|
|
||||||
devnode -> libudev;
|
|
||||||
xdriver -> context;
|
|
||||||
libudev -> context;
|
|
||||||
|
|
||||||
context->evdev;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Entry point for all devices is ``evdev_device_create()``, this function
|
|
||||||
decides to create a ``struct evdev_device`` for the given device node.
|
|
||||||
Based on the udev tags (e.g. ``ID_INPUT_TOUCHPAD``), a
|
|
||||||
:ref:`architecture-dispatch` is initialized. All event handling is then in this
|
|
||||||
dispatch.
|
|
||||||
|
|
||||||
Rejection of devices and the application of quirks is generally handled in
|
|
||||||
``evdev.c`` as well. Common functionality shared across multiple device types
|
|
||||||
(like button-scrolling) is also handled here.
|
|
||||||
|
|
||||||
.. _architecture-dispatch:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Device-type specific event dispatch
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Depending on the device type, ``evdev_configure_device`` creates the matching
|
|
||||||
``struct evdev_dispatch``. This dispatch interface contains the function
|
|
||||||
pointers to handle events. Four such dispatch methods are currently
|
|
||||||
implemented: touchpad, tablet, tablet pad, and the fallback dispatch which
|
|
||||||
handles mice, keyboards and touchscreens.
|
|
||||||
|
|
||||||
.. graphviz::
|
|
||||||
|
|
||||||
digraph context
|
|
||||||
{
|
|
||||||
compound=true;
|
|
||||||
rankdir="LR";
|
|
||||||
node [
|
|
||||||
shape="box";
|
|
||||||
]
|
|
||||||
|
|
||||||
evdev [label="evdev_device_create()"]
|
|
||||||
|
|
||||||
fallback [label="evdev-fallback.c"]
|
|
||||||
touchpad [label="evdev-mt-touchpad.c"]
|
|
||||||
tablet [label="evdev-tablet.c"]
|
|
||||||
pad [label="evdev-tablet-pad.c"]
|
|
||||||
|
|
||||||
evdev -> fallback;
|
|
||||||
evdev -> touchpad;
|
|
||||||
evdev -> tablet;
|
|
||||||
evdev -> pad;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Event dispatch is done per "evdev frame", a collection of events up until including
|
|
||||||
the ``SYN_REPORT``. One such ``struct evdev_frame`` represents all state **updates**
|
|
||||||
to the previous frame.
|
|
||||||
|
|
||||||
While ``evdev.c`` pulls the event out of libevdev, the actual handling of the
|
|
||||||
events is performed within the dispatch method.
|
|
||||||
|
|
||||||
.. graphviz::
|
|
||||||
|
|
||||||
digraph context
|
|
||||||
{
|
|
||||||
compound=true;
|
|
||||||
rankdir="LR";
|
|
||||||
node [
|
|
||||||
shape="box";
|
|
||||||
]
|
|
||||||
|
|
||||||
evdev [label="evdev_device_dispatch()"]
|
|
||||||
|
|
||||||
plugins [label="plugin pipeline"]
|
|
||||||
|
|
||||||
fallback [label="fallback_interface_process()"];
|
|
||||||
touchpad [label="tp_interface_process()"]
|
|
||||||
tablet [label="tablet_process()"]
|
|
||||||
pad [label="pad_process()"]
|
|
||||||
|
|
||||||
evdev -> plugins;
|
|
||||||
plugins -> fallback;
|
|
||||||
plugins -> touchpad;
|
|
||||||
plugins -> tablet;
|
|
||||||
plugins -> pad;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
The dispatch methods then look at the ``struct evdev_frame`` and proceed to
|
|
||||||
update the state.
|
|
||||||
|
|
||||||
.. _architecture-plugins:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
The Plugin Pipeline
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
As of libinput 1.29 libinput has an **internal** plugin pipeline. These plugins
|
|
||||||
logically sit between libevdev and the :ref:`architecture-dispatch` and modify
|
|
||||||
the device and/or event stream. The primary motivation of such plugins is that
|
|
||||||
modifying the event stream is often simpler than analyzing the state later.
|
|
||||||
|
|
||||||
Plugins are loaded on libinput context startup and are executed in-order. The last
|
|
||||||
plugin is the hardcoded `evdev-plugin.c` which takes the modified event stream and
|
|
||||||
passes the events to the dispatch.
|
|
||||||
|
|
||||||
.. graphviz::
|
|
||||||
|
|
||||||
digraph context
|
|
||||||
{
|
|
||||||
compound=true;
|
|
||||||
rankdir="LR";
|
|
||||||
node [
|
|
||||||
shape="box";
|
|
||||||
]
|
|
||||||
|
|
||||||
evdev [label="evdev_device_dispatch()"]
|
|
||||||
|
|
||||||
p1 [label="P1"]
|
|
||||||
p2 [label="P2"]
|
|
||||||
p3 [label="P3"]
|
|
||||||
ep [label="evdev-plugin"]
|
|
||||||
|
|
||||||
fallback [label="fallback_interface_process()"];
|
|
||||||
touchpad [label="tp_interface_process()"]
|
|
||||||
tablet [label="tablet_process()"]
|
|
||||||
pad [label="pad_process()"]
|
|
||||||
|
|
||||||
evdev -> p1;
|
|
||||||
p1 -> p2;
|
|
||||||
p2 -> p3;
|
|
||||||
p3 -> ep;
|
|
||||||
ep -> fallback;
|
|
||||||
ep -> touchpad;
|
|
||||||
ep -> tablet;
|
|
||||||
ep -> pad;
|
|
||||||
}
|
|
||||||
|
|
||||||
Each plugin may not only modify the current event frame (this includes adding/removing events
|
|
||||||
from the frame), it may also append or prepend additional event frames. For
|
|
||||||
example the tablet proximity-timer plugin adds proximity in/out events to the
|
|
||||||
event stream.
|
|
||||||
|
|
||||||
.. graphviz::
|
|
||||||
|
|
||||||
digraph context
|
|
||||||
{
|
|
||||||
compound=true;
|
|
||||||
rankdir="LR";
|
|
||||||
node [
|
|
||||||
shape="box";
|
|
||||||
]
|
|
||||||
n0 [label= "", shape=none,height=.0,width=.0]
|
|
||||||
n1 [label= "", shape=none,height=.0,width=.0]
|
|
||||||
|
|
||||||
p1 [label="P1"]
|
|
||||||
p2 [label="P2"]
|
|
||||||
p3 [label="P3"]
|
|
||||||
ep [label="evdev-plugin"]
|
|
||||||
|
|
||||||
n0 -> p1 [label="F1"];
|
|
||||||
p1 -> p2 [label="F1"];
|
|
||||||
p2 -> p3 [label="F1,F2"];
|
|
||||||
p3 -> ep [label="F3,F1,F2"];
|
|
||||||
ep -> n1 [label="F3,F1,F2"];
|
|
||||||
}
|
|
||||||
|
|
||||||
In the diagram above, the plugin ``P2`` *appends* a new frame (``F2``), the plugin ``P3``
|
|
||||||
*prepends* a new frame (``F3``). The original event frame ``F1`` thus becomes the event frame
|
|
||||||
sequence ``F3``, ``F1``, ``F2`` by the time it reaches the :ref:`architecture-dispatch`.
|
|
||||||
|
|
||||||
Note that each plugin only sees one event frame at a time, so ``P3`` would see ``F1`` first,
|
|
||||||
decides to prepend ``F3`` and passes ``F1`` through. It then sees ``F2`` but does nothing with
|
|
||||||
it (optionally modified in-place).
|
|
||||||
|
|
||||||
.. _architecture-configuration:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Device configuration
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
All device-specific configuration is handled through ``struct
|
|
||||||
libinput_device_config_FOO`` instances. These are set up during device init
|
|
||||||
and provide the function pointers for the ``get``, ``set``, ``get_default``
|
|
||||||
triplet of configuration queries (or more, where applicable).
|
|
||||||
|
|
||||||
For example, the ``struct tablet_dispatch`` for tablet devices has a
|
|
||||||
``struct libinput_device_config_accel``. This struct is set up with the
|
|
||||||
required function pointers to change the profiles.
|
|
||||||
|
|
||||||
|
|
||||||
.. graphviz::
|
|
||||||
|
|
||||||
|
|
||||||
digraph context
|
|
||||||
{
|
|
||||||
compound=true;
|
|
||||||
rankdir="LR";
|
|
||||||
node [
|
|
||||||
shape="box";
|
|
||||||
]
|
|
||||||
|
|
||||||
tablet [label="struct tablet_dispatch"]
|
|
||||||
config [label="struct libinput_device_config_accel"];
|
|
||||||
tablet_config [label="tablet_accel_config_set_profile()"];
|
|
||||||
tablet->config;
|
|
||||||
config->tablet_config;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
When the matching ``**libinput_device_config_set_FOO()**`` is called, this goes
|
|
||||||
through to the config struct and invokes the function there. Thus, it is
|
|
||||||
possible to have different configuration functions for a mouse vs a
|
|
||||||
touchpad, even though the interface is the same.
|
|
||||||
|
|
||||||
|
|
||||||
.. graphviz::
|
|
||||||
|
|
||||||
|
|
||||||
digraph context
|
|
||||||
{
|
|
||||||
compound=true;
|
|
||||||
rankdir="LR";
|
|
||||||
node [
|
|
||||||
shape="box";
|
|
||||||
]
|
|
||||||
|
|
||||||
libinput [label="**libinput_device_config_accel_set_profile()**"];
|
|
||||||
tablet_config [label="tablet_accel_config_set_profile()"];
|
|
||||||
libinput->tablet_config;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.. _architecture-filter:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Pointer acceleration filters
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
All pointer acceleration is handled in the ``filter.c`` file and its
|
|
||||||
associated files.
|
|
||||||
|
|
||||||
The ``struct motion_filter`` is initialized during device init, whenever
|
|
||||||
deltas are available they are passed to ``filter_dispatch()``. This function
|
|
||||||
returns a set of :ref:`normalized coordinates <motion_normalization_customization>`.
|
|
||||||
|
|
||||||
All actual acceleration is handled within the filter, the device itself has
|
|
||||||
no further knowledge. Thus it is possible to have different acceleration
|
|
||||||
filters for the same device types (e.g. the Lenovo X230 touchpad has a
|
|
||||||
custom filter).
|
|
||||||
|
|
||||||
|
|
||||||
.. graphviz::
|
|
||||||
|
|
||||||
|
|
||||||
digraph context
|
|
||||||
{
|
|
||||||
compound=true;
|
|
||||||
rankdir="LR";
|
|
||||||
node [
|
|
||||||
shape="box";
|
|
||||||
]
|
|
||||||
|
|
||||||
fallback [label="fallback deltas"];
|
|
||||||
touchpad [label="touchpad deltas"];
|
|
||||||
tablet [label="tablet deltas"];
|
|
||||||
|
|
||||||
filter [label="filter_dispatch"];
|
|
||||||
|
|
||||||
fallback->filter;
|
|
||||||
touchpad->filter;
|
|
||||||
tablet->filter;
|
|
||||||
|
|
||||||
flat [label="accelerator_interface_flat()"];
|
|
||||||
x230 [label="accelerator_filter_x230()"];
|
|
||||||
pen [label="tablet_accelerator_filter_flat_pen()"];
|
|
||||||
|
|
||||||
filter->flat;
|
|
||||||
filter->x230;
|
|
||||||
filter->pen;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Most filters convert the deltas (incl. timestamps) to a motion speed and
|
|
||||||
then apply a so-called profile function. This function returns a factor that
|
|
||||||
is then applied to the current delta, converting it into an accelerated
|
|
||||||
delta. See :ref:`pointer-acceleration` for more details.
|
|
||||||
the current
|
|
||||||
|
|
@ -1,299 +0,0 @@
|
||||||
.. _building_libinput:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
libinput build instructions
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:local:
|
|
||||||
:backlinks: entry
|
|
||||||
|
|
||||||
Instructions on how to build libinput and its tools and how to build against
|
|
||||||
libinput.
|
|
||||||
|
|
||||||
The build instruction on this page detail how to overwrite your
|
|
||||||
system-provided libinput with one from the git repository,
|
|
||||||
see :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 libinput
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
libinput uses `meson <https://www.mesonbuild.com>`_ and
|
|
||||||
`ninja <https://www.ninja-build.org>`_. A build is usually the three-step
|
|
||||||
process below. A successful build requires the
|
|
||||||
:ref:`building_dependencies` to be installed before running meson.
|
|
||||||
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$> git clone https://gitlab.freedesktop.org/libinput/libinput
|
|
||||||
$> cd libinput
|
|
||||||
$> meson setup --prefix=/usr builddir/
|
|
||||||
$> ninja -C builddir/
|
|
||||||
$> sudo ninja -C builddir/ install
|
|
||||||
|
|
||||||
|
|
||||||
When running libinput versions 1.11.x or earlier, you must run
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$> sudo systemd-hwdb update
|
|
||||||
|
|
||||||
|
|
||||||
Additional options may also be specified. For example:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$> meson setup --prefix=/usr -Ddocumentation=false builddir/
|
|
||||||
|
|
||||||
|
|
||||||
We recommend that users disable the documentation, it's not usually required
|
|
||||||
for testing and reduces the number of dependencies needed.
|
|
||||||
|
|
||||||
The ``prefix`` or other options can be changed later with the
|
|
||||||
``meson configure`` command. For example:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$> meson configure builddir/ -Dprefix=/some/other/prefix -Ddocumentation=true
|
|
||||||
$> ninja -C builddir
|
|
||||||
$> sudo ninja -C builddir/ install
|
|
||||||
|
|
||||||
|
|
||||||
Running ``meson configure builddir/`` with no other arguments lists all
|
|
||||||
configurable options meson provides.
|
|
||||||
|
|
||||||
To rebuild from scratch, simply remove the build directory and run meson
|
|
||||||
again:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$> rm -r builddir/
|
|
||||||
$> meson setup --prefix=....
|
|
||||||
|
|
||||||
|
|
||||||
.. _verifying_install:
|
|
||||||
|
|
||||||
..............................................................................
|
|
||||||
Verifying the install
|
|
||||||
..............................................................................
|
|
||||||
|
|
||||||
To verify the install worked correctly, check that libinput.so.x.x.x is in
|
|
||||||
the library path and that all symlinks point to the new library.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$> ldconfig -p | grep libinput | awk '{print $NF}' | xargs ls -l
|
|
||||||
lrwxrwxrwx 1 root root 14 lug 22 13:06 /usr/lib/x86_64-linux-gnu/libinput.so -> libinput.so.10
|
|
||||||
lrwxrwxrwx 1 root root 19 lug 22 13:06 /usr/lib/x86_64-linux-gnu/libinput.so.10 -> libinput.so.10.13.0
|
|
||||||
-rwxr-xr-x 1 root root 1064144 lug 22 13:06 /usr/lib/x86_64-linux-gnu/libinput.so.10.13.0
|
|
||||||
|
|
||||||
.. _reverting_install:
|
|
||||||
|
|
||||||
..............................................................................
|
|
||||||
Reverting to the system-provided libinput package
|
|
||||||
..............................................................................
|
|
||||||
|
|
||||||
The recommended way to revert to the system install is to use the package
|
|
||||||
manager to reinstall the libinput package. In some cases, this may leave
|
|
||||||
files in the system (e.g. ``/usr/lib/libinput.la``) but these files are
|
|
||||||
usually harmless. To definitely remove all files, run the following command
|
|
||||||
from the libinput source directory:
|
|
||||||
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$> sudo ninja -C builddir/ uninstall
|
|
||||||
# WARNING: Do not restart the computer/X/the Wayland compositor after
|
|
||||||
# uninstall, reinstall the system package immediately!
|
|
||||||
|
|
||||||
|
|
||||||
The following commands reinstall the current system package for libinput,
|
|
||||||
overwriting manually installed files.
|
|
||||||
|
|
||||||
- **Debian/Ubuntu** based distributions: ``sudo apt-get install --reinstall libinput``
|
|
||||||
- **Fedora 22** and later: ``sudo dnf reinstall libinput``
|
|
||||||
- **RHEL/CentOS/Fedora 21** and earlier: ``sudo yum reinstall libinput``
|
|
||||||
- **openSUSE**: ``sudo zypper install --force libinput10``
|
|
||||||
- **Arch**: ``sudo pacman -S libinput``
|
|
||||||
|
|
||||||
.. _building_selinux:
|
|
||||||
|
|
||||||
..............................................................................
|
|
||||||
SELinux adjustments
|
|
||||||
..............................................................................
|
|
||||||
|
|
||||||
.. note:: This section only applies to meson version < 0.42.0
|
|
||||||
|
|
||||||
On systems with SELinux, overwriting the distribution-provided package with
|
|
||||||
a manually built libinput may cause SELinux denials. This usually manifests
|
|
||||||
when gdm does not start because it is denied access to libinput. The journal
|
|
||||||
shows a log message in the form of:
|
|
||||||
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
May 25 15:28:42 localhost.localdomain audit[23268]: AVC avc: denied { execute } for pid=23268 comm="gnome-shell" path="/usr/lib64/libinput.so.10.12.2" dev="dm-0" ino=1709093 scontext=system_u:system_r:xdm_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=0
|
|
||||||
May 25 15:28:42 localhost.localdomain org.gnome.Shell.desktop[23270]: /usr/bin/gnome-shell: error while loading shared libraries: libinput.so.10: failed to map segment from shared object
|
|
||||||
|
|
||||||
|
|
||||||
The summary of this error message is that gdm's gnome-shell runs in the
|
|
||||||
``system_u:system_r:xdm_t`` context but libinput is installed with the
|
|
||||||
context ``unconfined_u:object_r:user_home_t``.
|
|
||||||
|
|
||||||
To avoid this issue, restore the SELinux context for any system files.
|
|
||||||
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$> sudo restorecon /usr/lib*/libinput.so.*
|
|
||||||
|
|
||||||
|
|
||||||
This issue is tracked in https://github.com/mesonbuild/meson/issues/1967.
|
|
||||||
|
|
||||||
.. _building_dependencies:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Build dependencies
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
libinput has a few build-time dependencies that must be installed prior to
|
|
||||||
running meson.
|
|
||||||
|
|
||||||
.. hint:: The build dependencies for some distributions can be found in the
|
|
||||||
`GitLab Continuous Integration file <https://gitlab.freedesktop.org/libinput/libinput/blob/main/.gitlab-ci.yml>`_.
|
|
||||||
Search for **FEDORA_PACKAGES** in the **variables:** definition
|
|
||||||
and check the list for an entry for your distribution.
|
|
||||||
|
|
||||||
In most cases, it is sufficient to install the dependencies that your
|
|
||||||
distribution uses to build the libinput package. These can be installed
|
|
||||||
with one of the following commands:
|
|
||||||
|
|
||||||
- **Debian/Ubuntu** based distributions: ``sudo apt-get build-dep libinput``
|
|
||||||
- **Fedora 22** and later: ``sudo dnf builddep libinput``
|
|
||||||
- **RHEL/CentOS/Fedora 21** and earlier: ``sudo yum-builddep libinput``
|
|
||||||
- **openSUSE**: ::
|
|
||||||
|
|
||||||
$> sudo zypper modifyrepo --enable ``zypper repos | grep source | awk '{print $5}'``
|
|
||||||
$> sudo zypper source-install -d libinput10
|
|
||||||
$> sudo zypper install autoconf automake libtool
|
|
||||||
$> sudo zypper modifyrepo --disable ``zypper repos | grep source | awk '{print $5}'``
|
|
||||||
|
|
||||||
|
|
||||||
- **Arch**: ::
|
|
||||||
|
|
||||||
$> sudo pacman -S asp
|
|
||||||
$> cd $(mktemp -d)
|
|
||||||
$> asp export libinput
|
|
||||||
$> cd libinput
|
|
||||||
$> makepkg --syncdeps --nobuild --noextract
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
If dependencies are missing, meson shows a message ``No package 'foo'
|
|
||||||
found``. See
|
|
||||||
`this blog post here <https://who-t.blogspot.com/2018/07/meson-fails-with-native-dependency-not-found.html>`_
|
|
||||||
for instructions on how to fix it.
|
|
||||||
|
|
||||||
..............................................................................
|
|
||||||
Build dependencies per distribution
|
|
||||||
..............................................................................
|
|
||||||
|
|
||||||
|
|
||||||
.. include:: dependencies.rst
|
|
||||||
|
|
||||||
|
|
||||||
.. _building_conditional:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Conditional builds
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
libinput supports several meson options to disable parts of the build. See
|
|
||||||
the ``meson_options.txt`` file in the source tree for a full list of
|
|
||||||
available options. The default build enables most options and thus requires
|
|
||||||
more build dependencies. On systems where build dependencies are an issue,
|
|
||||||
options may be disabled with this meson command: ::
|
|
||||||
|
|
||||||
meson setup --prefix=/usr -Dsomefeature=false builddir
|
|
||||||
|
|
||||||
Where ``-Dsomefeature=false`` may be one of:
|
|
||||||
|
|
||||||
- ``-Ddocumentation=false``
|
|
||||||
Disables the documentation build (this website). Building the
|
|
||||||
documentation is only needed on the maintainer machine.
|
|
||||||
- ``-Dtests=false``
|
|
||||||
Disables the test suite. The test suite is only needed on developer
|
|
||||||
systems.
|
|
||||||
- ``-Ddebug-gui=false``
|
|
||||||
Disables the ``libinput debug-gui`` helper tool (see :ref:`tools`),
|
|
||||||
dropping GTK and other build dependencies. The debug-gui is only
|
|
||||||
required for troubleshooting.
|
|
||||||
- ``-Dlibwacom=false``
|
|
||||||
libwacom is required by libinput's tablet code to gather additional
|
|
||||||
information about tablets that is not available from the kernel device.
|
|
||||||
It is not recommended to disable libwacom unless libinput is used in an
|
|
||||||
environment where tablet support is not required. libinput provides tablet
|
|
||||||
support even without libwacom, but some features may be missing or working
|
|
||||||
differently.
|
|
||||||
|
|
||||||
.. _building_against:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Building against libinput
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
libinput provides a
|
|
||||||
`pkg-config <https://www.freedesktop.org/wiki/Software/pkg-config/>`_ file.
|
|
||||||
Software that uses autotools should use the ``PKG_CHECK_MODULES`` autoconf
|
|
||||||
macro: ::
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(LIBINPUT, "libinput")
|
|
||||||
|
|
||||||
Software that uses meson should use the ``dependency()`` function: ::
|
|
||||||
|
|
||||||
pkgconfig = import('pkgconfig')
|
|
||||||
dep_libinput = dependency('libinput')
|
|
||||||
|
|
||||||
Software that uses CMake should use: ::
|
|
||||||
|
|
||||||
find_package(Libinput)
|
|
||||||
target_link_libraries(myprogram PRIVATE Libinput::Libinput)
|
|
||||||
|
|
||||||
Otherwise, the most rudimentary way to compile and link a program against
|
|
||||||
libinput is:
|
|
||||||
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
gcc -o myprogram myprogram.c ``pkg-config --cflags --libs libinput``
|
|
||||||
|
|
||||||
|
|
||||||
For further information on using pkgconfig see the pkg-config documentation.
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
|
|
||||||
.. _button_debouncing:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Button debouncing
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
Physical buttons experience wear-and-tear with usage. On some devices this
|
|
||||||
can result in an effect called "contact bouncing" or "chatter". This effect
|
|
||||||
can cause the button to send multiple events within a short time frame, even
|
|
||||||
though the user only pressed or clicked the button once. This effect can be
|
|
||||||
counteracted by "debouncing" the buttons, usually by ignoring erroneous
|
|
||||||
events.
|
|
||||||
|
|
||||||
libinput provides two methods of debouncing buttons, referred to as the
|
|
||||||
"bounce" and "spurious" methods:
|
|
||||||
|
|
||||||
- In the "bounce" method, libinput monitors hardware bouncing on button
|
|
||||||
state changes, i.e. when a user clicks or releases a button. For example,
|
|
||||||
if a user presses a button but the hardware generates a
|
|
||||||
press-release-press sequence in quick succession, libinput ignores the
|
|
||||||
release and second press event. This method is always enabled.
|
|
||||||
- in the "spurious" method, libinput detects spurious releases of a button
|
|
||||||
while the button is physically held down by the user. These releases are
|
|
||||||
immediately followed by a press event. libinput monitors for these events
|
|
||||||
and ignores the release and press event. This method is disabled by
|
|
||||||
default and enables once libinput detects the first faulty event sequence.
|
|
||||||
|
|
||||||
The "bounce" method guarantees that all press events are delivered
|
|
||||||
immediately and most release events are delivered immediately. The
|
|
||||||
"spurious" method requires that release events are delayed, libinput thus
|
|
||||||
does not enable this method unless a faulty event sequence is detected. A
|
|
||||||
message is printed to the log when spurious debouncing was detected.
|
|
||||||
|
|
||||||
libinput's debouncing is supposed to correct hardware damage or
|
|
||||||
substandard hardware. Debouncing also exists as an accessibility feature
|
|
||||||
but the requirements are different. In the accessibility feature, multiple
|
|
||||||
physical key presses, usually caused by involuntary muscle movement, must be
|
|
||||||
filtered to only one key press. This feature must be implemented higher in
|
|
||||||
the stack, libinput is limited to hardware debouncing.
|
|
||||||
|
|
||||||
Below is an illustration of the button debouncing modes to show the relation
|
|
||||||
of the physical button state and the application state. Where applicable, an
|
|
||||||
extra line is added to show the timeouts used by libinput that
|
|
||||||
affect the button state handling. The waveform's high and low states
|
|
||||||
correspond to the buttons 'pressed' and 'released' states, respectively.
|
|
||||||
|
|
||||||
.. figure:: button-debouncing-wave-diagram.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
Diagram illustrating button debouncing
|
|
||||||
|
|
||||||
|
|
||||||
Some devices send events in bursts, erroneously triggering the button
|
|
||||||
debouncing detection. Please :ref:`file a bug <reporting_bugs>` if that
|
|
||||||
occurs for your device.
|
|
||||||
|
|
@ -1,144 +0,0 @@
|
||||||
.. _clickpad_softbuttons:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Clickpad software button behavior
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
"Clickpads" are touchpads without separate physical buttons. Instead, the
|
|
||||||
whole touchpad acts as a button and left or right button clicks are
|
|
||||||
distinguished by :ref:`the location of the fingers <software_buttons>` or
|
|
||||||
the :ref:`number of fingers on the touchpad <clickfinger>`.
|
|
||||||
"ClickPad" is a trademark by `Synaptics Inc. <http://www.synaptics.com/en/clickpad.php>`_
|
|
||||||
but for simplicity we refer to any touchpad with the above feature as Clickpad,
|
|
||||||
regardless of the manufacturer.
|
|
||||||
|
|
||||||
The kernel marks clickpads with the
|
|
||||||
`INPUT_PROP_BUTTONPAD <https://www.kernel.org/doc/Documentation/input/event-codes.txt>`_
|
|
||||||
property. Without this property, libinput would not know whether a touchpad
|
|
||||||
is a clickpad or not. To perform a right-click on a Clickpad, libinput
|
|
||||||
provides :ref:`software_buttons` and :ref:`clickfinger`.
|
|
||||||
|
|
||||||
.. note:: The term "click" refers refer to a physical button press
|
|
||||||
and/or release of the touchpad, the term "button event" refers to
|
|
||||||
the events generated by libinput in response to a click.
|
|
||||||
|
|
||||||
.. _software_buttons:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Software button areas
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The bottom of the touchpad is split into three distinct areas generate left,
|
|
||||||
middle or right button events on click. The height of the button area
|
|
||||||
depends on the hardware but is usually around 10mm.
|
|
||||||
|
|
||||||
.. figure :: software-buttons-visualized.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
The locations of the virtual button areas.
|
|
||||||
|
|
||||||
|
|
||||||
Left, right and middle button events can be triggered as follows:
|
|
||||||
|
|
||||||
- if a finger is in the main area or the left button area, a click generates
|
|
||||||
left button events.
|
|
||||||
- if a finger is in the right area, a click generates right button events.
|
|
||||||
- if a finger is in the middle area, a click generates middle button events.
|
|
||||||
|
|
||||||
.. figure:: software-buttons.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
Left, right and middle-button click with software button areas
|
|
||||||
|
|
||||||
The middle button is always centered on the touchpad and smaller in size
|
|
||||||
than the left or right button. The actual size is device-dependent. Many
|
|
||||||
touchpads do not have visible markings so the exact location of the button
|
|
||||||
is unfortunately not visibly obvious.
|
|
||||||
|
|
||||||
.. note:: If :ref:`middle button emulation <middle_button_emulation>` is
|
|
||||||
enabled on a clickpad, only left and right button areas are
|
|
||||||
available.
|
|
||||||
|
|
||||||
If fingers are down in the main area in addition to fingers in the
|
|
||||||
left or right button area, those fingers are are ignored.
|
|
||||||
A release event always releases the buttons logically down, regardless of
|
|
||||||
the current finger position
|
|
||||||
|
|
||||||
.. figure:: software-buttons-thumbpress.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
Only the location of the thumb determines whether it is a left, right or
|
|
||||||
middle click.
|
|
||||||
|
|
||||||
The movement of a finger can alter the button area behavior:
|
|
||||||
|
|
||||||
- if a finger starts in the main area and moves into the software button
|
|
||||||
area, the software buttons do not apply to that finger
|
|
||||||
- once a finger has moved out of the button area, it cannot move back in and
|
|
||||||
trigger a right or middle button event
|
|
||||||
- a finger moving within the software button area does not move the pointer
|
|
||||||
- once a finger moves out out of the button area it will control the
|
|
||||||
pointer (this only applies if there is no other finger down on the
|
|
||||||
touchpad)
|
|
||||||
|
|
||||||
.. figure:: software-buttons-conditions.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
**Left:** moving a finger into the right button area does not trigger a
|
|
||||||
right-button click.
|
|
||||||
**Right:** moving within the button areas does not generate pointer
|
|
||||||
motion.
|
|
||||||
|
|
||||||
On some touchpads, notably the 2015 Lenovo X1 Carbon 3rd series, the very
|
|
||||||
bottom end of the touchpad is outside of the sensor range but it is possible
|
|
||||||
to trigger a physical click there. To libinput, the click merely shows up as
|
|
||||||
a left button click without any positional finger data and it is
|
|
||||||
impossible to determine whether it is a left or a right click. libinput
|
|
||||||
ignores such button clicks, this behavior is intentional.
|
|
||||||
|
|
||||||
.. _clickfinger:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Clickfinger behavior
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
This is the default behavior on Apple touchpads. Here, a left, right, middle
|
|
||||||
button event is generated when one, two, or three fingers are held down on the
|
|
||||||
touchpad when a physical click is generated, given the default mapping. The
|
|
||||||
location of the fingers does not matter and there are no software-defined
|
|
||||||
button areas. It is possible to swap right and middle buttons, the same way as
|
|
||||||
with :ref:`tapping <tapping>`.
|
|
||||||
|
|
||||||
.. figure:: clickfinger.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
One, two and three-finger click with Clickfinger behavior
|
|
||||||
|
|
||||||
On some touchpads, libinput imposes a limit on how the fingers may be placed
|
|
||||||
on the touchpad. In the most common use-case this allows for a user to
|
|
||||||
trigger a click with the thumb while leaving the pointer-moving finger on
|
|
||||||
the touchpad.
|
|
||||||
|
|
||||||
.. figure:: clickfinger-distance.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
Illustration of the distance detection algorithm
|
|
||||||
|
|
||||||
In the illustration above the red area marks the proximity area around the
|
|
||||||
first finger. Since the thumb is outside of that area libinput considers the
|
|
||||||
click a single-finger click rather than a two-finger click.
|
|
||||||
|
|
||||||
.. _special_clickpads:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Special Clickpads
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The Lenovo \*40 series laptops have a clickpad that provides two software button sections, one at
|
|
||||||
the top and one at the bottom. See :ref:`Lenovo \*40 series touchpad support <t440_support>`
|
|
||||||
for details on the top software button.
|
|
||||||
|
|
||||||
Some Clickpads, notably some Cypress ones, perform right button detection in
|
|
||||||
firmware and appear to userspace as if the touchpad had physical buttons.
|
|
||||||
While physically clickpads, these are not handled by the software and
|
|
||||||
treated like traditional touchpads.
|
|
||||||
|
|
@ -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>`__
|
|
||||||
|
|
@ -1,193 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Configuration file for the Sphinx documentation builder.
|
|
||||||
#
|
|
||||||
# This file does only contain a selection of the most common options. For a
|
|
||||||
# full list see the documentation:
|
|
||||||
# http://www.sphinx-doc.org/en/stable/config
|
|
||||||
|
|
||||||
# -- Path setup --------------------------------------------------------------
|
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
|
||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
|
||||||
#
|
|
||||||
# sys.path.insert(0, os.path.abspath('.'))
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
sys.path.insert(0, os.path.abspath('@BUILDDIR@'))
|
|
||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
|
||||||
|
|
||||||
project = '@PROJECT_NAME@'
|
|
||||||
copyright = '2019, the libinput authors'
|
|
||||||
author = 'the libinput authors'
|
|
||||||
|
|
||||||
# The short X.Y version
|
|
||||||
version = '@PROJECT_VERSION@'
|
|
||||||
# The full version, including alpha/beta/rc tags
|
|
||||||
release = '@PROJECT_VERSION@'
|
|
||||||
|
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
|
||||||
#
|
|
||||||
# needs_sphinx = '1.0'
|
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be
|
|
||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
|
||||||
# ones.
|
|
||||||
extensions = [
|
|
||||||
'sphinx.ext.mathjax',
|
|
||||||
'sphinx.ext.graphviz',
|
|
||||||
'sphinx.ext.extlinks',
|
|
||||||
]
|
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
|
||||||
templates_path = ['_templates']
|
|
||||||
|
|
||||||
# The suffix(es) of source filenames.
|
|
||||||
# You can specify multiple suffix as a list of string:
|
|
||||||
#
|
|
||||||
# source_suffix = ['.rst', '.md']
|
|
||||||
source_suffix = '.rst'
|
|
||||||
|
|
||||||
# The master toctree document.
|
|
||||||
master_doc = 'index'
|
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
|
||||||
# for a list of supported languages.
|
|
||||||
#
|
|
||||||
# This is also used if you do content translation via gettext catalogs.
|
|
||||||
# Usually you set "language" from the command line for these cases.
|
|
||||||
language = 'en'
|
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
|
||||||
# directories to ignore when looking for source files.
|
|
||||||
# This pattern also affects html_static_path and html_extra_path .
|
|
||||||
exclude_patterns = []
|
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
|
||||||
pygments_style = 'sphinx'
|
|
||||||
|
|
||||||
highlight_language = 'none'
|
|
||||||
|
|
||||||
# -- Options for HTML output -------------------------------------------------
|
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
|
||||||
# a list of builtin themes.
|
|
||||||
#
|
|
||||||
html_theme = 'sphinx_rtd_theme'
|
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
|
||||||
# further. For a list of options available for each theme, see the
|
|
||||||
# documentation.
|
|
||||||
#
|
|
||||||
html_theme_options = {
|
|
||||||
'collapse_navigation': False,
|
|
||||||
'navigation_depth': 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
|
||||||
# html_static_path = ['_static']
|
|
||||||
|
|
||||||
# Custom sidebar templates, must be a dictionary that maps document names
|
|
||||||
# to template names.
|
|
||||||
#
|
|
||||||
# The default sidebars (for documents that don't match any pattern) are
|
|
||||||
# defined by theme itself. Builtin themes are using these templates by
|
|
||||||
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
|
|
||||||
# 'searchbox.html']``.
|
|
||||||
#
|
|
||||||
# html_sidebars = {}
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTMLHelp output ---------------------------------------------
|
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
|
||||||
htmlhelp_basename = '@PROJECT_NAME@doc'
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for LaTeX output ------------------------------------------------
|
|
||||||
|
|
||||||
latex_elements = {
|
|
||||||
# The paper size ('letterpaper' or 'a4paper').
|
|
||||||
#
|
|
||||||
# 'papersize': 'letterpaper',
|
|
||||||
|
|
||||||
# The font size ('10pt', '11pt' or '12pt').
|
|
||||||
#
|
|
||||||
# 'pointsize': '10pt',
|
|
||||||
|
|
||||||
# Additional stuff for the LaTeX preamble.
|
|
||||||
#
|
|
||||||
# 'preamble': '',
|
|
||||||
|
|
||||||
# Latex figure (float) alignment
|
|
||||||
#
|
|
||||||
# 'figure_align': 'htbp',
|
|
||||||
}
|
|
||||||
|
|
||||||
# Grouping the document tree into LaTeX files. List of tuples
|
|
||||||
# (source start file, target name, title,
|
|
||||||
# author, documentclass [howto, manual, or own class]).
|
|
||||||
latex_documents = [
|
|
||||||
(master_doc, '@PROJECT_NAME@.tex', '@PROJECT_NAME@ Documentation',
|
|
||||||
'Peter Hutterer', 'manual'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for manual page output ------------------------------------------
|
|
||||||
|
|
||||||
# One entry per manual page. List of tuples
|
|
||||||
# (source start file, name, description, authors, manual section).
|
|
||||||
man_pages = [
|
|
||||||
(master_doc, '@PROJECT_NAME@', '@PROJECT_NAME@ Documentation',
|
|
||||||
[author], 1)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for Texinfo output ----------------------------------------------
|
|
||||||
|
|
||||||
# Grouping the document tree into Texinfo files. List of tuples
|
|
||||||
# (source start file, target name, title, author,
|
|
||||||
# dir menu entry, description, category)
|
|
||||||
texinfo_documents = [
|
|
||||||
(master_doc, '@PROJECT_NAME@', '@PROJECT_NAME@ Documentation',
|
|
||||||
author, '@PROJECT_NAME@', 'One line description of project.',
|
|
||||||
'Miscellaneous'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# -- Extension configuration -------------------------------------------------
|
|
||||||
|
|
||||||
from recommonmark.parser import CommonMarkParser
|
|
||||||
|
|
||||||
extlinks = { 'commit' :
|
|
||||||
('https://gitlab.freedesktop.org/libinput/libinput/commit/%s',
|
|
||||||
'git commit %s')
|
|
||||||
}
|
|
||||||
|
|
||||||
# -- git version hack -------------------------------------------------
|
|
||||||
#
|
|
||||||
# meson doesn't take configuration_data() for vcs_tag, so we cannot replace
|
|
||||||
# two substrings in the same file.
|
|
||||||
#
|
|
||||||
# sphinx cannot do ..include:: without linebreaks, so in-line replacements
|
|
||||||
# are a no-go.
|
|
||||||
#
|
|
||||||
# Work around this by generating a mini python module in meson through
|
|
||||||
# vcs_tag, then use that to generate the replacements in rst_prolog.
|
|
||||||
|
|
||||||
import git_version
|
|
||||||
|
|
||||||
rst_prolog = """
|
|
||||||
.. |git_version| replace:: :commit:`{}`
|
|
||||||
.. |git_version_full| replace:: :commit:`{}`
|
|
||||||
|
|
||||||
""".format(git_version.get_git_version(),
|
|
||||||
git_version.get_git_version_full)
|
|
||||||
|
|
@ -1,237 +0,0 @@
|
||||||
.. _config_options:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Configuration options
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
Below is a list of configurable options exposed to the users.
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:depth: 1
|
|
||||||
:local:
|
|
||||||
|
|
||||||
|
|
||||||
.. hint:: Not all configuration options are available on all devices. Use
|
|
||||||
:ref:`libinput list-devices <libinput-list-devices>` to show the
|
|
||||||
configuration options for local devices.
|
|
||||||
|
|
||||||
libinput's configuration interface is available to the caller only, not
|
|
||||||
directly to the user. Thus it is the responsibility of the caller to expose
|
|
||||||
the various options and how these options are exposed. For example, the
|
|
||||||
`xf86-input-libinput driver <https://gitlab.freedesktop.org/xorg/driver/xf86-input-libinput/>`_
|
|
||||||
exposes the options through X Input device properties and `xorg.conf.d
|
|
||||||
<https://linux.die.net/man/5/xorg.conf.d>`_ options. See the `libinput(4)
|
|
||||||
<https://www.mankier.com/4/libinput>`_ man page for more details.
|
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Tap-to-click
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
See :ref:`tapping` for details on how this feature works. Configuration
|
|
||||||
options exposed by libinput are:
|
|
||||||
|
|
||||||
- how many tapping fingers are supported by this device
|
|
||||||
- a toggle to enable/disable tapping
|
|
||||||
- a toggle to enable/disable tap-and-drag, see :ref:`tapndrag`.
|
|
||||||
- a toggle to enable/disable tap-and-drag drag lock, see :ref:`tapndrag`
|
|
||||||
- The default order is 1, 2, 3 finger tap mapping to left, right, middle
|
|
||||||
click, respectively. This order can be changed to left, middle, right click,
|
|
||||||
respectively.
|
|
||||||
|
|
||||||
Tapping is usually available on touchpads and the touchpad part of external
|
|
||||||
graphics tablets. Tapping is usually **not** available on touch screens,
|
|
||||||
for those devices it is expected to be implemented by the toolkit.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Three-finger drag
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Three-finger drag emulates the mouse button down while three fingers
|
|
||||||
are down on a touchpad without the need to press a physical button or use
|
|
||||||
:ref:`tapndrag`. See :ref:`drag_3fg` for details on how this feature works.
|
|
||||||
|
|
||||||
Three-finger drag is usually available on touchpads and the touchpad part of
|
|
||||||
external graphics tablets. Three-finger drag is usually **not** available on
|
|
||||||
touch screens, for those devices it is expected to be implemented by the
|
|
||||||
toolkit.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Send Events Mode
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The Send Events Mode is libinput's terminology for disabling a device. It is
|
|
||||||
more precise in that the device only stops sending events but may not get
|
|
||||||
fully disabled. For example, disabling the touchpad on a
|
|
||||||
:ref:`Lenovo T440 and similar <t440_support>` leaves the top software
|
|
||||||
buttons enabled for the trackpoint. Available options are
|
|
||||||
**enabled** (send events normally), **disabled** ( do not send events),
|
|
||||||
**disabled on external mouse** (disable the device while an external mouse
|
|
||||||
is plugged in).
|
|
||||||
|
|
||||||
|
|
||||||
.. _config_pointer_acceleration:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Pointer acceleration
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Pointer acceleration is a function to convert input deltas to output deltas,
|
|
||||||
usually based on the movement speed of the device, see
|
|
||||||
:ref:`pointer-acceleration` for details.
|
|
||||||
|
|
||||||
Pointer acceleration is normalized into a [-1, 1] range, where -1 is
|
|
||||||
"slowest" and 1 is "fastest". Most devices use a default speed of 0.
|
|
||||||
|
|
||||||
The pointer acceleration profile defines **how** the input deltas are
|
|
||||||
converted, see :ref:`ptraccel-profiles`. Most devices have their default
|
|
||||||
profile (usually called "adaptive") and a "flat" profile. The flat profile
|
|
||||||
does not apply any acceleration.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Scrolling
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
"Natural scrolling" is the terminology for moving the content in the
|
|
||||||
direction of scrolling, i.e. moving the wheel or fingers down moves the page
|
|
||||||
down. Traditional scrolling moves the content in the opposite direction.
|
|
||||||
Natural scrolling can be turned on or off, it is usually off by default.
|
|
||||||
|
|
||||||
The scroll method defines how to trigger scroll events. On touchpads
|
|
||||||
libinput provides two-finger scrolling and edge scrolling. Two-finger
|
|
||||||
scrolling converts a movement with two fingers to a series of scroll events.
|
|
||||||
Edge scrolling converts a movement with one finger along the right or bottom
|
|
||||||
edge of the touchpad into a series of scroll events.
|
|
||||||
|
|
||||||
On other libinput provides button-scrolling - movement of the device while
|
|
||||||
the designated scroll button is down is converted to scroll events. The
|
|
||||||
button used for scrolling is configurable.
|
|
||||||
|
|
||||||
The scroll method can be chosen or disabled altogether but most devices only
|
|
||||||
support a subset of available scroll methods. libinput's default is
|
|
||||||
two-finger scrolling for multi-touch touchpads, edge scrolling for
|
|
||||||
single-touch touchpads. On tracksticks, button scrolling is enabled by
|
|
||||||
default.
|
|
||||||
|
|
||||||
See :ref:`scrolling` for more details on how the scroll methods work.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Left-handed Mode
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Left-handed mode switches the device's functionality to be more
|
|
||||||
accommodating for left-handed users. On mice this usually means swapping the
|
|
||||||
left and right mouse button, on tablets this allows the tablet to be used
|
|
||||||
upside-down to present the pad buttons for the non-dominant right hand. Not
|
|
||||||
all devices have left-handed mode.
|
|
||||||
|
|
||||||
Left-handed mode can be enabled or disabled and is disabled by default.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Middle Button Emulation
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Middle button emulation converts a simultaneous left and right button click
|
|
||||||
into a middle button. The emulation can be enabled or disabled. Middle
|
|
||||||
button emulation is usually enabled when the device does not provide a
|
|
||||||
middle button.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Click method
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The click method defines how button events are triggered on a :ref:`clickpad
|
|
||||||
<clickpad_softbuttons>`. When set to button areas, the bottom area of the
|
|
||||||
touchpad is divided into a left, middle and right button area. When set to
|
|
||||||
clickfinger, the number of fingers on the touchpad decide the button type.
|
|
||||||
Clicking with 1, 2, 3 fingers triggers a left, right, or middle click,
|
|
||||||
respectively. The default click method is software button areas. Click
|
|
||||||
methods are usually only available on :ref:`clickpads
|
|
||||||
<clickpad_softbuttons>`.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Disable while typing
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
DWT is the most generic form of palm detection on touchpad. While the user
|
|
||||||
is typing on an internal keyboard the touchpad is disabled, the touchpad
|
|
||||||
is enabled again after a timeout. See :ref:`disable-while-typing` for more
|
|
||||||
info.
|
|
||||||
|
|
||||||
Disable-while-typing can be enabled or disabled, it is enabled by default on
|
|
||||||
most touchpads.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Disable while trackpointing
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
DWTP is a form of palm 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 is available for some direct-input devices (touch screens,
|
|
||||||
graphics tablets, etc.). The purpose of calibration is to ensure the input
|
|
||||||
lines up with the output and the configuration data is a transformation
|
|
||||||
matrix. It is thus not expected that the user sets this option. The desktop
|
|
||||||
environment should provide an interface for this.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Rotation
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The device rotation applies a corrective angle to relative input events,
|
|
||||||
allowing the device to be used e.g. sideways or upside-down. For example, a
|
|
||||||
trackball may be used in a 90° rotated position for accessibility reasons -
|
|
||||||
such a rotated position allows triggering the buttons with the thumb or
|
|
||||||
the non-dominant hand.
|
|
||||||
|
|
||||||
Note that where a device rotation is higher than 160 but less than 200 degrees,
|
|
||||||
the direction of wheels is also inverted. For all other angles, the wheel
|
|
||||||
direction is left as-is.
|
|
||||||
|
|
||||||
.. _config-tablet-pressure-range:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Tablet tool pressure range
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The pressure range on a :ref:`Tablet tool <tablet-tools>` can be reduced
|
|
||||||
from the full available hardware range to a subset of that range. The effect
|
|
||||||
of this is that the tablet will not register pressure below the given
|
|
||||||
the given threshold is met, and will reach the maximum logical pressure
|
|
||||||
before the maximum hardware-supported pressure is reached.
|
|
||||||
|
|
||||||
See :ref:`tablet-pressure-range` for more info.
|
|
||||||
|
|
||||||
.. _config-tablet-eraser-buttons:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Tablet tool eraser buttons
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
On many contemporary :ref:`Tablet tools <tablet-tools>` one button is hardcoded
|
|
||||||
in firmware to emulate an eraser. This button can be remapped to provide
|
|
||||||
a normal stylus button instead.
|
|
||||||
|
|
||||||
See :ref:`tablet-eraser-button` for more info.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Area configuration
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Area configuration is available for some indirect input devices such as
|
|
||||||
graphics tablets. This configuration allows reducing the active area of
|
|
||||||
such a device to a subset of the physically possible area.
|
|
||||||
|
|
||||||
An example use-case for this is to match the aspect ratio of the device to that
|
|
||||||
of the screen.
|
|
||||||
|
|
||||||
See :ref:`tablet-area` for more info.
|
|
||||||
|
|
@ -1,421 +0,0 @@
|
||||||
|
|
||||||
.. _contributing:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Contributing to libinput
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
So you want to contribute to libinput? Great! We'd love to help you be a part
|
|
||||||
of our community. Here is some important information to help you.
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:local:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Code of Conduct
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
As a freedesktop.org project, libinput follows the `freedesktop.org
|
|
||||||
Contributor Covenant <https://www.freedesktop.org/wiki/CodeOfConduct>`_.
|
|
||||||
|
|
||||||
Please conduct yourself in a respectful and civilised manner when
|
|
||||||
interacting with community members on mailing lists, IRC, or bug trackers.
|
|
||||||
The community represents the project as a whole, and abusive or bullying
|
|
||||||
behaviour is not tolerated by the project.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Contact
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Questions can be asked on ``#wayland`` on oftc or on the
|
|
||||||
`wayland-devel@lists.freedesktop.org
|
|
||||||
<https://lists.freedesktop.org/mailman/listinfo/wayland-devel>`_ mailing
|
|
||||||
list.
|
|
||||||
|
|
||||||
For IRC, ping user ``whot`` (Peter Hutterer, the libinput maintainer) though
|
|
||||||
note that he lives on UTC+10 and thus the rest of the world is out of sync
|
|
||||||
by default ;)
|
|
||||||
|
|
||||||
For anything that appears to be device specific and/or related to a new
|
|
||||||
feature, just file `an issue in our issue tracker
|
|
||||||
<https://gitlab.freedesktop.org/libinput/libinput/issues>`_. It's usually the
|
|
||||||
most efficient way to get answers.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
What to work on?
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
If you don't already know what you want to improve or fix with libinput,
|
|
||||||
then a good way of finding something is to search for the ``help needed``
|
|
||||||
tag in our `issue tracker <https://gitlab.freedesktop.org/libinput/libinput/issues?label_name%5B%5D=help+needed>`_.
|
|
||||||
These are issues that have been triaged to some degree and deemed to be a
|
|
||||||
possible future feature to libinput.
|
|
||||||
|
|
||||||
.. note:: Some of these issue may require specific hardware to reproduce.
|
|
||||||
|
|
||||||
Another good place to help out with is the documentation. For anything you
|
|
||||||
find in these pages that isn't clear enough please feel free to reword it
|
|
||||||
and add what is missing.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Getting the code
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The :ref:`building_libinput` have all the details but the short solution
|
|
||||||
will be:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$> git clone https://gitlab.freedesktop.org/libinput/libinput
|
|
||||||
$> cd libinput
|
|
||||||
$> meson setup --prefix=/usr builddir/
|
|
||||||
$> ninja -C builddir/
|
|
||||||
$> sudo ninja -C builddir/ install
|
|
||||||
|
|
||||||
You can omit the last step if you only want to test locally.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Working on the code
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
If you are planning to send patches, it's a good idea to set up
|
|
||||||
`pre-commit <https://pre-commit.com/>`_ with these commands::
|
|
||||||
|
|
||||||
$> pre-commit install
|
|
||||||
$> pre-commit install --hook-type pre-push
|
|
||||||
|
|
||||||
This will check a few things before you commit and/or push to your repos to
|
|
||||||
reduce the turnaround time for some common mistakes.
|
|
||||||
|
|
||||||
libinput has a roughly three-parts architecture:
|
|
||||||
|
|
||||||
- the front-end code which handles the ``libinput_some_function()`` API calls in ``libinput.c``
|
|
||||||
- the generic evdev interface handling which maps those API calls to the
|
|
||||||
backend calls (``evdev.c``).
|
|
||||||
- there are device-specific backends which do most of the actual work -
|
|
||||||
``evdev-mt-touchpad.c`` is the one for touchpads for example.
|
|
||||||
|
|
||||||
In general, things that only affect the internal workings of a device only
|
|
||||||
get implemented in the device-specific backend. You only need to touch the
|
|
||||||
API when you are adding configuration options. For more details, please read
|
|
||||||
the :ref:`architecture` document. There's also a `blog post describing the
|
|
||||||
building blocks
|
|
||||||
<https://who-t.blogspot.com/2019/03/libinputs-internal-building-blocks.html>`_
|
|
||||||
that may help to understand how it all fits together.
|
|
||||||
|
|
||||||
Documentation is in ``/doc/api`` for the doxygen-generated API documentation.
|
|
||||||
These are extracted from the libinput source code directly. The
|
|
||||||
documentation you're reading right now is in ``/doc/user`` and generated with
|
|
||||||
sphinx. Simply running ``ninja -C builddir`` will rebuild it and the final
|
|
||||||
product ends up in ``builddir/Documentation``.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Testing the code
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
libinput provides a bunch of :ref:`tools` to debug any changes - without
|
|
||||||
having to install libinput.
|
|
||||||
|
|
||||||
The two most useful ones are :ref:`libinput debug-events
|
|
||||||
<libinput-debug-events>` and :ref:`libinput debug-gui <libinput-debug-gui>`.
|
|
||||||
Both tools can be run from the build directory directly and are great for
|
|
||||||
quick test iterations::
|
|
||||||
|
|
||||||
$> sudo ./builddir/libinput-debug-events --verbose
|
|
||||||
$> sudo ./builddir/libinput-debug-gui --verbose
|
|
||||||
|
|
||||||
The former provides purely textual output and is useful for verifying event
|
|
||||||
streams from buttons, etc. The latter is particularly useful when you are
|
|
||||||
trying to debug pointer movement or placement. ``libinput debug-gui`` will
|
|
||||||
also visualize the raw data from the device so you can compare pointer
|
|
||||||
behavior with what comes from the kernel.
|
|
||||||
|
|
||||||
These tools create a new libinput context and will not affect your session's
|
|
||||||
behavior. Only once you've installed libinput and restarted your session
|
|
||||||
will your changes affect the X server/Wayland compositor.
|
|
||||||
|
|
||||||
Once everything seems to be correct, it's time to run the
|
|
||||||
:ref:`test-suite`::
|
|
||||||
|
|
||||||
$> sudo ./builddir/libinput-test-suite
|
|
||||||
|
|
||||||
This test suite can take test names etc. as arguments, have a look at
|
|
||||||
:ref:`test-suite` for more info. There are a bunch of other tests that are
|
|
||||||
run by the CI on merge requests, you can run those locally with ::
|
|
||||||
|
|
||||||
$> sudo ninja -C builddir check
|
|
||||||
|
|
||||||
So it always pays to run that before submitting. This will also run the code
|
|
||||||
through valgrind and pick up any memory leaks.
|
|
||||||
|
|
||||||
.. _contributing_submitting_code:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Submitting Code
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Any patches should be sent via a Merge Request (see the `GitLab docs
|
|
||||||
<https://docs.gitlab.com/ce/gitlab-basics/add-merge-request.htm>`_)
|
|
||||||
in the `libinput GitLab instance hosted by freedesktop.org
|
|
||||||
<https://gitlab.freedesktop.org/libinput/libinput>`_.
|
|
||||||
|
|
||||||
.. note:: freedesktop.org's GitLab instance has restrictions to prevent Spam
|
|
||||||
and you cannot fork libinput until you have successfully
|
|
||||||
`applied for fork permissions <https://gitlab.freedesktop.org/freedesktop/freedesktop/-/wikis/home>`_.
|
|
||||||
|
|
||||||
Below are the steps required to submit a merge request. They do not
|
|
||||||
replace `learning git <https://git-scm.com/doc>`__ but they should be
|
|
||||||
sufficient to make some of the more confusing steps obvious.
|
|
||||||
|
|
||||||
- `Register an account <https://gitlab.freedesktop.org/users/sign_in>`_ in
|
|
||||||
the freedesktop.org GitLab instance and
|
|
||||||
`apply for fork permissions <https://gitlab.freedesktop.org/freedesktop/freedesktop/-/wikis/home>`_.
|
|
||||||
- `Fork libinput <https://gitlab.freedesktop.org/libinput/libinput/-/forks/new>`_
|
|
||||||
into your username's namespace. Select public visibility.
|
|
||||||
- Get libinput's main repository. git will call this repository ``origin``. ::
|
|
||||||
|
|
||||||
git clone https://gitlab.freedesktop.org/libinput/libinput.git
|
|
||||||
|
|
||||||
- Add the forked git repository to your remotes (replace ``USERNAME``
|
|
||||||
with your username). git will call this repository ``gitlab``. ::
|
|
||||||
|
|
||||||
cd /path/to/libinput.git
|
|
||||||
git remote add gitlab git@ssh.gitlab.freedesktop.org:USERNAME/libinput.git
|
|
||||||
git fetch gitlab
|
|
||||||
|
|
||||||
- Create a new branch and commit your changes to that branch. ::
|
|
||||||
|
|
||||||
git switch -C mynewbranch
|
|
||||||
# edit files, make changes
|
|
||||||
git add file1 file2
|
|
||||||
git commit -s
|
|
||||||
# edit commit message in the editor
|
|
||||||
|
|
||||||
Replace ``mynewbranch`` (here and in the commands below) with a meaningful
|
|
||||||
name. See :ref:`contributing_commit_messages` for details on the commit
|
|
||||||
message format.
|
|
||||||
|
|
||||||
- Push your changes to your fork and submit a merge request ::
|
|
||||||
|
|
||||||
git push gitlab mynewbranch
|
|
||||||
|
|
||||||
This command will print the URL to file a merge request, you then only
|
|
||||||
have to click through. Alternatively you can go to:
|
|
||||||
|
|
||||||
https://gitlab.freedesktop.org/USERNAME/libinput/merge_requests
|
|
||||||
|
|
||||||
Select your branch name to merge and ``libinput/libinput`` ``main`` as target branch.
|
|
||||||
|
|
||||||
- Verify that the CI completes successfully by visiting the merge request
|
|
||||||
page. A successful pipeline shows only green ticks, failure is indicated
|
|
||||||
by a red cross or a yellow exclamation mark (see
|
|
||||||
the `GitLab Docs
|
|
||||||
<https://docs.gitlab.com/ee/ci/pipelines/#pipeline-mini-graphs>`__). For
|
|
||||||
details about the failures, click on the failed jobs in the pipelines
|
|
||||||
and/or click the ``Expand`` button in the box for the test summaries.
|
|
||||||
|
|
||||||
A merge request without a successful pipeline may never be looked at by a
|
|
||||||
maintainer.
|
|
||||||
|
|
||||||
- If changes are requested by the maintainers, please **amend** the
|
|
||||||
commit(s) and **force-push** the updated branch. ::
|
|
||||||
|
|
||||||
# edits in file foo.c
|
|
||||||
git add foo.c
|
|
||||||
git commit --amend
|
|
||||||
git push -f gitlab mynewbranch
|
|
||||||
|
|
||||||
A force-push will re-trigger the CI and notify the merge request that new
|
|
||||||
changes are available.
|
|
||||||
|
|
||||||
If the branch contains more than one commit, please look at
|
|
||||||
`git interactive rebases
|
|
||||||
<https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History>`__
|
|
||||||
to learn how to change multiple commits, or squash new changes into older
|
|
||||||
commits.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Commit History
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
libinput strives to have a
|
|
||||||
`linear, 'recipe' style history <http://www.bitsnbites.eu/git-history-work-log-vs-recipe/>`_
|
|
||||||
This means that every commit should be small, digestible, stand-alone, and
|
|
||||||
functional. Rather than a purely chronological commit history like this: ::
|
|
||||||
|
|
||||||
doc: final docs for view transforms
|
|
||||||
fix tests when disabled, redo broken doc formatting
|
|
||||||
better transformed-view iteration (thanks Hannah!)
|
|
||||||
try to catch more cases in tests
|
|
||||||
tests: add new spline test
|
|
||||||
fix compilation on splines
|
|
||||||
doc: notes on reticulating splines
|
|
||||||
compositor: add spline reticulation for view transforms
|
|
||||||
|
|
||||||
We aim to have a clean history which only reflects the final state, broken up
|
|
||||||
into functional groupings: ::
|
|
||||||
|
|
||||||
compositor: add spline reticulation for view transforms
|
|
||||||
compositor: new iterator for view transforms
|
|
||||||
tests: add view-transform correctness tests
|
|
||||||
doc: fix Doxygen formatting for view transforms
|
|
||||||
|
|
||||||
This ensures that the final patch series only contains the final state,
|
|
||||||
without the changes and missteps taken along the development process.
|
|
||||||
|
|
||||||
The first line of a commit message should contain a prefix indicating
|
|
||||||
what part is affected by the patch followed by one sentence that
|
|
||||||
describes the change. For example: ::
|
|
||||||
|
|
||||||
touchpad: add software button behavior
|
|
||||||
fallback: disable button debouncing on device foo
|
|
||||||
|
|
||||||
If in doubt what prefix to use, look at other commits that change the
|
|
||||||
same file(s) as the patch being sent.
|
|
||||||
|
|
||||||
.. _contributing_commit_messages:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Commit Messages
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
When you re-send patches, revised or not, it would be very good to document the
|
|
||||||
changes compared to the previous revision in the commit message and/or the
|
|
||||||
merge request. If you have already received Reviewed-by or Acked-by tags, you
|
|
||||||
should evaluate whether they still apply and include them in the respective
|
|
||||||
commit messages. Otherwise the tags may be lost, reviewers miss the credit they
|
|
||||||
deserve, and the patches may cause redundant review effort.
|
|
||||||
|
|
||||||
If your commit solves a GitLab issue, add a ``Closes:`` tag followed by the
|
|
||||||
issue number at the end of your commit message. For example: ::
|
|
||||||
|
|
||||||
Closes: #974
|
|
||||||
|
|
||||||
If your commit fixes an issue introduced by another commit, use a ``Fixes`` tag
|
|
||||||
followed by the first 12 characters of the SHA-1 ID and the commit one line
|
|
||||||
summary at the end of your commit message. For example: ::
|
|
||||||
|
|
||||||
Fixes: 123456789012 ("The commit that caused the issue")
|
|
||||||
|
|
||||||
For further reading, please see
|
|
||||||
`'on commit messages' <http://who-t.blogspot.de/2009/12/on-commit-messages.html>`_
|
|
||||||
as a general guideline on what commit messages should contain.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Coding Style
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Please see the `CODING_STYLE.md
|
|
||||||
<https://gitlab.freedesktop.org/libinput/libinput/blob/main/CODING_STYLE.md>`_
|
|
||||||
document in the source tree.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Tracking patches and follow-ups
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Once submitted to GitLab, your patches will be reviewed by the libinput
|
|
||||||
development team on GitLab. Review may be entirely positive and result in your
|
|
||||||
code landing instantly, in which case, great! You're done. However, we may ask
|
|
||||||
you to make some revisions: fixing some bugs we've noticed, working to a
|
|
||||||
slightly different design, or adding documentation and tests.
|
|
||||||
|
|
||||||
If you do get asked to revise the patches, please bear in mind the notes above.
|
|
||||||
You should use ``git rebase -i`` to make revisions, so that your patches
|
|
||||||
follow the clear linear split documented above. Following that split makes
|
|
||||||
it easier for reviewers to understand your work, and to verify that the code
|
|
||||||
you're submitting is correct.
|
|
||||||
|
|
||||||
A common request is to split single large patch into multiple patches. This can
|
|
||||||
happen, for example, if when adding a new feature you notice a bug in
|
|
||||||
libinput's core which you need to fix to progress. Separating these changes
|
|
||||||
into separate commits will allow us to verify and land the bugfix quickly,
|
|
||||||
pushing part of your work for the good of everyone, whilst revision and
|
|
||||||
discussion continues on the larger feature part. It also allows us to direct
|
|
||||||
you towards reviewers who best understand the different areas you are
|
|
||||||
working on.
|
|
||||||
|
|
||||||
When you have made any requested changes, please rebase the commits, verify
|
|
||||||
that they still individually look good, then force-push your new branch to
|
|
||||||
GitLab. This will update the merge request and notify everyone subscribed to
|
|
||||||
your merge request, so they can review it again.
|
|
||||||
|
|
||||||
There are also many GitLab CLI clients, if you prefer to avoid the web
|
|
||||||
interface. It may be difficult to follow review comments without using the
|
|
||||||
web interface though, so we do recommend using this to go through the review
|
|
||||||
process, even if you use other clients to track the list of available
|
|
||||||
patches.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Failed pipeline errors
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
After submitting your merge request to GitLab, you might receive an email
|
|
||||||
informing you that your pipeline failed.
|
|
||||||
|
|
||||||
Visit your merge request page and check the `pipeline mini graph
|
|
||||||
<https://docs.gitlab.com/ee/ci/pipelines/#pipeline-mini-graphs>`_ to know which
|
|
||||||
step failed.
|
|
||||||
|
|
||||||
Follow the appropriate section to fix the errors.
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
Committed gitlab-ci.yml differs from generated gitlab-ci.yml. Please verify
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
When your merge request modifies the CI templates, you might see this error
|
|
||||||
mainly due two reasons: the wrong file was modified and/or
|
|
||||||
``ci-fairy generate-template`` wasn't run.
|
|
||||||
|
|
||||||
``.gitlab-ci.yaml`` is auto generated, changes should be made in:
|
|
||||||
|
|
||||||
- ``.gitlab-ci/ci.template``
|
|
||||||
|
|
||||||
- ``.gitlab-ci/config.yaml``
|
|
||||||
|
|
||||||
Once the changes are ready, run
|
|
||||||
`ci-fairy <https://freedesktop.pages.freedesktop.org/ci-templates/ci-fairy.html#templating-gitlab-ci-yml>`_
|
|
||||||
to update ``.gitlab-ci.yaml``: ::
|
|
||||||
|
|
||||||
ci-fairy generate-template
|
|
||||||
|
|
||||||
Finally, force-push you changes. See :ref:`contributing_submitting_code` for
|
|
||||||
more details.
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
Build errors
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Usually, checking the CI log is enough to catch this errors. However, your merge
|
|
||||||
request is built using different configurations you might have not tested.
|
|
||||||
|
|
||||||
In order to fix this kind of problems, you can compile libinput using the same
|
|
||||||
flags used by the CI.
|
|
||||||
|
|
||||||
For example, if an error is found in the ``build-no-libwacom`` step, open the
|
|
||||||
log and search the build options: ::
|
|
||||||
|
|
||||||
[...]
|
|
||||||
+ rm -rf 'build dir'
|
|
||||||
+ meson 'build dir' -Dlibwacom=false
|
|
||||||
The Meson build system
|
|
||||||
[...]
|
|
||||||
|
|
||||||
Use the same flags to fix the issue and force-push you changes. See
|
|
||||||
:ref:`contributing_submitting_code` for more details.
|
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
Test errors
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The test suite is run for your merge request to check for bugs, regressions and
|
|
||||||
memory leaks among other issues.
|
|
||||||
|
|
||||||
Open the CI error log and search for a message similar to: ::
|
|
||||||
|
|
||||||
:: Failure: ../test/test-touchpad.c:465: touchpad_2fg_scroll_slow_distance(synaptics-t440)
|
|
||||||
|
|
||||||
See :ref:`test-suite` to learn how to run the failing tests.
|
|
||||||
|
|
||||||
Once the tests are fixed, force-push you changes. See
|
|
||||||
:ref:`contributing_submitting_code` for more details.
|
|
||||||
|
|
@ -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@
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
.. _development:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Information for developers
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
Below is a list of topics of interest to developers, divided into
|
|
||||||
information for those :ref:`using_libinput_as_library` in a Wayland compositor
|
|
||||||
or other project. The :ref:`hacking_on_libinput` section applies to developers working on
|
|
||||||
libinput itself.
|
|
||||||
|
|
||||||
.. note:: If you use or work on libinput you should get in touch with the
|
|
||||||
libinput developers on the wayland-devel@lists.freedesktop.org
|
|
||||||
mailing lists
|
|
||||||
|
|
||||||
.. _using_libinput_as_library:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Using libinput as library
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
See :ref:`building_against` for information on how to integrate libinput
|
|
||||||
with your project's build system.
|
|
||||||
|
|
||||||
.. note:: **libinput's API documentation is available here:**
|
|
||||||
http://wayland.freedesktop.org/libinput/doc/latest/api/
|
|
||||||
|
|
||||||
|
|
||||||
Topics below explain some behaviors of libinput.
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 1
|
|
||||||
|
|
||||||
absolute-axes.rst
|
|
||||||
absolute-coordinate-ranges.rst
|
|
||||||
normalization-of-relative-motion.rst
|
|
||||||
seats.rst
|
|
||||||
timestamps.rst
|
|
||||||
wheel-api.rst
|
|
||||||
|
|
||||||
.. _hacking_on_libinput:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Hacking on libinput
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 1
|
|
||||||
|
|
||||||
architecture
|
|
||||||
test-suite.rst
|
|
||||||
pointer-acceleration.rst
|
|
||||||
device-configuration-via-udev.rst
|
|
||||||
|
|
@ -1,245 +0,0 @@
|
||||||
.. _udev_config:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Static device configuration via udev
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
libinput supports some static configuration through udev properties.
|
|
||||||
These properties are read when the device is initially added
|
|
||||||
to libinput's device list, i.e. before the
|
|
||||||
**LIBINPUT_EVENT_DEVICE_ADDED** event is generated.
|
|
||||||
|
|
||||||
The following udev properties are supported:
|
|
||||||
|
|
||||||
LIBINPUT_CALIBRATION_MATRIX
|
|
||||||
Sets the calibration matrix, see
|
|
||||||
**libinput_device_config_calibration_get_default_matrix()**. If unset,
|
|
||||||
defaults to the identity matrix.
|
|
||||||
|
|
||||||
The udev property is parsed as 6 floating point numbers separated by a
|
|
||||||
single space each (scanf(3) format ``"%f %f %f %f %f %f"``).
|
|
||||||
The 6 values represent the first two rows of the calibration matrix as
|
|
||||||
described in **libinput_device_config_calibration_set_matrix()**.
|
|
||||||
|
|
||||||
Example values are: ::
|
|
||||||
|
|
||||||
ENV{LIBINPUT_CALIBRATION_MATRIX}="1 0 0 0 1 0" # default
|
|
||||||
ENV{LIBINPUT_CALIBRATION_MATRIX}="0 -1 1 1 0 0" # 90 degree clockwise
|
|
||||||
ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 0 -1 1" # 180 degree clockwise
|
|
||||||
ENV{LIBINPUT_CALIBRATION_MATRIX}="0 1 0 -1 0 1" # 270 degree clockwise
|
|
||||||
ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 0 1 0" # reflect along y axis
|
|
||||||
|
|
||||||
|
|
||||||
LIBINPUT_DEVICE_GROUP
|
|
||||||
A string identifying the **libinput_device_group** for this device. Two
|
|
||||||
devices with the same property value are grouped into the same device group,
|
|
||||||
the value itself is irrelevant otherwise.
|
|
||||||
|
|
||||||
LIBINPUT_IGNORE_DEVICE
|
|
||||||
If set to anything other than "0", the device is ignored by libinput.
|
|
||||||
See :ref:`ignoring_devices` for more details.
|
|
||||||
|
|
||||||
ID_SEAT
|
|
||||||
Assigns the physical :ref:`seat <seats>` for this device. See
|
|
||||||
**libinput_seat_get_physical_name()**. Defaults to "seat0".
|
|
||||||
|
|
||||||
ID_INPUT
|
|
||||||
If this property is set, the device is considered an input device. Any
|
|
||||||
device with this property missing will be ignored, see :ref:`udev_device_type`.
|
|
||||||
|
|
||||||
ID_INPUT_KEYBOARD, ID_INPUT_KEY, ID_INPUT_MOUSE, ID_INPUT_TOUCHPAD, ID_INPUT_TOUCHSCREEN, ID_INPUT_TABLET, ID_INPUT_JOYSTICK, ID_INPUT_ACCELEROMETER
|
|
||||||
If any of the above is set, libinput initializes the device as the given
|
|
||||||
type, see :ref:`udev_device_type`. Note that for historical reasons more than
|
|
||||||
one of these may be set at any time, libinput will select only one of these
|
|
||||||
to determine the device type. To ensure libinput selects the correct device
|
|
||||||
type, only set one of them.
|
|
||||||
|
|
||||||
WL_SEAT
|
|
||||||
Assigns the logical :ref:`seat <seats>` for this device. See
|
|
||||||
**libinput_seat_get_logical_name()** context. Defaults to "default".
|
|
||||||
|
|
||||||
MOUSE_DPI
|
|
||||||
HW resolution and sampling frequency of a relative pointer device.
|
|
||||||
See :ref:`motion_normalization` for details.
|
|
||||||
|
|
||||||
MOUSE_WHEEL_CLICK_ANGLE
|
|
||||||
The angle in degrees for each click on a mouse wheel. See
|
|
||||||
**libinput_pointer_get_axis_source()** for details.
|
|
||||||
|
|
||||||
|
|
||||||
Below is an example udev rule to assign "seat1" to a device from vendor
|
|
||||||
``0x012a`` with the model ID of ``0x034b``. ::
|
|
||||||
|
|
||||||
$ cat /etc/udev/rules.d/99-my-device-is-on-seat1.rules
|
|
||||||
ACTION!="remove", KERNEL=="event[0-9]*", \
|
|
||||||
ENV{ID_VENDOR_ID}=="012a", \
|
|
||||||
ENV{ID_MODEL_ID}=="034b", \
|
|
||||||
ENV{ID_SEAT}="seat1"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _udev_device_type:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Device type assignment via udev
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
libinput requires the **ID_INPUT** property to be set on a device,
|
|
||||||
otherwise the device will be ignored. In addition, one of
|
|
||||||
**ID_INPUT_KEYBOARD, ID_INPUT_KEY, ID_INPUT_MOUSE, ID_INPUT_TOUCHPAD,
|
|
||||||
ID_INPUT_TOUCHSCREEN, ID_INPUT_TABLET, ID_INPUT_JOYSTICK,
|
|
||||||
ID_INPUT_ACCELEROMETER** must be set on the device to determine the
|
|
||||||
device type. The usual error handling applies within libinput and a device
|
|
||||||
type label does not guarantee that the device is initialized by libinput.
|
|
||||||
If a device fails to meet the requirements for a device type (e.g. a keyboard
|
|
||||||
labelled as touchpad) the device will not be available through libinput.
|
|
||||||
|
|
||||||
Only one device type should be set per device at a type, though libinput can
|
|
||||||
handle some combinations for historical reasons.
|
|
||||||
|
|
||||||
Below is an example udev rule to remove an **ID_INPUT_TOUCHPAD** setting
|
|
||||||
and change it into an **ID_INPUT_TABLET** setting. This rule would apply
|
|
||||||
for a device with the vendor/model ID of ``012a``/``034b``. ::
|
|
||||||
|
|
||||||
$ cat /etc/udev/rules.d/99-my-device-is-a-tablet.rules
|
|
||||||
ACTION!="remove", KERNEL=="event[0-9]*", \
|
|
||||||
ENV{ID_VENDOR_ID}=="012a", \
|
|
||||||
ENV{ID_MODEL_ID}=="034b", \
|
|
||||||
ENV{ID_INPUT_TOUCHPAD}="", ENV{ID_INPUT_TABLET}="1"
|
|
||||||
|
|
||||||
|
|
||||||
.. _model_specific_configuration:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Model-specific configuration
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
As of libinput 1.12, model-specific configuration is stored in the
|
|
||||||
:ref:`device-quirks` and not in the hwdb anymore. Please see
|
|
||||||
:ref:`device-quirks` for
|
|
||||||
details.
|
|
||||||
|
|
||||||
.. _model_specific_configuration_x220fw81:
|
|
||||||
|
|
||||||
..............................................................................
|
|
||||||
Lenovo x220 with touchpad firmware v8.1
|
|
||||||
..............................................................................
|
|
||||||
|
|
||||||
The property **LIBINPUT_MODEL_LENOVO_X220_TOUCHPAD_FW81** may be set by a
|
|
||||||
user in a local hwdb file. This property designates the touchpad on a Lenovo
|
|
||||||
x220 with a touchpad firmware version 8.1. When this firmware version is
|
|
||||||
installed, the touchpad is imprecise. The touchpad device does not send
|
|
||||||
continuous x/y axis position updates, a behavior also observed on its
|
|
||||||
successor model, the Lenovo x230 which has the same firmware version. If the
|
|
||||||
above property is set, libinput adjusts its behavior to better suit this
|
|
||||||
particular model.
|
|
||||||
|
|
||||||
The touchpad firmware version cannot be detected automatically by libinput,
|
|
||||||
local configuration is required to set this property. Refer to the libinput
|
|
||||||
model quirks hwdb for instructions.
|
|
||||||
|
|
||||||
This property must not be used for any other purpose, no specific behavior
|
|
||||||
is guaranteed.
|
|
||||||
|
|
||||||
|
|
||||||
.. _hwdb:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Configuring the hwdb
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
This section outlines how to query the
|
|
||||||
`udev hwdb <https://www.freedesktop.org/software/systemd/man/hwdb.html>`_
|
|
||||||
and reload properties so they are available to libinput.
|
|
||||||
|
|
||||||
The hwdb contains a set of match rules that assign udev properties that are
|
|
||||||
available to libinput when the device is connected and/or libinput is
|
|
||||||
initialized. This section only describes the hwdb in relation to libinput,
|
|
||||||
it is not a full documentation on how the hwdb works.
|
|
||||||
|
|
||||||
libinput's use of the hwdb is limited to properties systemd and custom
|
|
||||||
rules files (where available) provide. Hardware-specific quirks as used by
|
|
||||||
libinput are in the :ref:`device-quirks` system.
|
|
||||||
|
|
||||||
.. _hwdb_querying:
|
|
||||||
|
|
||||||
..............................................................................
|
|
||||||
Querying the hwdb
|
|
||||||
..............................................................................
|
|
||||||
|
|
||||||
libinput only uses device nodes in the form of ``/dev/input/eventX`` where X
|
|
||||||
is the number of the specific device. Running ``libinput debug-events`` lists
|
|
||||||
all devices currently available to libinput and their event node name: ::
|
|
||||||
|
|
||||||
$> sudo libinput debug-events
|
|
||||||
-event2 DEVICE_ADDED Power Button seat0 default group1 cap:k
|
|
||||||
-event5 DEVICE_ADDED Video Bus seat0 default group2 cap:k
|
|
||||||
-event0 DEVICE_ADDED Lid Switch seat0 default group3 cap:S
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
Note the event node name for your device and translate it into a syspath in
|
|
||||||
the form of ``/sys/class/input/eventX``. This path can be supplied to ``udevadm
|
|
||||||
info`` ::
|
|
||||||
|
|
||||||
$> udevadm info
|
|
||||||
P: /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0D:00/input/input0/event0
|
|
||||||
N: input/event0
|
|
||||||
E: DEVNAME=/dev/input/event0
|
|
||||||
E: DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0D:00/input/input0/event0
|
|
||||||
E: ID_INPUT=1
|
|
||||||
E: ID_INPUT_SWITCH=1
|
|
||||||
E: MAJOR=13
|
|
||||||
E: MINOR=64
|
|
||||||
E: SUBSYSTEM=input
|
|
||||||
E: TAGS=:power-switch:
|
|
||||||
E: USEC_INITIALIZED=7167898
|
|
||||||
|
|
||||||
Lines starting with ``E:`` are udev properties available to libinput. For
|
|
||||||
example, the above device's ``ID_INPUT_SWITCH`` property will cause libinput
|
|
||||||
to treat this device as switch device.
|
|
||||||
|
|
||||||
|
|
||||||
.. _hwdb_reloading:
|
|
||||||
|
|
||||||
..............................................................................
|
|
||||||
Reloading the hwdb
|
|
||||||
..............................................................................
|
|
||||||
|
|
||||||
The actual hwdb is stored in binary file on-disk and must be updated
|
|
||||||
manually whenever a ``.hwdb`` file changes. This is required both when a user
|
|
||||||
manually edits the ``.hwdb`` file but also when the git tree is updated (and
|
|
||||||
that update causes a hwdb change).
|
|
||||||
|
|
||||||
To update the binary file on-disk, run: ::
|
|
||||||
|
|
||||||
sudo systemd-hwdb update
|
|
||||||
|
|
||||||
Then, to trigger a reload of all properties on your device, run: ::
|
|
||||||
|
|
||||||
sudo udevadm trigger /sys/class/input/eventX
|
|
||||||
|
|
||||||
Then check with ``udevadm info`` whether the properties were updated, see
|
|
||||||
:ref:`hwdb_querying`. If a new property does not appear on the device, use ``udevadm
|
|
||||||
test`` to check for error messages by udev and the hwdb (e.g. syntax errors
|
|
||||||
in the udev rules files). ::
|
|
||||||
|
|
||||||
sudo udevadm test /sys/class/input/eventX
|
|
||||||
|
|
||||||
.. warning:: ``udevadm test`` does not run commands specified in ``RUN``
|
|
||||||
directives. This affects the udev properties relying on e.g.
|
|
||||||
the udev keyboard builtin such as the :ref:`touchpad_jitter`
|
|
||||||
workarounds.
|
|
||||||
|
|
||||||
.. _hwdb_modifying:
|
|
||||||
|
|
||||||
..............................................................................
|
|
||||||
Modifying the hwdb
|
|
||||||
..............................................................................
|
|
||||||
|
|
||||||
.. warning:: This section has been removed as it no longer applies in libinput 1.12
|
|
||||||
and later. libinput users should not need to modify the hwdb, any
|
|
||||||
device-specific quirks must go in to the :ref:`device-quirks` system.
|
|
||||||
|
|
||||||
For information about older libinput versions, please see the documentation
|
|
||||||
for your version available in: https://wayland.freedesktop.org/libinput/doc/
|
|
||||||
|
|
@ -1,244 +0,0 @@
|
||||||
.. _device-quirks:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Device quirks
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
libinput requires extra information from devices that is not always readily
|
|
||||||
available. For example, some touchpads are known to have jumping cursors
|
|
||||||
under specific conditions. libinput ships a set of files containing the
|
|
||||||
so-called model quirks to provide that information. Model quirks are usually
|
|
||||||
installed under ``/usr/share/libinput/<filename>.quirks`` and are standard
|
|
||||||
``.ini`` files. A file may contain multiple section headers (``[some
|
|
||||||
identifier]``) followed by one or more :ref:`MatchFoo=Bar <device-quirks-matches>`
|
|
||||||
directives, followed by at least one of ``ModelFoo=1`` or ``AttrFoo=bar`` directive.
|
|
||||||
See the ``quirks/README.md`` file in the libinput source repository for more
|
|
||||||
details on their contents.
|
|
||||||
|
|
||||||
.. warning:: Model quirks are internal API and may change at any time. No
|
|
||||||
backwards-compatibility is guaranteed.
|
|
||||||
|
|
||||||
For example, a quirks file may have this content to label all keyboards on
|
|
||||||
the serial bus (PS/2) as internal keyboards: ::
|
|
||||||
|
|
||||||
[Serial Keyboards]
|
|
||||||
MatchUdevType=keyboard
|
|
||||||
MatchBus=serial
|
|
||||||
AttrKeyboardIntegration=internal
|
|
||||||
|
|
||||||
|
|
||||||
The model quirks are part of the source distribution and should never be
|
|
||||||
modified locally. Updates to libinput may overwrite modifications or even
|
|
||||||
stop parsing any property. For temporary local workarounds, see
|
|
||||||
:ref:`device-quirks-local`.
|
|
||||||
|
|
||||||
Device quirks are parsed on libinput initialization. A parsing error in the
|
|
||||||
device quirks disables **all** device quirks and may negatively impact
|
|
||||||
device behavior on the host. If the quirks cannot be loaded, an error
|
|
||||||
message is posted to the log and users should use the information in
|
|
||||||
:ref:`device-quirks-debugging` to verify their quirks files.
|
|
||||||
|
|
||||||
.. _device-quirks-local:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Installing temporary local device quirks
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The model quirks are part of the source distribution and should never be
|
|
||||||
modified. For temporary local workarounds, libinput reads the
|
|
||||||
``/etc/libinput/local-overrides.quirks`` file. Users may add sections to
|
|
||||||
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.
|
|
||||||
|
|
||||||
.. warning:: Model quirks are internal API and may change at any time. No
|
|
||||||
backwards-compatibility is guaranteed. Local overrides should only
|
|
||||||
be used until the distribution updates the libinput packages.
|
|
||||||
|
|
||||||
The ``local-overrides.quirks`` file usually needs to be created by the user.
|
|
||||||
Once the required section has been added, use the information from section
|
|
||||||
:ref:`device-quirks-debugging` to validate and test the quirks.
|
|
||||||
|
|
||||||
.. _device-quirks-debugging:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Debugging device quirks
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
libinput provides the ``libinput quirks`` tool to debug the quirks database.
|
|
||||||
This tool takes an action as first argument, the most common invocation is
|
|
||||||
``libinput quirks list`` to list model quirks that apply to one or more local
|
|
||||||
devices. ::
|
|
||||||
|
|
||||||
$ libinput quirks list /dev/input/event19
|
|
||||||
$ libinput quirks list /dev/input/event0
|
|
||||||
AttrLidSwitchReliability=unreliable
|
|
||||||
|
|
||||||
The device `event19` does not have any quirks assigned.
|
|
||||||
|
|
||||||
When called with the ``--verbose`` argument, ``libinput quirks list`` prints
|
|
||||||
information about all files and its attempts to match the device: ::
|
|
||||||
|
|
||||||
$ libinput quirks list --verbose /dev/input/event0
|
|
||||||
quirks debug: /usr/share/share/libinput is data root
|
|
||||||
quirks debug: /usr/share/share/libinput/10-generic-keyboard.quirks
|
|
||||||
quirks debug: /usr/share/share/libinput/10-generic-lid.quirks
|
|
||||||
[...]
|
|
||||||
quirks debug: /usr/share/etc/libinput/local-overrides.quirks
|
|
||||||
quirks debug: /dev/input/event0: fetching quirks
|
|
||||||
quirks debug: [Serial Keyboards] (10-generic-keyboard.quirks) wants MatchBus but we don't have that
|
|
||||||
quirks debug: [Lid Switch Ct9] (10-generic-lid.quirks) matches for MatchName
|
|
||||||
quirks debug: [Lid Switch Ct10] (10-generic-lid.quirks) matches for MatchName
|
|
||||||
quirks debug: [Lid Switch Ct10] (10-generic-lid.quirks) matches for MatchDMIModalias
|
|
||||||
quirks debug: [Lid Switch Ct10] (10-generic-lid.quirks) is full match
|
|
||||||
quirks debug: property added: AttrLidSwitchReliability from [Lid Switch Ct10] (10-generic-lid.quirks)
|
|
||||||
quirks debug: [Aiptek No Tilt Tablet] (30-vendor-aiptek.quirks) wants MatchBus but we don't have that
|
|
||||||
[...]
|
|
||||||
quirks debug: [HUION PenTablet] (30-vendor-huion.quirks) wants MatchBus but we don't have that
|
|
||||||
quirks debug: [Logitech Marble Mouse Trackball] (30-vendor-logitech.quirks) wants MatchBus but we don't have that
|
|
||||||
quirks debug: [Logitech K400] (30-vendor-logitech.quirks) wants MatchBus but we don't have that
|
|
||||||
quirks debug: [Logitech K400r] (30-vendor-logitech.quirks) wants MatchBus but we don't have that
|
|
||||||
quirks debug: [Logitech K830] (30-vendor-logitech.quirks) wants MatchBus but we don't have that
|
|
||||||
quirks debug: [Logitech K400Plus] (30-vendor-logitech.quirks) wants MatchBus but we don't have that
|
|
||||||
quirks debug: [Logitech Wireless Touchpad] (30-vendor-logitech.quirks) wants MatchBus but we don't have that
|
|
||||||
quirks debug: [Microsoft Surface 3 Lid Switch] (30-vendor-microsoft.quirks) matches for MatchName
|
|
||||||
[...]
|
|
||||||
AttrLidSwitchReliability
|
|
||||||
|
|
||||||
|
|
||||||
Note that this is an example only, the output may change over time. The tool
|
|
||||||
uses the same parser as libinput and any parsing errors will show up in the
|
|
||||||
output.
|
|
||||||
|
|
||||||
.. _device-quirks-list:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
List of currently available device quirks
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
This list is a guide for developers to ease the process of submitting
|
|
||||||
patches upstream. This section shows device quirks currently available in
|
|
||||||
|git_version|.
|
|
||||||
|
|
||||||
.. 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
|
|
||||||
libinput.
|
|
||||||
|
|
||||||
In the documentation below, the letters N, M, O, P refer to arbitrary integer
|
|
||||||
values.
|
|
||||||
|
|
||||||
Quirks starting with **Model*** triggers implementation-defined behaviour
|
|
||||||
for this device not needed for any other device. Only the more
|
|
||||||
general-purpose **Model*** flags are listed here.
|
|
||||||
|
|
||||||
ModelALPSTouchpad, ModelAppleTouchpad, ModelWacomTouchpad, ModelChromebook
|
|
||||||
Reserved for touchpads made by the respective vendors
|
|
||||||
ModelTouchpadVisibleMarker
|
|
||||||
Indicates the touchpad has a drawn-on visible marker between the software
|
|
||||||
buttons.
|
|
||||||
ModelTabletModeNoSuspend
|
|
||||||
Indicates that the device does not need to be
|
|
||||||
suspended in :ref:`switches_tablet_mode`.
|
|
||||||
ModelTabletModeSwitchUnreliable
|
|
||||||
Indicates that this tablet mode switch's state cannot be relied upon.
|
|
||||||
ModelTrackball
|
|
||||||
Reserved for trackballs
|
|
||||||
ModelBouncingKeys
|
|
||||||
Indicates that the device may send fake bouncing key events and
|
|
||||||
timestamps can not be relied upon.
|
|
||||||
ModelSynapticsSerialTouchpad
|
|
||||||
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
|
|
||||||
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
|
|
||||||
a large proportion of matching devices. They should not be used for any
|
|
||||||
specific device, override ``EVDEV_ABS_*`` instead, see
|
|
||||||
:ref:`absolute_coordinate_ranges_fix`.
|
|
||||||
AttrTouchSizeRange=N:M, AttrPalmSizeThreshold=O
|
|
||||||
Specifies the touch size required to trigger a press (N) and to trigger
|
|
||||||
a release (M). O > N > M. See :ref:`touchpad_touch_size_hwdb` for more
|
|
||||||
details.
|
|
||||||
An AttrPalmSizeThreshold of zero unsets any threshold that has been
|
|
||||||
inherited from another quirk.
|
|
||||||
AttrPressureRange=N:M, AttrPalmPressureThreshold=O, AttrThumbPressureThreshold=P
|
|
||||||
Specifies the touch pressure required to trigger a press (N) and to
|
|
||||||
trigger a release (M), when a palm touch is triggered (O) and when a
|
|
||||||
thumb touch is triggered (P). O > P > N > M. See
|
|
||||||
:ref:`touchpad_pressure_hwdb` for more details.
|
|
||||||
An AttrPalmPressureThreshold of zero unsets any threshold that has been
|
|
||||||
inherited from another quirk.
|
|
||||||
AttrLidSwitchReliability=reliable|unreliable|write_open
|
|
||||||
Indicates the reliability of the lid switch. This is a string enum.
|
|
||||||
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
|
|
||||||
Indicates the integration of the keyboard. This is a string enum.
|
|
||||||
Generally only needed for USB keyboards.
|
|
||||||
AttrTPKComboLayout=below
|
|
||||||
Indicates the position of the touchpad on an external touchpad+keyboard
|
|
||||||
combination device. This is a string enum. Don't specify it unless the
|
|
||||||
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.
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
digraph stack
|
|
||||||
{
|
|
||||||
compound=true;
|
|
||||||
rankdir="LR";
|
|
||||||
node [
|
|
||||||
shape="box";
|
|
||||||
]
|
|
||||||
|
|
||||||
kernel [label="Kernel"];
|
|
||||||
|
|
||||||
libinput;
|
|
||||||
xserver [label="X Server"];
|
|
||||||
|
|
||||||
kernel -> libinput
|
|
||||||
libinput -> xserver
|
|
||||||
|
|
||||||
kernel -> evemu
|
|
||||||
evemu -> stdout
|
|
||||||
}
|
|
||||||
|
|
@ -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];
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
digraph stack
|
|
||||||
{
|
|
||||||
compound=true;
|
|
||||||
rankdir="LR";
|
|
||||||
node [
|
|
||||||
shape="box";
|
|
||||||
]
|
|
||||||
|
|
||||||
gcc -> gsettings
|
|
||||||
|
|
||||||
xf86libinput -> libinput
|
|
||||||
|
|
||||||
subgraph cluster0 {
|
|
||||||
label="X.Org";
|
|
||||||
xf86libinput [label="xf86-input-libinput"];
|
|
||||||
xserver [label="X Server"];
|
|
||||||
xserver -> xf86libinput;
|
|
||||||
}
|
|
||||||
|
|
||||||
gcc [label="gnome-control-center"];
|
|
||||||
|
|
||||||
subgraph cluster3 {
|
|
||||||
gsettings
|
|
||||||
}
|
|
||||||
|
|
||||||
gsd [label="mutter"];
|
|
||||||
|
|
||||||
gsd -> gsettings
|
|
||||||
gsd -> xserver
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
digraph stack
|
|
||||||
{
|
|
||||||
compound=true;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
client [label="Wayland client"];
|
|
||||||
|
|
||||||
event0 -> libinput;
|
|
||||||
event1 -> libinput;
|
|
||||||
libinput -> client [ltail=cluster_0 label="Wayland protocol"];
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
digraph stack
|
|
||||||
{
|
|
||||||
compound=true;
|
|
||||||
rankdir="LR";
|
|
||||||
node [
|
|
||||||
shape="box";
|
|
||||||
]
|
|
||||||
|
|
||||||
subgraph cluster_2 {
|
|
||||||
label="Kernel";
|
|
||||||
event0 [label="/dev/input/event0"]
|
|
||||||
event1 [label="/dev/input/event1"]
|
|
||||||
}
|
|
||||||
|
|
||||||
subgraph cluster_0 {
|
|
||||||
label="X server process";
|
|
||||||
subgraph cluster_1 {
|
|
||||||
label="xf86-input-libinput"
|
|
||||||
libinput;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
libinput;
|
|
||||||
client [label="X11 client"];
|
|
||||||
|
|
||||||
event0 -> libinput;
|
|
||||||
event1 -> libinput;
|
|
||||||
libinput -> client [ltail=cluster_0 label="X protocol"];
|
|
||||||
}
|
|
||||||
|
|
@ -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"];
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
digraph seats_libinput
|
|
||||||
{
|
|
||||||
rankdir="BT";
|
|
||||||
node [
|
|
||||||
shape="box";
|
|
||||||
]
|
|
||||||
|
|
||||||
ctx1 [label="libinput context 1"; URL="\ref libinput"];
|
|
||||||
ctx2 [label="libinput context 2"; URL="\ref libinput"];
|
|
||||||
|
|
||||||
seat0 [ label="seat phys 0 logical A"];
|
|
||||||
seat1 [ label="seat phys 0 logical B"];
|
|
||||||
seat2 [ label="seat phys 1 logical C"];
|
|
||||||
|
|
||||||
dev1 [label="device 'Foo'"];
|
|
||||||
dev2 [label="device 'Bar'"];
|
|
||||||
dev3 [label="device 'Spam'"];
|
|
||||||
dev4 [label="device 'Egg'"];
|
|
||||||
|
|
||||||
ctx1 -> dev1
|
|
||||||
ctx1 -> dev2
|
|
||||||
ctx1 -> dev3
|
|
||||||
ctx2 -> dev4
|
|
||||||
|
|
||||||
dev1 -> seat0
|
|
||||||
dev2 -> seat0
|
|
||||||
dev3 -> seat1
|
|
||||||
dev4 -> seat2
|
|
||||||
}
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
digraph seats
|
|
||||||
{
|
|
||||||
rankdir="BT";
|
|
||||||
node [
|
|
||||||
shape="box";
|
|
||||||
]
|
|
||||||
|
|
||||||
kernel [label="Kernel"];
|
|
||||||
|
|
||||||
event0 [URL="\ref libinput_event"];
|
|
||||||
event1 [URL="\ref libinput_event"];
|
|
||||||
event2 [URL="\ref libinput_event"];
|
|
||||||
event3 [URL="\ref libinput_event"];
|
|
||||||
|
|
||||||
pseat0 [label="phys seat0"; URL="\ref libinput_seat_get_physical_name"];
|
|
||||||
pseat1 [label="phys seat1"; URL="\ref libinput_seat_get_physical_name"];
|
|
||||||
|
|
||||||
lseatA [label="logical seat A"; URL="\ref libinput_seat_get_logical_name"];
|
|
||||||
lseatB [label="logical seat B"; URL="\ref libinput_seat_get_logical_name"];
|
|
||||||
lseatC [label="logical seat C"; URL="\ref libinput_seat_get_logical_name"];
|
|
||||||
|
|
||||||
ctx1 [label="libinput context 1"; URL="\ref libinput"];
|
|
||||||
ctx2 [label="libinput context 2"; URL="\ref libinput"];
|
|
||||||
|
|
||||||
dev1 [label="device 'Foo'"];
|
|
||||||
dev2 [label="device 'Bar'"];
|
|
||||||
dev3 [label="device 'Spam'"];
|
|
||||||
dev4 [label="device 'Egg'"];
|
|
||||||
|
|
||||||
kernel -> event0
|
|
||||||
kernel -> event1
|
|
||||||
kernel -> event2
|
|
||||||
kernel -> event3
|
|
||||||
|
|
||||||
event0 -> pseat0
|
|
||||||
event1 -> pseat0
|
|
||||||
event2 -> pseat0
|
|
||||||
event3 -> pseat1
|
|
||||||
|
|
||||||
pseat0 -> ctx1
|
|
||||||
pseat1 -> ctx2
|
|
||||||
|
|
||||||
ctx1 -> lseatA
|
|
||||||
ctx1 -> lseatB
|
|
||||||
ctx2 -> lseatC
|
|
||||||
|
|
||||||
lseatA -> dev1
|
|
||||||
lseatA -> dev2
|
|
||||||
lseatB -> dev3
|
|
||||||
lseatC -> dev4
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -1,390 +0,0 @@
|
||||||
.. _faq:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
FAQs - Frequently Asked Questions
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
Frequently asked questions about libinput.
|
|
||||||
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:local:
|
|
||||||
:backlinks: entry
|
|
||||||
|
|
||||||
.. _faq_feature:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Why doesn't libinput support ...?
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
First, read :ref:`what_is_libinput` If you have a feature that you think
|
|
||||||
libinput needs to support, please file a bug report. See :ref:`reporting_bugs`
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
.. _faq_fast_mouse:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
My mouse moves too fast, even at the slowest setting
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
This is a symptom of high-dpi mice (greater than 1000dpi). These devices
|
|
||||||
need a udev hwdb entry to normalize their motion. See
|
|
||||||
:ref:`motion_normalization` for a detailed explanation.
|
|
||||||
|
|
||||||
.. _faq_fast_trackpoint:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
My trackpoint moves too slow or too fast
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
This is a symptom of an invalid trackpoint multiplier. These devices need
|
|
||||||
:ref:`device-quirks` to specify the range available so libinput can adjust the
|
|
||||||
pointer acceleration accordingly. See :ref:`trackpoint_range` for a detailed
|
|
||||||
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:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Why isn't touchpad tap-to-click enabled by default
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
See :ref:`tapping_default`
|
|
||||||
|
|
||||||
.. _faq_touchpad_pressure:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Why does my touchpad lose track of touches
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The most common cause for this is an incorrect pressure threshold range.
|
|
||||||
See :ref:`touchpad_pressure` for more info.
|
|
||||||
|
|
||||||
.. _faq_kinetic_scrolling:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Kinetic scrolling does not work
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The X.Org synaptics driver implemented kinetic scrolling in the driver. It
|
|
||||||
measures the scroll speed and once the finger leaves the touchpad the driver
|
|
||||||
keeps sending scroll events for a predetermined time. This effectively
|
|
||||||
provides for kinetic scrolling without client support but triggers an
|
|
||||||
unfixable `bug <https://bugs.freedesktop.org/show_bug.cgi?id=38909>`_: the
|
|
||||||
client cannot know that the events are from a kinetic scroll source. Scroll
|
|
||||||
events in X are always sent to the current cursor position, a movement of the
|
|
||||||
cursor after lifting the finger will send the kinetic scroll events to the
|
|
||||||
new client, something the user does not usually expect. A key event during
|
|
||||||
the kinetic scroll procedure causes side-effects such as triggering zoom.
|
|
||||||
|
|
||||||
libinput does not implement kinetic scrolling for touchpads. Instead it
|
|
||||||
provides the **libinput_event_pointer_get_axis_source()** function that enables
|
|
||||||
callers to implement kinetic scrolling on a per-widget basis, see
|
|
||||||
:ref:`scroll_sources`.
|
|
||||||
|
|
||||||
.. _faq_gpl:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Is libinput GPL-licensed?
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
No, libinput is MIT licensed. The Linux kernel header file linux/input.h in
|
|
||||||
libinput's tree is provided to ensure the same behavior regardless of which
|
|
||||||
kernel version libinput is built on. It does not make libinput GPL-licensed.
|
|
||||||
|
|
||||||
.. _faq_config_options:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Where is the configuration stored?
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
libinput does not store configuration options, it is up to the caller to
|
|
||||||
manage these and decide which configuration option to apply to each device.
|
|
||||||
This must be done at startup, after a resume and whenever a new device is
|
|
||||||
detected.
|
|
||||||
|
|
||||||
One commonly used way to configure libinput is to have the Wayland
|
|
||||||
compositor expose a compositor-specific configuration option. For example,
|
|
||||||
in a GNOME stack, the gnome-control-center modifies dconf entries. These
|
|
||||||
changes are read by mutter and applied to libinput. Changing these entries
|
|
||||||
via the gsettings commandline tool has the same effect.
|
|
||||||
|
|
||||||
Another commonly used way to configure libinput is to have xorg.conf.d
|
|
||||||
snippets. When libinput is used with the xf86-input-libinput driver in an
|
|
||||||
X.Org stack, these options are read on startup and apply to each device.
|
|
||||||
Changing properties at runtime with the xinput commandline tool has the same
|
|
||||||
effect.
|
|
||||||
|
|
||||||
In both cases, the selection of available options and how they are exposed
|
|
||||||
depends on the libinput caller (e.g. mutter or xf86-input-libinput).
|
|
||||||
|
|
||||||
.. graphviz:: libinput-stack-gnome.gv
|
|
||||||
|
|
||||||
This has an effect on the availability of configuration options: if an
|
|
||||||
option is not exposed by the intermediary, it cannot be configured by the
|
|
||||||
client. Also some configuration options that are provided by the
|
|
||||||
intermediary may not be libinput-specific configuration options.
|
|
||||||
|
|
||||||
.. _faq_configure_wayland:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
How do I configure my device on Wayland?
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
See :ref:`faq_config_options` Use the configuration tool provided by your
|
|
||||||
desktop environment (e.g. gnome-control-center) or direct access to your
|
|
||||||
desktop environment's configuration storage (e.g. gsettings).
|
|
||||||
|
|
||||||
.. _faq_configure_xorg:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
How do I configure my device on X?
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
See :ref:`faq_config_options` If your desktop environment does not provide a
|
|
||||||
graphical configuration tool you can use an
|
|
||||||
`xorg.conf.d snippet <https://www.x.org/archive/current/doc/man/man5/xorg.conf.5.xhtml>`_.
|
|
||||||
Usually, such a snippet looks like this:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$> cat /etc/X11/xorg.conf.d/99-libinput-custom-config.conf
|
|
||||||
Section "InputClass"
|
|
||||||
Identifier "something to identify this snippet"
|
|
||||||
MatchDriver "libinput"
|
|
||||||
MatchProduct "substring of the device name"
|
|
||||||
Option "some option name" "the option value"
|
|
||||||
EndSection
|
|
||||||
|
|
||||||
|
|
||||||
The identifier is merely a human-readable string that shows up in the log
|
|
||||||
file. The MatchProduct line should contain the device name or a substring of
|
|
||||||
the device name that the snippet should apply to. For a full list of option
|
|
||||||
names and permitted values, see the
|
|
||||||
`libinput man page <https://www.mankier.com/4/libinput>`_.
|
|
||||||
xorg.conf.d snippets like the above apply to hotplugged devices but can be
|
|
||||||
overwritten at runtime by desktop tools. Multiple snippets may be placed
|
|
||||||
into the same file.
|
|
||||||
|
|
||||||
For run-time configuration and testing, the
|
|
||||||
`xinput <https://www.x.org/archive/X11R7.5/doc/man/man1/xinput.1.html>`_
|
|
||||||
debugging tool can modify a devices' properties. See the
|
|
||||||
`libinput man page <https://www.mankier.com/4/libinput>`_
|
|
||||||
for supported property names and values. Usually, an invocation looks like
|
|
||||||
this:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
$> xinput set-prop "the device name" "the property name" value [value2] [value3]
|
|
||||||
|
|
||||||
|
|
||||||
.. note:: Changes performed by xinput do not persist across device hotplugs. xinput
|
|
||||||
is considered a debugging and testing tool only and should not be used
|
|
||||||
for permanent configurations.
|
|
||||||
|
|
||||||
.. _faq_configuration:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Can you add a configuration option for $FEATURE?
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
No. At least that's going to be the initial answer. Read
|
|
||||||
`Why libinput doesn't have a lot of configuration options <http://who-t.blogspot.com/2016/04/why-libinput-doesnt-have-lot-of-config.html>`_
|
|
||||||
first. Configuration options for most features are a signal that we are incapable
|
|
||||||
of handling it correctly. To get to that point, we want to be sure we're
|
|
||||||
truly incapable of doing so. libinput has several features that
|
|
||||||
are handled automatically (and correctly) that users wanted to have
|
|
||||||
configuration options for initially.
|
|
||||||
|
|
||||||
So the answer to this question will almost always be 'no'. A configuration
|
|
||||||
option is, in most cases, a cop-out.
|
|
||||||
|
|
||||||
.. _faq_synclient:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Why don't synclient and syndaemon work with libinput?
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Synclient and syndaemon rely on X input device properties that are specific
|
|
||||||
to the xf86-input-synaptics X.Org input driver. Both were written when the
|
|
||||||
synaptics driver was the only common touchpad driver in existence. They
|
|
||||||
assume that if the properties aren't available, no touchpad is available
|
|
||||||
either. The xf86-input-libinput X.Org input driver does not export these
|
|
||||||
driver-specific properties, synclient/syndaemon will thus not detect the
|
|
||||||
touchpad and refuse to work. Other tools that rely on synclient/syndaemon or
|
|
||||||
those same properties also do not work with xf86-input-libinput.
|
|
||||||
|
|
||||||
Most of syndaemon's functionality is built into libinput, see
|
|
||||||
:ref:`disable-while-typing`. synclient is merely a configuration tool, see
|
|
||||||
:ref:`faq_configure_xorg` for similar functionality.
|
|
||||||
|
|
||||||
See also the blog posts
|
|
||||||
`The definitive guide to synclient <http://who-t.blogspot.com.au/2017/01/the-definitive-guide-to-synclient.html>`_ and
|
|
||||||
`The future of xinput, xmodmap, setxkbmap, xsetwacom and other tools under Wayland <http://who-t.blogspot.com.au/2016/12/the-future-of-xinput-xmodmap-setxkbmap.html>`_
|
|
||||||
|
|
||||||
.. _faq_tablets:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Does libinput support non-Wacom tablets?
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Yes, though unfortunately many non-Wacom tablets suffer from bad firmware
|
|
||||||
and don't send the required events. But they should all work nonetheless. If
|
|
||||||
you have a tablet that does not work with libinput, please
|
|
||||||
:ref:`file a bug <reporting_bugs>`.
|
|
||||||
|
|
||||||
.. _faq_tablet_capabilities:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
My tablet doesn't work
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
If you see the message
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
libinput bug: device does not meet tablet criteria. Ignoring this device.
|
|
||||||
|
|
||||||
|
|
||||||
or the message
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
missing tablet capabilities [...] Ignoring this device.
|
|
||||||
|
|
||||||
|
|
||||||
your tablet device does not have the required capabilities to be treated as
|
|
||||||
a tablet. This is usually a problem with the device and the kernel driver.
|
|
||||||
See :ref:`tablet-capabilities` for more details.
|
|
||||||
|
|
||||||
.. _faq_hwdb_changes:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
How to apply hwdb changes
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Sometimes users are asked to test updates to the
|
|
||||||
`udev hwdb <https://www.freedesktop.org/software/systemd/man/hwdb.html>`_
|
|
||||||
or patches that include a change to the hwdb. See :ref:`hwdb` for
|
|
||||||
details on the hwdb and how to modify it locally.
|
|
||||||
|
|
||||||
.. note:: As of libinput 1.12, libinput-specific properties are now stored in
|
|
||||||
the :ref:`device-quirks` system. There are no libinput-specific hwdb
|
|
||||||
entries anymore and any changes to the hwdb must be merged into the
|
|
||||||
systemd repository.
|
|
||||||
|
|
||||||
.. _faq_timer_offset:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
What causes the "your system is too slow" warning?
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
libinput relies on the caller to call **libinput_dispatch()** whenever data is
|
|
||||||
available. **libinput_dispatch()** will process the state of all devices,
|
|
||||||
including some time-sensitive features (e.g. palm detection, tap-to-click,
|
|
||||||
disable-while-typing, etc.).
|
|
||||||
|
|
||||||
If the time between the event and the call to **libinput_dispatch()**
|
|
||||||
is excessive, those features may not work correctly. For example, a delay in
|
|
||||||
touch event processing may cause wrong or missing tap-to-click events or
|
|
||||||
a palm may not be detected correctly.
|
|
||||||
|
|
||||||
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
|
|
||||||
is an indication of the caller being overloaded and not handling events as
|
|
||||||
speedily as required.
|
|
||||||
|
|
||||||
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
|
|
||||||
libinput. libinput does not control how quickly **libinput_dispatch()** is
|
|
||||||
called.
|
|
||||||
|
|
||||||
.. _faq_wayland:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Is libinput required for Wayland?
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Technically - no. But for your use-case - probably.
|
|
||||||
|
|
||||||
Wayland is a display server communication protocol. libinput is a low-level
|
|
||||||
library to simplify handling input devices and their events. They have no
|
|
||||||
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
|
|
||||||
pen required to write English". No, it isn't.
|
|
||||||
|
|
||||||
You can use libinput without a Wayland compositor, you can write a Wayland
|
|
||||||
compositor without libinput. On most major distributions, libinput is the
|
|
||||||
standard input stack used with the X.Org X server through the
|
|
||||||
xf86-input-libinput driver.
|
|
||||||
|
|
||||||
So why "for your use-case - probably"? All general-purpose Wayland
|
|
||||||
compositors use libinput for their input stack. Wayland compositors that
|
|
||||||
are more specialized (e.g. in-vehicle infotainment or IVI) can handle input
|
|
||||||
devices directly but the compositor you want to use
|
|
||||||
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.
|
|
||||||
|
|
||||||
.. _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.
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
.. _features:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
libinput Features
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
Below is a list of features supported by libinput. The availability of
|
|
||||||
features usually depends on the device type and a device's capabilities.
|
|
||||||
Not all features are user-configurable, some rely on :ref:`device-quirks`
|
|
||||||
to be useful.
|
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 1
|
|
||||||
|
|
||||||
button-debouncing.rst
|
|
||||||
clickpad-softbuttons.rst
|
|
||||||
gestures.rst
|
|
||||||
middle-button-emulation.rst
|
|
||||||
palm-detection.rst
|
|
||||||
touchpad-thumb-detection.rst
|
|
||||||
scrolling.rst
|
|
||||||
t440-support.rst
|
|
||||||
tapping.rst
|
|
||||||
drag-3fg.rst
|
|
||||||
tablet-support.rst
|
|
||||||
switches.rst
|
|
||||||
touchpad-pressure.rst
|
|
||||||
trackpoints.rst
|
|
||||||
|
|
@ -1,373 +0,0 @@
|
||||||
.. _gestures:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Gestures
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
libinput supports :ref:`gestures_pinch` and :ref:`gestures_swipe` on most
|
|
||||||
modern touchpads and other indirect touch devices. Note that libinput **does
|
|
||||||
not** support gestures on touchscreens, see :ref:`gestures_touchscreens`.
|
|
||||||
|
|
||||||
.. _gestures_lifetime:
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
Lifetime of a gesture
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
A gesture starts when the finger position and/or finger motion is
|
|
||||||
unambiguous as to what gesture to trigger and continues until the first
|
|
||||||
finger belonging to this gesture is lifted.
|
|
||||||
|
|
||||||
A single gesture cannot change the finger count. For example, if a user
|
|
||||||
puts down a fourth finger during a three-finger swipe gesture, libinput will
|
|
||||||
end (cancel) the three-finger gesture and, if applicable, start a
|
|
||||||
four-finger swipe gesture. A caller may however decide that those gestures
|
|
||||||
are semantically identical and continue the two gestures as one single
|
|
||||||
gesture.
|
|
||||||
|
|
||||||
.. _gestures_pinch:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Pinch gestures
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Pinch gestures are executed when two or more fingers are located on the
|
|
||||||
touchpad and are either changing the relative distance to each other
|
|
||||||
(pinching) or are changing the relative angle (rotate). Pinch gestures may
|
|
||||||
change both rotation and distance at the same time. For such gestures,
|
|
||||||
libinput calculates a logical center for the gestures and provides the
|
|
||||||
caller with the delta x/y coordinates of that center, the relative angle of
|
|
||||||
the fingers compared to the previous event, and the absolute scale compared
|
|
||||||
to the initial finger position.
|
|
||||||
|
|
||||||
.. figure:: pinch-gestures.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
The pinch and rotate gestures
|
|
||||||
|
|
||||||
The illustration above shows a basic pinch in the left image and a rotate in
|
|
||||||
the right angle. Not shown is a movement of the logical center if the
|
|
||||||
fingers move unevenly. Such a movement is supported by libinput, it is
|
|
||||||
merely left out of the illustration.
|
|
||||||
|
|
||||||
Note that while position and angle is relative to the previous event, the
|
|
||||||
scale is always absolute and a multiplier of the initial finger position's
|
|
||||||
scale.
|
|
||||||
|
|
||||||
.. _gestures_swipe:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Swipe gestures
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Swipe gestures are executed when three or more fingers are moved
|
|
||||||
synchronously in the same direction. libinput provides x and y coordinates
|
|
||||||
in the gesture and thus allows swipe gestures in any direction, including
|
|
||||||
the tracing of complex paths. It is up to the caller to interpret the
|
|
||||||
gesture into an action or limit a gesture to specific directions only.
|
|
||||||
|
|
||||||
.. figure:: swipe-gestures.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
The swipe gestures
|
|
||||||
|
|
||||||
The illustration above shows a vertical three-finger swipe. The coordinates
|
|
||||||
provided during the gesture are the movements of the logical center.
|
|
||||||
|
|
||||||
.. _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:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Touchscreen gestures
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Touchscreen gestures are **not** interpreted by libinput. Rather, any touch
|
|
||||||
point is passed to the caller and any interpretation of gestures is up to
|
|
||||||
the caller or, eventually, the X or Wayland client.
|
|
||||||
|
|
||||||
Interpreting gestures on a touchscreen requires context that libinput does
|
|
||||||
not have, such as the location of windows and other virtual objects on the
|
|
||||||
screen as well as the context of those virtual objects:
|
|
||||||
|
|
||||||
.. figure:: touchscreen-gestures.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
Context-sensitivity of touchscreen gestures
|
|
||||||
|
|
||||||
In the above example, the finger movements are identical but in the left
|
|
||||||
case both fingers are located within the same window, thus suggesting an
|
|
||||||
attempt to zoom. In the right case both fingers are located on a window
|
|
||||||
border, thus suggesting a window movement. libinput has no knowledge of the
|
|
||||||
window coordinates and thus cannot differentiate the two.
|
|
||||||
|
|
||||||
.. _gestures_softbuttons:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Gestures with enabled software buttons
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
If the touchpad device is a :ref:`Clickpad <touchpads_buttons_clickpads>`, it
|
|
||||||
is recommended that a caller switches to :ref:`clickfinger`.
|
|
||||||
Usually fingers placed in a :ref:`software button area <software_buttons>`
|
|
||||||
are not considered for gestures, resulting in some gestures to be
|
|
||||||
interpreted as pointer motion or two-finger scroll events.
|
|
||||||
|
|
||||||
.. figure:: pinch-gestures-softbuttons.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
Interference of software buttons and pinch gestures
|
|
||||||
|
|
||||||
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
|
|
||||||
software button area. libinput ignores fingers within the software button
|
|
||||||
areas, the movement of the remaining fingers is thus interpreted as a
|
|
||||||
two-finger scroll motion.
|
|
||||||
|
|
||||||
.. _gestures_twofinger_touchpads:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Gestures on two-finger touchpads
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
As of kernel 4.2, many :ref:`touchpads_touch_partial_mt` provide only two
|
|
||||||
slots. This affects how gestures can be interpreted. Touchpads with only two
|
|
||||||
slots can identify two touches by position but can usually tell that there
|
|
||||||
is a third (or fourth) finger down on the touchpad - without providing
|
|
||||||
positional information for that finger.
|
|
||||||
|
|
||||||
Touchpoints are assigned in sequential order and only the first two touch
|
|
||||||
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
|
|
||||||
whenever a user puts the index and middle finger down first. Since the third
|
|
||||||
finger does not have positional information, its location cannot be
|
|
||||||
determined.
|
|
||||||
|
|
||||||
.. figure:: gesture-2fg-ambiguity.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
Ambiguity of three-finger gestures on two-finger touchpads
|
|
||||||
|
|
||||||
The image above illustrates this ambiguity. The index and middle finger are
|
|
||||||
set down first, the data stream from both finger positions looks identical.
|
|
||||||
In this case, libinput assumes the fingers are in a horizontal arrangement
|
|
||||||
(the right image above) and use a swipe gesture.
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
def get_git_version():
|
|
||||||
return "__GIT_VERSION__"[:7]
|
|
||||||
|
|
||||||
def get_git_version_full():
|
|
||||||
return "__GIT_VERSION__"
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
what-is-libinput
|
|
||||||
features
|
|
||||||
configuration
|
|
||||||
building
|
|
||||||
faqs
|
|
||||||
reporting-bugs
|
|
||||||
troubleshooting
|
|
||||||
contributing
|
|
||||||
development
|
|
||||||
lua-plugins
|
|
||||||
API documentation <@HTTP_DOC_LINK@/api/>
|
|
||||||
|
|
||||||
|
|
||||||
++++++++++++++++++++++++++++++
|
|
||||||
libinput
|
|
||||||
++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
libinput is a library that provides a full input stack for display servers
|
|
||||||
and other applications that need to handle input devices provided by the
|
|
||||||
kernel.
|
|
||||||
|
|
||||||
libinput provides device detection, event handling and abstraction to
|
|
||||||
minimize the amount of custom input code the user of libinput need to
|
|
||||||
provide the common set of functionality that users expect. Input event
|
|
||||||
processing includes scaling touch coordinates, generating
|
|
||||||
relative pointer events from touchpads, pointer acceleration, etc.
|
|
||||||
|
|
||||||
libinput is not used directly by applications. Think of it more as a device
|
|
||||||
driver than an application library. See :ref:`what_is_libinput` for more details.
|
|
||||||
|
|
||||||
--------------------
|
|
||||||
Users and Developers
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Please use the side-bar to navigate through the various documentation items.
|
|
||||||
|
|
||||||
-----------------
|
|
||||||
API documentation
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
The API documentation is available here:
|
|
||||||
https://wayland.freedesktop.org/libinput/doc/latest/api/
|
|
||||||
|
|
||||||
.. note:: This documentation is generally only needed by authors of Wayland
|
|
||||||
compositors or other developers dealing with input events directly.
|
|
||||||
|
|
||||||
-------
|
|
||||||
License
|
|
||||||
-------
|
|
||||||
|
|
||||||
libinput is licensed under the MIT license
|
|
||||||
|
|
||||||
.. code-block:: none
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
copy of this software and associated documentation files (the "Software"),
|
|
||||||
to deal in the Software without restriction, including without limitation
|
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following conditions: [...]
|
|
||||||
|
|
||||||
See the
|
|
||||||
`COPYING <https://gitlab.freedesktop.org/libinput/libinput/tree/master/COPYING>`_
|
|
||||||
file for the full license information.
|
|
||||||
|
|
||||||
.....
|
|
||||||
About
|
|
||||||
.....
|
|
||||||
Documentation generated from |git_version|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -1,224 +0,0 @@
|
||||||
# Sphinx build
|
|
||||||
sphinx = find_program('sphinx-build-3', 'sphinx-build', required : false)
|
|
||||||
if not sphinx.found()
|
|
||||||
error('Program "sphinx-build" not found or not executable. Try building with -Ddocumentation=false')
|
|
||||||
endif
|
|
||||||
|
|
||||||
yq = find_program('yq', required : false)
|
|
||||||
if not yq.found()
|
|
||||||
warning('Program "yq" not found or not executable. Dependency list will not be built.')
|
|
||||||
endif
|
|
||||||
|
|
||||||
sphinx_config = configuration_data()
|
|
||||||
sphinx_config.set('PROJECT_NAME', meson.project_name())
|
|
||||||
sphinx_config.set('PROJECT_VERSION', meson.project_version())
|
|
||||||
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',
|
|
||||||
output : 'conf.py',
|
|
||||||
configuration : sphinx_config)
|
|
||||||
|
|
||||||
# 404 replacements for old URLs
|
|
||||||
# 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/seats-sketch.gv',
|
|
||||||
'dot/seats-sketch-libinput.gv',
|
|
||||||
'dot/libinput-contexts.gv',
|
|
||||||
'dot/libinput-stack-wayland.gv',
|
|
||||||
'dot/libinput-stack-xorg.gv',
|
|
||||||
'dot/libinput-stack-gnome.gv',
|
|
||||||
'dot/evemu.gv',
|
|
||||||
'dot/libinput-record.gv',
|
|
||||||
'dot/plugin-stack.gv',
|
|
||||||
# svgs
|
|
||||||
'svg/button-debouncing-wave-diagram.svg',
|
|
||||||
'svg/button-scrolling.svg',
|
|
||||||
'svg/clickfinger.svg',
|
|
||||||
'svg/clickfinger-distance.svg',
|
|
||||||
'svg/edge-scrolling.svg',
|
|
||||||
'svg/gesture-2fg-ambiguity.svg',
|
|
||||||
'svg/palm-detection.svg',
|
|
||||||
'svg/pinch-gestures.svg',
|
|
||||||
'svg/pinch-gestures-softbuttons.svg',
|
|
||||||
'svg/ptraccel-custom.svg',
|
|
||||||
'svg/ptraccel-linear.svg',
|
|
||||||
'svg/ptraccel-low-dpi.svg',
|
|
||||||
'svg/ptraccel-touchpad.svg',
|
|
||||||
'svg/ptraccel-trackpoint.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/tablet-area.svg',
|
|
||||||
'svg/tablet-axes.svg',
|
|
||||||
'svg/tablet-cintiq24hd-modes.svg',
|
|
||||||
'svg/tablet-eraser-invert.svg',
|
|
||||||
'svg/tablet-eraser-button.svg',
|
|
||||||
'svg/tablet-interfaces.svg',
|
|
||||||
'svg/tablet-intuos-modes.svg',
|
|
||||||
'svg/tablet-left-handed.svg',
|
|
||||||
'svg/tablet-out-of-bounds.svg',
|
|
||||||
'svg/tablet.svg',
|
|
||||||
'svg/tap-n-drag.svg',
|
|
||||||
'svg/thumb-detection.svg',
|
|
||||||
'svg/top-software-buttons.svg',
|
|
||||||
'svg/touchscreen-gestures.svg',
|
|
||||||
'svg/trackpoint-delta-illustration.svg',
|
|
||||||
'svg/twofinger-scrolling.svg',
|
|
||||||
# rst files
|
|
||||||
'absolute-axes.rst',
|
|
||||||
'absolute-coordinate-ranges.rst',
|
|
||||||
'architecture.rst',
|
|
||||||
'building.rst',
|
|
||||||
'button-debouncing.rst',
|
|
||||||
'clickpad-softbuttons.rst',
|
|
||||||
'clickpad-with-right-button.rst',
|
|
||||||
'contributing.rst',
|
|
||||||
'device-configuration-via-udev.rst',
|
|
||||||
'device-quirks.rst',
|
|
||||||
'drag-3fg.rst',
|
|
||||||
'faqs.rst',
|
|
||||||
'gestures.rst',
|
|
||||||
'incorrectly-enabled-hires.rst',
|
|
||||||
'ignoring-devices.rst',
|
|
||||||
'middle-button-emulation.rst',
|
|
||||||
'normalization-of-relative-motion.rst',
|
|
||||||
'palm-detection.rst',
|
|
||||||
'lua-plugins.rst',
|
|
||||||
'pointer-acceleration.rst',
|
|
||||||
'reporting-bugs.rst',
|
|
||||||
'scrolling.rst',
|
|
||||||
'seats.rst',
|
|
||||||
'switches.rst',
|
|
||||||
't440-support.rst',
|
|
||||||
'tablet-support.rst',
|
|
||||||
'tapping.rst',
|
|
||||||
'test-suite.rst',
|
|
||||||
'timestamps.rst',
|
|
||||||
'tablet-debugging.rst',
|
|
||||||
'tools.rst',
|
|
||||||
'touchpad-jumping-cursors.rst',
|
|
||||||
'touchpad-pressure.rst',
|
|
||||||
'touchpad-pressure-debugging.rst',
|
|
||||||
'touchpad-jitter.rst',
|
|
||||||
'touchpad-thumb-detection.rst',
|
|
||||||
'touchpads.rst',
|
|
||||||
'trackpoints.rst',
|
|
||||||
'trackpoint-configuration.rst',
|
|
||||||
'what-is-libinput.rst',
|
|
||||||
'wheel-api.rst',
|
|
||||||
'features.rst',
|
|
||||||
'development.rst',
|
|
||||||
'troubleshooting.rst',
|
|
||||||
'configuration.rst',
|
|
||||||
)
|
|
||||||
|
|
||||||
src_sphinx = []
|
|
||||||
foreach f : src_rst
|
|
||||||
sf = configure_file(input: f,
|
|
||||||
output: '@PLAINNAME@',
|
|
||||||
copy : true)
|
|
||||||
src_sphinx += [ sf ]
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
configure_file(input: 'index.rst',
|
|
||||||
output: 'index.rst',
|
|
||||||
configuration: sphinx_config)
|
|
||||||
|
|
||||||
dependencies_config = configuration_data()
|
|
||||||
if yq.found()
|
|
||||||
distributions = ['fedora', 'ubuntu', 'debian', 'arch', 'alpine']
|
|
||||||
foreach distro : distributions
|
|
||||||
yq_filter = '.distributions[] | select(.name == "@0@") | .packages | join(" ")'.format(distro)
|
|
||||||
deps = run_command(yq, '-r', yq_filter,
|
|
||||||
dir_gitlab_ci / 'config.yml',
|
|
||||||
check: true).stdout()
|
|
||||||
dependencies_config.set('@0@_PACKAGES'.format(distro.to_upper()), deps)
|
|
||||||
endforeach
|
|
||||||
endif
|
|
||||||
configure_file(input: 'dependencies.rst',
|
|
||||||
output: 'dependencies.rst',
|
|
||||||
configuration: dependencies_config)
|
|
||||||
|
|
||||||
# do not use -j, it breaks on Ubuntu
|
|
||||||
sphinx_output_dir = 'Documentation'
|
|
||||||
custom_target('sphinx',
|
|
||||||
input : [ sphinx_conf_py, git_version_page ] + src_sphinx + dst_404s,
|
|
||||||
output : [ sphinx_output_dir ],
|
|
||||||
command : [ sphinx, '-q', '-b', 'html',
|
|
||||||
'-d', meson.current_build_dir() / 'doctrees',
|
|
||||||
meson.current_build_dir(), sphinx_output_dir],
|
|
||||||
build_by_default : true)
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
.. _middle_button_emulation:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Middle button emulation
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
Middle button emulation provides users with the ability to generate a middle
|
|
||||||
click even when the device does not have a physical middle button available.
|
|
||||||
|
|
||||||
When middle button emulation is enabled, a simultaneous press of the left
|
|
||||||
and right button generates a middle mouse button event. Releasing the
|
|
||||||
buttons generates a middle mouse button release, the left and right button
|
|
||||||
events are discarded otherwise.
|
|
||||||
|
|
||||||
The middle button release event may be generated when either button is
|
|
||||||
released, or when both buttons have been released. The exact behavior is
|
|
||||||
device-dependent, libinput will implement the behavior that is most
|
|
||||||
appropriate to the physical device.
|
|
||||||
|
|
||||||
The middle button emulation behavior when combined with other device
|
|
||||||
buttons, including a physical middle button is device-dependent.
|
|
||||||
For example, :ref:`clickpad_softbuttons` provides a middle button area when
|
|
||||||
middle button emulation is disabled. That middle button area disappears
|
|
||||||
when middle button emulation is enabled - a middle click can then only be
|
|
||||||
triggered by a simultaneous left + right click.
|
|
||||||
|
|
||||||
Some devices provide middle mouse button emulation but do not allow
|
|
||||||
enabling/disabling that emulation. Likewise, some devices may allow middle
|
|
||||||
button emulation but have it disabled by default. This is the case for most
|
|
||||||
mouse-like devices where a middle button is detected.
|
|
||||||
|
|
||||||
libinput provides **libinput_device_config_middle_emulation_set_enabled()** to
|
|
||||||
enable or disable middle button emulation. See :ref:`faq_configure_wayland`
|
|
||||||
and :ref:`faq_configure_xorg` for info on how to enable or disable middle
|
|
||||||
button emulation in the Wayland compositor or the X stack.
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
.. _motion_normalization:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Normalization of relative motion
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
Most relative input devices generate input in so-called "mickeys". A
|
|
||||||
mickey is in device-specific units that depend on the resolution
|
|
||||||
of the sensor. Most optical mice use sensors with 1000dpi resolution, but
|
|
||||||
some devices range from 100dpi to well above 8000dpi.
|
|
||||||
|
|
||||||
Without a physical reference point, a relative coordinate cannot be
|
|
||||||
interpreted correctly. A delta of 10 mickeys may be a millimeter of
|
|
||||||
physical movement or 10 millimeters, depending on the sensor. This
|
|
||||||
affects pointer acceleration in libinput and interpretation of relative
|
|
||||||
coordinates in callers.
|
|
||||||
|
|
||||||
libinput does partial normalization of relative input. For devices with a
|
|
||||||
resolution of 1000dpi and higher, motion events are normalized to a default
|
|
||||||
of 1000dpi before pointer acceleration is applied. As a result, devices with
|
|
||||||
1000dpi and above feel the same.
|
|
||||||
|
|
||||||
Devices below 1000dpi are not normalized (normalization of a 1-device unit
|
|
||||||
movement on a 400dpi mouse would cause a 2.5 pixel movement). Instead,
|
|
||||||
libinput applies a dpi-dependent acceleration function. At low speeds, a
|
|
||||||
1-device unit movement usually translates into a 1-pixel movements. As the
|
|
||||||
movement speed increases, acceleration is applied - at high speeds a low-dpi
|
|
||||||
device will roughly feel the same as a higher-dpi mouse.
|
|
||||||
|
|
||||||
The reason for the normalization is convenience: a caller can assume that a
|
|
||||||
delta of 1 should result in a movement of 1 pixel on a traditional
|
|
||||||
(low-dpi) screen. On screens with high resolutions, the caller must scale
|
|
||||||
according to the UI scale factors.
|
|
||||||
|
|
||||||
This normalization only applies to accelerated coordinates, unaccelerated
|
|
||||||
coordinates are left in device-units. It is up to the caller to interpret
|
|
||||||
those coordinates correctly.
|
|
||||||
|
|
||||||
.. _motion_normalization_touchpad:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Normalization of touchpad coordinates
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Touchpads may have a different resolution for the horizontal and vertical
|
|
||||||
axis. Interpreting coordinates from the touchpad without taking resolution
|
|
||||||
into account results in uneven motion.
|
|
||||||
|
|
||||||
libinput scales unaccelerated touchpad motion to the resolution of the
|
|
||||||
touchpad's x axis, i.e. the unaccelerated value for the y axis is:
|
|
||||||
``y = (x / resolution_x) * resolution_y``.
|
|
||||||
|
|
||||||
.. _motion_normalization_tablet:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Normalization of tablet coordinates
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
See :ref:`tablet-relative-motion`
|
|
||||||
|
|
||||||
.. _motion_normalization_customization:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Setting custom DPI settings
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Devices usually do not advertise their resolution and libinput relies on
|
|
||||||
the udev property **MOUSE_DPI** for this information. This property is usually
|
|
||||||
set via the
|
|
||||||
`udev hwdb <http://cgit.freedesktop.org/systemd/systemd/tree/hwdb/70-mouse.hwdb>`_.
|
|
||||||
The ``mouse-dpi-tool`` utility provided by
|
|
||||||
`libevdev <https://freedesktop.org/wiki/Software/libevdev/>`_ should be
|
|
||||||
used to measure a device's resolution.
|
|
||||||
|
|
||||||
The format of the property for single-resolution mice is: ::
|
|
||||||
|
|
||||||
MOUSE_DPI=resolution@frequency
|
|
||||||
|
|
||||||
The resolution is in dots per inch, the frequency in Hz.
|
|
||||||
The format of the property for multi-resolution mice may list multiple
|
|
||||||
resolutions and frequencies: ::
|
|
||||||
|
|
||||||
MOUSE_DPI=r1@f1 *r2@f2 r3@f3
|
|
||||||
|
|
||||||
The default frequency must be pre-fixed with an asterisk.
|
|
||||||
|
|
||||||
For example, these two properties are valid: ::
|
|
||||||
|
|
||||||
MOUSE_DPI=800@125
|
|
||||||
MOUSE_DPI=400@125 800@125 *1000@500 5500@500
|
|
||||||
|
|
||||||
The behavior for a malformed property is undefined. If the property is
|
|
||||||
unset, libinput assumes the resolution is 1000dpi.
|
|
||||||
|
|
||||||
Note that HW does not usually provide information about run-time
|
|
||||||
resolution changes, libinput will thus not detect when a resolution
|
|
||||||
changes to the non-default value.
|
|
||||||
|
|
@ -1,227 +0,0 @@
|
||||||
.. _palm_detection:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Palm detection
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
Palm detection tries to identify accidental touches while typing, while
|
|
||||||
using the trackpoint and/or during general use of the touchpad area.
|
|
||||||
|
|
||||||
On most laptops typing on the keyboard generates accidental touches on the
|
|
||||||
touchpad with the palm (usually the area below the thumb). This can lead to
|
|
||||||
cursor jumps or accidental clicks. On large touchpads, the palm may also
|
|
||||||
touch the bottom edges of the touchpad during normal interaction.
|
|
||||||
|
|
||||||
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
|
|
||||||
during typing on a Lenovo T440 happened in the left-most and right-most 5% of
|
|
||||||
the touchpad. The T440 series has one of the largest touchpads, other
|
|
||||||
touchpads are less affected by palm touches.
|
|
||||||
|
|
||||||
libinput has multiple ways of detecting a palm, each of which depends on
|
|
||||||
hardware-specific capabilities.
|
|
||||||
|
|
||||||
- :ref:`palm_tool`
|
|
||||||
- :ref:`palm_pressure`
|
|
||||||
- :ref:`palm_touch_size`
|
|
||||||
- :ref:`palm_exclusion_zones`
|
|
||||||
- :ref:`trackpoint-disabling`
|
|
||||||
- :ref:`disable-while-typing`
|
|
||||||
- :ref:`disable-while-trackpointing`
|
|
||||||
- :ref:`stylus-touch-arbitration`
|
|
||||||
|
|
||||||
Palm detection is always enabled, with the exception of
|
|
||||||
disable-while-typing.
|
|
||||||
|
|
||||||
.. _palm_tool:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Palm detection based on firmware labelling
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Some devices provide palm detection in the firmware, forwarded by the kernel
|
|
||||||
as the ``EV_ABS/ABS_MT_TOOL`` axis with a value of ``MT_TOOL_PALM``
|
|
||||||
(whenever a palm is detected). libinput honors that value and switches that
|
|
||||||
touch to a palm.
|
|
||||||
|
|
||||||
.. _palm_pressure:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Palm detection based on 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
|
|
||||||
that it cannot be triggered by a finger movement. Once a touch is labelled as
|
|
||||||
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
|
|
||||||
pressure changes as the user is typing.
|
|
||||||
|
|
||||||
For some information on how to detect pressure on a touch and debug the
|
|
||||||
pressure ranges, see :ref:`touchpad_pressure`.
|
|
||||||
|
|
||||||
.. _palm_touch_size:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Palm detection based on touch size
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
On touchpads that support the ``ABS_MT_TOUCH_MAJOR`` axes, libinput can perform
|
|
||||||
palm detection based on the size of the touch ellipse. This works similar to
|
|
||||||
the pressure-based palm detection in that a touch is labelled as palm when
|
|
||||||
it exceeds the (device-specific) touch size threshold.
|
|
||||||
|
|
||||||
For some information on how to detect the size of a touch and debug the
|
|
||||||
touch size ranges, see :ref:`touchpad_pressure`.
|
|
||||||
|
|
||||||
.. _palm_exclusion_zones:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Palm exclusion zones
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
libinput enables palm detection on the left, right and top edges of the
|
|
||||||
touchpad. Two exclusion zones are defined on the left and right edge of the
|
|
||||||
touchpad. If a touch starts in the exclusion zone, it is considered a palm
|
|
||||||
and the touch point is ignored. However, for fast cursor movements across
|
|
||||||
the screen, it is common for a finger to start inside an exclusion zone and
|
|
||||||
move rapidly across the touchpad. libinput detects such movements and avoids
|
|
||||||
palm detection on such touch sequences.
|
|
||||||
|
|
||||||
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
|
|
||||||
avoids palm detection on such touch sequences.
|
|
||||||
|
|
||||||
A touch starting in the exclusion zone does not trigger a tap (see
|
|
||||||
:ref:`tapping`).
|
|
||||||
|
|
||||||
In the diagram below, the exclusion zones are painted red.
|
|
||||||
Touch 'A' starts inside the exclusion zone and moves
|
|
||||||
almost vertically. It is considered a palm and ignored for cursor movement,
|
|
||||||
despite moving out of the exclusion zone.
|
|
||||||
|
|
||||||
Touch 'B' starts inside the exclusion zone but moves horizontally out of the
|
|
||||||
zone. It is considered a valid touch and controls the cursor.
|
|
||||||
|
|
||||||
Touch 'C' occurs in the exclusion zone. Despite being a tapping motion, it does
|
|
||||||
not generate an emulated button event.
|
|
||||||
|
|
||||||
.. figure:: palm-detection.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
.. _trackpoint-disabling:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Palm detection during trackpoint use
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
If a device provides a
|
|
||||||
`trackpoint <http://en.wikipedia.org/wiki/Pointing_stick>`_, it is
|
|
||||||
usually located above the touchpad. This increases the likelihood of
|
|
||||||
accidental touches whenever the trackpoint is used.
|
|
||||||
|
|
||||||
libinput disables the touchpad whenever it detects trackpoint activity for a
|
|
||||||
certain timeout until after trackpoint activity stops. Touches generated
|
|
||||||
during this timeout will not move the pointer, and touches started during
|
|
||||||
this timeout will likewise not move the pointer (allowing for a user to rest
|
|
||||||
the palm on the touchpad while using the trackstick).
|
|
||||||
If the touchpad is disabled, the :ref:`top software buttons <t440_support>`
|
|
||||||
remain enabled.
|
|
||||||
|
|
||||||
.. _disable-while-typing:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Disable-while-typing
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
libinput automatically disables the touchpad for a timeout after a key
|
|
||||||
press, a feature traditionally referred to as "disable while typing" and
|
|
||||||
previously available through the
|
|
||||||
`syndaemon(1) <http://linux.die.net/man/1/syndaemon>`_ command. libinput does
|
|
||||||
not require an external command and the feature is currently enabled for all
|
|
||||||
touchpads but will be reduced in the future to only apply to touchpads where
|
|
||||||
finger width or pressure data is unreliable.
|
|
||||||
|
|
||||||
Notable behaviors of libinput's disable-while-typing feature:
|
|
||||||
|
|
||||||
- Two different timeouts are used, after a single key press the timeout is
|
|
||||||
short to ensure responsiveness. After multiple key events, the timeout is
|
|
||||||
longer to avoid accidental pointer manipulation while typing.
|
|
||||||
- Some keys do not trigger the timeout, specifically some modifier keys
|
|
||||||
(Ctrl, Alt, Shift, and Fn). Actions such as Ctrl + click thus stay
|
|
||||||
responsive.
|
|
||||||
- Touches started while typing do not control the cursor even after typing
|
|
||||||
has stopped, it is thus possible to rest the palm on the touchpad while
|
|
||||||
typing.
|
|
||||||
- Physical buttons work even while the touchpad is disabled. This includes
|
|
||||||
:ref:`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
|
|
||||||
**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
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
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
|
|
||||||
hand may touch the surface and trigger touches. As the user is currently
|
|
||||||
interacting with the stylus, these touches would interfere with the correct
|
|
||||||
working of the stylus.
|
|
||||||
|
|
||||||
libinput employs a method similar to :ref:`disable-while-typing` to detect
|
|
||||||
these touches and disables the touchpad accordingly.
|
|
||||||
|
|
||||||
.. _thumb-detection:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Thumb detection
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Many users rest their thumb on the touchpad while using the index finger to
|
|
||||||
move the finger around. For clicks, often the thumb is used rather than the
|
|
||||||
finger. The thumb should otherwise be ignored as a touch, i.e. it should not
|
|
||||||
count towards :ref:`clickfinger` and it should not cause a single-finger
|
|
||||||
movement to trigger :ref:`twofinger_scrolling`.
|
|
||||||
|
|
||||||
libinput uses two triggers for thumb detection: pressure and
|
|
||||||
location. A touch exceeding a pressure threshold is considered a thumb if it
|
|
||||||
is within the thumb detection zone.
|
|
||||||
|
|
||||||
.. note:: "Pressure" on touchpads is synonymous with "contact area." A large touch
|
|
||||||
surface area has a higher pressure and thus hints at a thumb or palm
|
|
||||||
touching the surface.
|
|
||||||
|
|
||||||
Pressure readings are unreliable at the far bottom of the touchpad as a
|
|
||||||
thumb hanging mostly off the touchpad will have a small surface area.
|
|
||||||
libinput has a definitive thumb zone where any touch is considered a resting
|
|
||||||
thumb.
|
|
||||||
|
|
||||||
.. 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 labelled as
|
|
||||||
thumb if it remains in that area for a time without moving outside.
|
|
||||||
|
|
@ -1,296 +0,0 @@
|
||||||
.. _pointer-acceleration:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Pointer acceleration
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
libinput uses device-specific pointer acceleration methods, with the default
|
|
||||||
being the :ref:`ptraccel-linear`. The methods share common properties, such as
|
|
||||||
:ref:`ptraccel-velocity`.
|
|
||||||
|
|
||||||
This page explains the high-level concepts used in the code. It aims to
|
|
||||||
provide an overview for developers and is not necessarily useful for
|
|
||||||
users.
|
|
||||||
|
|
||||||
.. _ptraccel-profiles:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Pointer acceleration profiles
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The profile decides the general method of pointer acceleration.
|
|
||||||
libinput currently supports three profiles: **"adaptive"**, **"flat"** and
|
|
||||||
**"custom"**.
|
|
||||||
|
|
||||||
- The **adaptive** profile is the default profile for all devices and takes the
|
|
||||||
current speed of the device into account when deciding on acceleration.
|
|
||||||
- The **flat** profile is simply a constant factor applied to all device deltas,
|
|
||||||
regardless of the speed of motion (see :ref:`ptraccel-profile-flat`).
|
|
||||||
- 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:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Velocity calculation
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The device's speed of movement is measured across multiple input events
|
|
||||||
through so-called "trackers". Each event prepends a tracker item, each
|
|
||||||
subsequent tracker contains the delta of that item to the current position,
|
|
||||||
the timestamp of the event that created it and the cardinal direction of the
|
|
||||||
movement at the time. If a device moves into the same direction, the
|
|
||||||
velocity is calculated across multiple trackers. For example, if a device
|
|
||||||
moves steadily for 10 events to the left, the velocity is calculated across
|
|
||||||
all 10 events.
|
|
||||||
|
|
||||||
Whenever the movement changes direction or significantly changes speed, the
|
|
||||||
velocity is calculated from the direction/speed change only. For example, if
|
|
||||||
a device moves steadily for 8 events to the left and then 2 events to the
|
|
||||||
right, the velocity is only that of the last 2 events.
|
|
||||||
|
|
||||||
An extra time limit prevents events that are too old to factor into the
|
|
||||||
velocity calculation. For example, if a device moves steadily for 5 events
|
|
||||||
to the left, then pauses, then moves again for 5 events to the left, only
|
|
||||||
the last 5 events are used for velocity calculation.
|
|
||||||
|
|
||||||
The velocity is then used to calculate the acceleration factor
|
|
||||||
|
|
||||||
.. _ptraccel-factor:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Acceleration factor
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The acceleration factor is the final outcome of the pointer acceleration
|
|
||||||
calculations. It is a unitless factor that is applied to the current delta,
|
|
||||||
a factor of 2 doubles the delta (i.e. speeds up the movement), a factor of
|
|
||||||
less than 1 reduces the delta (i.e. slows the movement).
|
|
||||||
|
|
||||||
Any factor less than 1 requires the user to move the device further to move
|
|
||||||
the visible pointer. This is called deceleration and enables high precision
|
|
||||||
target selection through subpixel movements. libinput's current maximum
|
|
||||||
deceleration factor is 0.3 (i.e. slow down to 30% of the pointer speed).
|
|
||||||
|
|
||||||
A factor higher than 1 moves the pointer further than the physical device
|
|
||||||
moves. This is acceleration and allows a user to cross the screen quickly
|
|
||||||
but effectively skips pixels. libinput's current maximum acceleration factor
|
|
||||||
is 3.5.
|
|
||||||
|
|
||||||
.. _ptraccel-linear:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Linear pointer acceleration
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The linear pointer acceleration method is the default for most pointer
|
|
||||||
devices. It provides deceleration at very slow movements, a 1:1 mapping for
|
|
||||||
regular movements and a linear increase to the maximum acceleration factor
|
|
||||||
for fast movements.
|
|
||||||
|
|
||||||
Linear pointer acceleration applies to devices with above 1000dpi resolution
|
|
||||||
and after :ref:`motion_normalization` is applied.
|
|
||||||
|
|
||||||
.. figure:: ptraccel-linear.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
Linear pointer acceleration
|
|
||||||
|
|
||||||
The image above shows the linear pointer acceleration settings at various
|
|
||||||
speeds. The line for 0.0 is the default acceleration curve, speed settings
|
|
||||||
above 0.0 accelerate sooner, faster and to a higher maximum acceleration.
|
|
||||||
Speed settings below 0 delay when acceleration kicks in, how soon the
|
|
||||||
maximum acceleration is reached and the maximum acceleration factor.
|
|
||||||
|
|
||||||
Extremely low speed settings provide no acceleration and additionally
|
|
||||||
decelerate all movement by a constant factor.
|
|
||||||
|
|
||||||
.. _ptraccel-low-dpi:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Pointer acceleration for low-dpi devices
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Low-dpi devices are those with a physical resolution of less than 1000 dots
|
|
||||||
per inch (dpi). The pointer acceleration is adjusted to provide roughly the
|
|
||||||
same feel for all devices at normal to high speeds. At slow speeds, the
|
|
||||||
pointer acceleration works on device-units rather than normalized
|
|
||||||
coordinates (see :ref:`motion_normalization`).
|
|
||||||
|
|
||||||
.. figure:: ptraccel-low-dpi.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
Pointer acceleration for low-dpi devices
|
|
||||||
|
|
||||||
The image above shows the default pointer acceleration curve for a speed of
|
|
||||||
0.0 at different DPI settings. A device with low DPI has the acceleration
|
|
||||||
applied sooner and with a stronger acceleration factor.
|
|
||||||
|
|
||||||
.. _ptraccel-touchpad:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Pointer acceleration on touchpads
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Touchpad pointer acceleration uses the same approach as the
|
|
||||||
:ref:`ptraccel-linear` profile, with a constant deceleration factor applied. The
|
|
||||||
user expectation of how much a pointer should move in response to finger
|
|
||||||
movement is different to that of a mouse device, hence the constant
|
|
||||||
deceleration factor.
|
|
||||||
|
|
||||||
.. figure:: ptraccel-touchpad.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
Pointer acceleration curve for touchpads
|
|
||||||
|
|
||||||
The image above shows the touchpad acceleration profile in comparison to the
|
|
||||||
:ref:`ptraccel-linear`. The shape of the curve is identical but vertically squashed.
|
|
||||||
|
|
||||||
.. _ptraccel-trackpoint:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Pointer acceleration on trackpoints
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The main difference between trackpoint hardware and mice or touchpads is
|
|
||||||
that trackpoint speed is a function of pressure rather than moving speed.
|
|
||||||
But trackpoint hardware is quite varied in how it reacts to user pressure
|
|
||||||
and unlike other devices it cannot easily be normalized for physical
|
|
||||||
properties. Measuring pressure objectively across a variety of hardware is
|
|
||||||
nontrivial. See :ref:`trackpoints` for more details.
|
|
||||||
|
|
||||||
The deltas for trackpoints are converted units/ms but there is no common
|
|
||||||
physical reference point for a unit. Thus, the same pressure on different
|
|
||||||
trackpoints will generate different speeds and thus different acceleration
|
|
||||||
behaviors. Additionally, some trackpoints provide the ability to adjust the
|
|
||||||
sensitivity in hardware by modifying a sysfs file on the serio node. A
|
|
||||||
higher sensitivity results in higher deltas, thus changing the definition of
|
|
||||||
what is a unit again.
|
|
||||||
|
|
||||||
libinput attempts to normalize unit data to the best of its abilities, see
|
|
||||||
:ref:`trackpoint_multiplier`. Beyond this, it is not possible to have
|
|
||||||
consistent behavior across different trackpoint devices.
|
|
||||||
|
|
||||||
.. figure:: ptraccel-trackpoint.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
Pointer acceleration curves for trackpoints
|
|
||||||
|
|
||||||
The image above shows the trackpoint acceleration profile for the speed in
|
|
||||||
units/ms.
|
|
||||||
|
|
||||||
.. _ptraccel-profile-flat:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
The flat pointer acceleration profile
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
In a flat profile, the acceleration factor is constant regardless of the
|
|
||||||
velocity of the pointer and each delta (dx, dy) results in an accelerated delta
|
|
||||||
(dx * factor, dy * factor). This provides 1:1 movement between the device
|
|
||||||
and the pointer on-screen.
|
|
||||||
|
|
||||||
.. _ptraccel-tablet:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Pointer acceleration on tablets
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Pointer acceleration for relative motion on tablet devices is a flat
|
|
||||||
acceleration, with the speed setting slowing down or speeding up the pointer
|
|
||||||
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.
|
|
||||||
|
|
@ -1,395 +0,0 @@
|
||||||
.. _reporting_bugs:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Reporting bugs
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
A new bug can be filed here:
|
|
||||||
https://gitlab.freedesktop.org/libinput/libinput/issues/new
|
|
||||||
|
|
||||||
.. hint:: libinput has lots of users but very few developers. It is in your
|
|
||||||
own interest to follow the steps here precisely to ensure your bug can be
|
|
||||||
dealt with efficiently.
|
|
||||||
|
|
||||||
When reporting bugs against libinput, you will need:
|
|
||||||
|
|
||||||
- a reliable :ref:`reproducer <reporting_bugs_reproducer>` for the bug
|
|
||||||
- a :ref:`recording <libinput-record>` of the device while the bug is reproduced
|
|
||||||
- device-specific information, see
|
|
||||||
|
|
||||||
- :ref:`reporting_bugs_touchpad`
|
|
||||||
- :ref:`reporting_bugs_mouse`
|
|
||||||
- :ref:`reporting_bugs_keyboard`
|
|
||||||
- :ref:`reporting_bugs_trackpoint`
|
|
||||||
- :ref:`reporting_bugs_other`
|
|
||||||
|
|
||||||
- the :ref:`libinput version <reporting_bugs_version>` you are on.
|
|
||||||
- the :ref:`configuration options <reporting_bugs_options>` you have set
|
|
||||||
- a `gitlab account <https://gitlab.freedesktop.org/users/sign_in>`_
|
|
||||||
|
|
||||||
Stay technical, on-topic, and keep the description concise.
|
|
||||||
|
|
||||||
.. _reporting_bugs_version:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Obtaining the libinput version
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
If your libinput version is older than the current stable branch, please try
|
|
||||||
the latest version. If you run a distribution-provided
|
|
||||||
libinput, use the package manager to get the **full** package name and
|
|
||||||
version of libinput, e.g.
|
|
||||||
|
|
||||||
- ``rpm -q libinput``
|
|
||||||
- ``dpkg -s libinput10``
|
|
||||||
|
|
||||||
If you run a self-compiled version of libinput provide the git commit you
|
|
||||||
have built or the tarball name.
|
|
||||||
|
|
||||||
As a last resort, use ``libinput --version``
|
|
||||||
|
|
||||||
.. _reporting_bugs_reproducer:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Reproducing bugs
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Try to identify the bug by reproducing it reliably. Bugs without a
|
|
||||||
reliable reproducer will have lowest priority. The more specific a bug
|
|
||||||
description and reproducer is, the easier it is to fix.
|
|
||||||
|
|
||||||
Try to replicate the series of events that lead to the bug being triggered.
|
|
||||||
Narrow it down until you have a reliable sequence that can trigger the bug.
|
|
||||||
For the vast majority of bugs you should not take longer than 5 seconds or
|
|
||||||
three interactions (clicks, touches, taps, ...) with the device to
|
|
||||||
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
|
|
||||||
tool::
|
|
||||||
|
|
||||||
$> libinput debug-events --verbose
|
|
||||||
|
|
||||||
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
|
|
||||||
on the commandline, see the :ref:`libinput-debug-events`
|
|
||||||
man page. Use the ``--verbose`` flag to get more information about how
|
|
||||||
libinput processes events.
|
|
||||||
|
|
||||||
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
|
|
||||||
libinput.
|
|
||||||
|
|
||||||
.. _reporting_bugs_options:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
libinput configuration settings
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
libinput has a number of device-specific default configuration settings that
|
|
||||||
may differ from the ones your desktop environment picks by default. You may
|
|
||||||
have changed some options in a settings panel or in an the xorg.conf snippet
|
|
||||||
yourself.
|
|
||||||
|
|
||||||
You must provide these options in the bug report, otherwise a developer
|
|
||||||
reproducing the issue may not be able to do so.
|
|
||||||
|
|
||||||
If you are on X11, the current settings can be can be obtained with
|
|
||||||
``xinput list-props "your device name"``. Use ``xinput list`` to
|
|
||||||
obtain the device name.
|
|
||||||
|
|
||||||
If you are on Wayland, provide a manual summary of the options you have
|
|
||||||
changed from the default (e.g. "I enabled tap-to-click").
|
|
||||||
|
|
||||||
.. _reporting_bugs_touchpad:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Reporting touchpad bugs
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
When you file a bug, please attach the following information:
|
|
||||||
|
|
||||||
- a virtual description of your input device, see :ref:`libinput-record`.
|
|
||||||
This is the most important piece of information, do not forget it!
|
|
||||||
- the output from udevadm info, see :ref:`udev_info`.
|
|
||||||
- the vendor model number of your laptop (e.g. "Lenovo Thinkpad T440s")
|
|
||||||
- and the content of ``/sys/class/dmi/id/modalias``.
|
|
||||||
- run ``libinput measure touchpad-size`` tool (see :ref:`absolute_coordinate_ranges_fix`)
|
|
||||||
and verify that the ranges and sizes it prints match the touchpad (up to 5mm
|
|
||||||
difference is ok)
|
|
||||||
|
|
||||||
If you are reporting a bug related to button event generation:
|
|
||||||
|
|
||||||
- does your touchpad have (separate) physical hardware buttons or is the
|
|
||||||
whole touchpad clickable?
|
|
||||||
- Are you using software buttons or clickfinger? See :ref:`clickpad_softbuttons`.
|
|
||||||
- Do you have :ref:`tapping` enabled?
|
|
||||||
|
|
||||||
.. _reporting_bugs_mouse:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Reporting mouse bugs
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
When you file a bug, please attach the following information:
|
|
||||||
|
|
||||||
- a virtual description of your input device, see :ref:`libinput-record`.
|
|
||||||
This is the most important piece of information, do not forget it!
|
|
||||||
- the vendor model number of the device (e.g. "Logitech M325")
|
|
||||||
- the output from udevadm info, see :ref:`udev_info`.
|
|
||||||
|
|
||||||
If the bug is related to the :ref:`speed of the mouse <motion_normalization_customization>`:
|
|
||||||
|
|
||||||
- the resolution of the mouse as specified by the vendor (in DPI)
|
|
||||||
- the output of the ``mouse-dpi-tool`` (provided by libevdev)
|
|
||||||
|
|
||||||
.. _reporting_bugs_keyboard:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Reporting keyboard bugs
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Is your bug related to a keyboard layout? libinput does not handle keyboard
|
|
||||||
layouts and merely forwards the physical key events. File the bug with your
|
|
||||||
desktop environment instead (e.g. GNOME, KDE, ...), that's most likely where
|
|
||||||
the issue is.
|
|
||||||
|
|
||||||
When you file a bug, please attach the following information:
|
|
||||||
|
|
||||||
- a virtual description of your input device, see :ref:`libinput-record`.
|
|
||||||
This is the most important piece of information, do not forget it!
|
|
||||||
|
|
||||||
.. _reporting_bugs_trackpoint:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Reporting trackpoint bugs
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
When you file a bug, please attach the following information:
|
|
||||||
|
|
||||||
- a virtual description of your input device, see :ref:`libinput-record`.
|
|
||||||
This is the most important piece of information, do not forget it!
|
|
||||||
- the vendor model number of the device (e.g. "Logitech M325")
|
|
||||||
- the output from udevadm info, see :ref:`udev_info`.
|
|
||||||
- the sensitivity of the trackpoint if it exists (adjust the event node number as needed): ::
|
|
||||||
|
|
||||||
$ cat /sys/class/input/event17/device/device/sensitivity
|
|
||||||
|
|
||||||
|
|
||||||
.. _reporting_bugs_other:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
All other devices
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
When you file a bug, please attach the following information:
|
|
||||||
|
|
||||||
- a virtual description of your input device, see :ref:`libinput-record`.
|
|
||||||
This is the most important piece of information, do not forget it!
|
|
||||||
- the vendor model number of the device (e.g. "Sony PlayStation3 controller")
|
|
||||||
|
|
||||||
.. _udev_info:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
udev information for the device
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
In many cases, we require the udev properties assigned to the device to
|
|
||||||
verify whether device-specific quirks were applied. This can be obtained
|
|
||||||
with ``udevadm info /sys/class/input/eventX``, with the correct event
|
|
||||||
node for your device. An example output is below: ::
|
|
||||||
|
|
||||||
$ udevadm info /sys/class/input/event4
|
|
||||||
P: /devices/platform/i8042/serio1/input/input5/event4
|
|
||||||
N: input/event4
|
|
||||||
E: DEVNAME=/dev/input/event4
|
|
||||||
E: DEVPATH=/devices/platform/i8042/serio1/input/input5/event4
|
|
||||||
E: EVDEV_ABS_00=::41
|
|
||||||
E: EVDEV_ABS_01=::37
|
|
||||||
E: EVDEV_ABS_35=::41
|
|
||||||
E: EVDEV_ABS_36=::37
|
|
||||||
E: ID_INPUT=1
|
|
||||||
E: ID_INPUT_HEIGHT_MM=66
|
|
||||||
E: ID_INPUT_TOUCHPAD=1
|
|
||||||
E: ID_INPUT_WIDTH_MM=97
|
|
||||||
E: MAJOR=13
|
|
||||||
E: MINOR=68
|
|
||||||
E: SUBSYSTEM=input
|
|
||||||
E: USEC_INITIALIZED=5463031
|
|
||||||
|
|
||||||
|
|
||||||
.. _evemu:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Recording devices with evemu
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
.. warning:: Where available, the :ref:`libinput-record` tools should be used instead
|
|
||||||
of evemu
|
|
||||||
|
|
||||||
`evemu-record <https://www.freedesktop.org/wiki/Evemu/>`_ records the
|
|
||||||
device capabilities together with the event stream from the kernel. On our
|
|
||||||
side, this allows us to recreate a virtual device identical to your device
|
|
||||||
and re-play the event sequence, hopefully triggering the same bug.
|
|
||||||
|
|
||||||
evemu-record takes a ``/dev/input/eventX`` event node, but without arguments
|
|
||||||
it will simply show the list of devices and let you select: ::
|
|
||||||
|
|
||||||
$ sudo evemu-record > scroll.evemu
|
|
||||||
Available devices:
|
|
||||||
/dev/input/event0: Lid Switch
|
|
||||||
/dev/input/event1: Sleep Button
|
|
||||||
/dev/input/event2: Power Button
|
|
||||||
/dev/input/event3: AT Translated Set 2 keyboard
|
|
||||||
/dev/input/event4: SynPS/2 Synaptics TouchPad
|
|
||||||
/dev/input/event5: Video Bus
|
|
||||||
/dev/input/event6: ELAN Touchscreen
|
|
||||||
/dev/input/event10: ThinkPad Extra Buttons
|
|
||||||
/dev/input/event11: HDA Intel HDMI HDMI/DP,pcm=3
|
|
||||||
/dev/input/event12: HDA Intel HDMI HDMI/DP,pcm=7
|
|
||||||
/dev/input/event13: HDA Intel HDMI HDMI/DP,pcm=8
|
|
||||||
/dev/input/event14: HDA Intel PCH Dock Mic
|
|
||||||
/dev/input/event15: HDA Intel PCH Mic
|
|
||||||
/dev/input/event16: HDA Intel PCH Dock Headphone
|
|
||||||
/dev/input/event17: HDA Intel PCH Headphone
|
|
||||||
/dev/input/event18: Integrated Camera
|
|
||||||
/dev/input/event19: TPPS/2 IBM TrackPoint
|
|
||||||
Select the device event number [0-19]:
|
|
||||||
|
|
||||||
|
|
||||||
Select the device that triggers the issue, then reproduce the bug and Ctrl+C
|
|
||||||
the process. The resulting recording, ("scroll.evemu" in this example) will
|
|
||||||
contain the sequence required to reproduce the bug. If the bug fails to
|
|
||||||
reproduce during recording, simply Ctrl+C and restart evemu-record.
|
|
||||||
Always start the recording from a neutral state, i.e. without any buttons or
|
|
||||||
keys down, with the position of the device in the neutral position, without
|
|
||||||
touching the screen/touchpad.
|
|
||||||
|
|
||||||
.. note:: The longer the recording, the harder it is to identify the event
|
|
||||||
sequence triggering the bug. Please keep the event sequence as short
|
|
||||||
as possible.
|
|
||||||
|
|
||||||
To verify that the recording contains the bug, you can replay it on your
|
|
||||||
device. For example, to replay the sequence recorded in the example above: ::
|
|
||||||
|
|
||||||
$ sudo evemu-play /dev/input/event4 < scroll.evemu
|
|
||||||
|
|
||||||
|
|
||||||
If the bug is triggered by replaying on your device, attach the recording to
|
|
||||||
the bug report.
|
|
||||||
|
|
||||||
libinput does not affect the evemu recording. libinput and evemu talk
|
|
||||||
directly to the kernel's device nodes. An evemu recording is not
|
|
||||||
influenced by the libinput version or whether a libinput context is
|
|
||||||
currently active.
|
|
||||||
|
|
||||||
.. graphviz:: evemu.gv
|
|
||||||
|
|
||||||
.. _fixed_bugs:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
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
|
|
||||||
master, the bug is considered fixed and the gitlab issue will be closed
|
|
||||||
accordingly.
|
|
||||||
|
|
||||||
Of course, unless you actually run git master, the bug will continue to
|
|
||||||
affect you on your local machine. You are most likely running the
|
|
||||||
distribution's package and you will need to wait until the distribution has
|
|
||||||
updated its package accordingly.
|
|
||||||
|
|
||||||
.. warning:: Do not re-open a bug just because it hasn't trickled down to
|
|
||||||
your distribution's package version yet.
|
|
||||||
|
|
||||||
Whether the bug fix ends up in your distribution depends on a number of
|
|
||||||
things. Any given bug fix **may** be cherry-picked into the current stable
|
|
||||||
branch, depending on its severity, impact, and likelihood to cause
|
|
||||||
regressions. Once cherry-picked it will land in the next stable branch
|
|
||||||
release. These are usually a few weeks apart.
|
|
||||||
|
|
||||||
.. warning:: Do not re-open a bug because it wasn't picked into a stable branch
|
|
||||||
release or because your distribution didn't update to the latest stable
|
|
||||||
branch release.
|
|
||||||
|
|
||||||
Stable branches are usually discontinued when the next release comes out.
|
|
||||||
|
|
||||||
Your distribution may pick a patch up immediately and ship the fix
|
|
||||||
even before the next stable branch update is released. For example, Fedora
|
|
||||||
does this frequently.
|
|
||||||
|
|
||||||
.. hint:: If a bug needs to be fixed urgently, file a bug in your
|
|
||||||
distribution's bug tracker.
|
|
||||||
|
|
||||||
Patches on git master will end up in the next libinput release. Once your
|
|
||||||
distribution updates to that release, your local libinput version will
|
|
||||||
contain the fix.
|
|
||||||
|
|
||||||
.. warning:: Do not re-open a bug because your distribution didn't update to
|
|
||||||
the release.
|
|
||||||
|
|
||||||
You can always run libinput from git master (see :ref:`building_libinput`).
|
|
||||||
Even while in development, libinput is very stable so this option isn't as
|
|
||||||
scary as it may sounds.
|
|
||||||
|
|
||||||
.. _reporting_bugs_reopen:
|
|
||||||
|
|
||||||
..............................................................................
|
|
||||||
When is it ok to re-open a fixed bug?
|
|
||||||
..............................................................................
|
|
||||||
|
|
||||||
Any time the bug was considered fixed but it turns out that the fix is
|
|
||||||
insufficient and/or causes a regression.
|
|
||||||
|
|
||||||
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
|
|
||||||
to improve tapping breaks two-finger scrolling behavior, you should file a
|
|
||||||
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.
|
|
||||||
|
|
@ -1,178 +0,0 @@
|
||||||
.. _scrolling:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Scrolling
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
libinput supports three different types of scrolling methods:
|
|
||||||
:ref:`twofinger_scrolling`, :ref:`edge_scrolling` and
|
|
||||||
:ref:`button_scrolling`. Some devices support multiple methods, though only
|
|
||||||
one can be enabled at a time. As a general overview:
|
|
||||||
|
|
||||||
- touchpad devices with physical buttons below the touchpad support edge and
|
|
||||||
two-finger scrolling
|
|
||||||
- touchpad devices without physical buttons (:ref:`ClickPads <clickpad_softbuttons>`)
|
|
||||||
support two-finger scrolling only
|
|
||||||
- pointing sticks provide on-button scrolling by default
|
|
||||||
- mice and other pointing devices support on-button scrolling but it is not
|
|
||||||
enabled by default
|
|
||||||
|
|
||||||
A device may differ from the above based on its capabilities. See
|
|
||||||
**libinput_device_config_scroll_set_method()** for documentation on how to
|
|
||||||
switch methods and **libinput_device_config_scroll_get_methods()** for
|
|
||||||
documentation on how to query a device for available scroll methods.
|
|
||||||
|
|
||||||
.. _horizontal_scrolling:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Horizontal scrolling
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Scroll movements provide vertical and horizontal directions, each
|
|
||||||
scroll event contains both directions where applicable, see
|
|
||||||
**libinput_event_pointer_get_axis_value()**. libinput does not provide separate
|
|
||||||
toggles to enable or disable horizontal scrolling. Instead, horizontal
|
|
||||||
scrolling is always enabled. This is intentional, libinput does not have
|
|
||||||
enough context to know when horizontal scrolling is appropriate for a given
|
|
||||||
widget. The task of filtering horizontal movements is up to the caller.
|
|
||||||
|
|
||||||
.. _twofinger_scrolling:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Two-finger scrolling
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The default on two-finger capable touchpads (almost all modern touchpads are
|
|
||||||
capable of detecting two fingers). Scrolling is triggered by two fingers
|
|
||||||
being placed on the surface of the touchpad, then moving those fingers
|
|
||||||
vertically or horizontally.
|
|
||||||
|
|
||||||
.. figure:: twofinger-scrolling.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
Vertical and horizontal two-finger scrolling
|
|
||||||
|
|
||||||
For scrolling to trigger, a built-in distance threshold has to be met, but once
|
|
||||||
engaged, any movement will scroll. In other words: to start scrolling, a
|
|
||||||
sufficiently large movement is required; once scrolling, tiny amounts of
|
|
||||||
movements will translate into tiny scroll movements.
|
|
||||||
Scrolling in both directions at once is possible by meeting the required
|
|
||||||
distance thresholds to enable each direction separately.
|
|
||||||
|
|
||||||
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
|
|
||||||
reasonable precision. Unfortunately, some so-called "semi-mt" touchpads can
|
|
||||||
only track the bounding box of the two fingers rather than the actual
|
|
||||||
position of each finger. In addition, that bounding box usually suffers from
|
|
||||||
a low resolution, causing jumpy movement during two-finger scrolling.
|
|
||||||
libinput does not provide two-finger scrolling on those touchpads.
|
|
||||||
|
|
||||||
.. _edge_scrolling:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Edge scrolling
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
On some touchpads, edge scrolling is available, triggered by moving a single
|
|
||||||
finger along the right edge (vertical scroll) or bottom edge (horizontal
|
|
||||||
scroll).
|
|
||||||
|
|
||||||
.. figure:: edge-scrolling.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
Vertical and horizontal edge scrolling
|
|
||||||
|
|
||||||
Due to the layout of the edges, diagonal scrolling is not possible. The
|
|
||||||
behavior of edge scrolling using both edges at the same time is undefined.
|
|
||||||
|
|
||||||
Edge scrolling overlaps with :ref:`clickpad_softbuttons`. A physical click on
|
|
||||||
a clickpad ends scrolling.
|
|
||||||
|
|
||||||
.. _button_scrolling:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
On-Button scrolling
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
On-button scrolling converts the motion of a device into scroll events while
|
|
||||||
a designated button is held down. For example, Lenovo devices provide a
|
|
||||||
`pointing stick <http://en.wikipedia.org/wiki/Pointing_stick>`_ that emulates
|
|
||||||
scroll events when the trackstick's middle mouse button is held down.
|
|
||||||
|
|
||||||
.. note:: On-button scrolling is enabled by default for pointing sticks. This
|
|
||||||
prevents middle-button dragging; all motion events while the middle
|
|
||||||
button is down are converted to scroll events.
|
|
||||||
|
|
||||||
.. figure:: button-scrolling.svg
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
Button scrolling
|
|
||||||
|
|
||||||
The button may be changed with
|
|
||||||
**libinput_device_config_scroll_set_button()** but must be on the same device as
|
|
||||||
the motion events. Cross-device scrolling is not supported but
|
|
||||||
for one exception: libinput's :ref:`t440_support` enables the use of the middle
|
|
||||||
button for button scrolling (even when the touchpad is disabled).
|
|
||||||
|
|
||||||
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
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
.. 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
|
|
||||||
source can be obtained with the **libinput_event_pointer_get_axis_source()**
|
|
||||||
function and is one of **wheel**, **finger**, or **continuous**. The source
|
|
||||||
information lets a caller decide when to implement kinetic scrolling.
|
|
||||||
Usually, a caller will process events of source wheel as they come in.
|
|
||||||
For events of source finger a caller should calculate the velocity of the
|
|
||||||
scroll motion and upon finger release start a kinetic scrolling motion (i.e.
|
|
||||||
continue executing a scroll according to some friction factor).
|
|
||||||
libinput expects the caller to be in charge of widget handling, the source
|
|
||||||
information is thus enough to provide kinetic scrolling on a per-widget
|
|
||||||
basis. A caller should cancel kinetic scrolling when the pointer leaves the
|
|
||||||
current widget or when a key is pressed.
|
|
||||||
|
|
||||||
See the **libinput_event_pointer_get_axis_source()** for details on the
|
|
||||||
behavior of each scroll source.
|
|
||||||
|
|
||||||
See also http://who-t.blogspot.com.au/2015/03/libinput-scroll-sources.html
|
|
||||||
|
|
||||||
.. _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.
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
.. _seats:
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
Seats
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
Each device in libinput is assigned to one seat.
|
|
||||||
A seat has two identifiers, the physical name and the logical name. The
|
|
||||||
physical name is summarized as the list of devices a process on the same
|
|
||||||
physical seat has access to. The logical seat name is the seat name for a
|
|
||||||
logical group of devices. A compositor may use that to create additional
|
|
||||||
seats as independent device sets. Alternatively, a compositor may limit
|
|
||||||
itself to a single logical seat, leaving a second compositor to manage
|
|
||||||
devices on the other logical seats.
|
|
||||||
|
|
||||||
.. _seats_overview:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Overview
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Below is an illustration of how physical seats and logical seats interact:
|
|
||||||
|
|
||||||
.. graphviz:: seats-sketch.gv
|
|
||||||
|
|
||||||
The devices "Foo", "Bar" and "Spam" share the same physical seat and are
|
|
||||||
thus available in the same libinput context. Only "Foo" and "Bar" share the
|
|
||||||
same logical seat. The device "Egg" is not available in the libinput context
|
|
||||||
associated with the physical seat 0.
|
|
||||||
|
|
||||||
The above graph is for illustration purposes only. In libinput, a struct
|
|
||||||
**libinput_seat** comprises both physical seat and logical seat. From a
|
|
||||||
caller's point-of-view the above device layout is presented as:
|
|
||||||
|
|
||||||
.. graphviz:: seats-sketch-libinput.gv
|
|
||||||
|
|
||||||
Thus, devices "Foo" and "Bar" both reference the same struct
|
|
||||||
**libinput_seat**, all other devices reference their own respective seats.
|
|
||||||
|
|
||||||
.. _seats_and_features:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
The effect of seat assignment
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
A logical set is interpreted as a group of devices that usually belong to a
|
|
||||||
single user that interacts with a computer. Thus, the devices are
|
|
||||||
semantically related. This means for devices within the same logical seat:
|
|
||||||
|
|
||||||
- if the same button is pressed on different devices, the button should only
|
|
||||||
be considered logically pressed once.
|
|
||||||
- if the same button is released on one device, the button should be
|
|
||||||
considered logically down if still down on another device.
|
|
||||||
- if two different buttons or keys are pressed on different devices, the
|
|
||||||
logical state is that of both buttons/keys down.
|
|
||||||
- if a button is pressed on one device and another device moves, this should
|
|
||||||
count as dragging.
|
|
||||||
- if two touches are down on different devices, the logical state is that of
|
|
||||||
two touches down.
|
|
||||||
|
|
||||||
libinput provides functions to aid with the above:
|
|
||||||
**libinput_event_pointer_get_seat_button_count()**,
|
|
||||||
**libinput_event_keyboard_get_seat_key_count()**, and
|
|
||||||
**libinput_event_touch_get_seat_slot()**.
|
|
||||||
|
|
||||||
Internally, libinput counts devices within the same logical seat as related.
|
|
||||||
Cross-device features only activate if all required devices are in the same
|
|
||||||
logical seat. For example, libinput will only activate the top software
|
|
||||||
buttons (see :ref:`t440_support`) if both trackstick and touchpad are assigned
|
|
||||||
to the same logical seat.
|
|
||||||
|
|
||||||
|
|
||||||
.. _changing_seats:
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
Changing seats
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
A device may change the logical seat it is assigned to at runtime with
|
|
||||||
**libinput_device_set_seat_logical_name()**. The physical seat is immutable and
|
|
||||||
may not be changed.
|
|
||||||
|
|
||||||
Changing the logical seat for a device is equivalent to unplugging the
|
|
||||||
device and plugging it back in with the new logical seat. No device state
|
|
||||||
carries over across a logical seat change.
|
|
||||||
|
Before Width: | Height: | Size: 105 KiB |
|
|
@ -1,292 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
version="1.1"
|
|
||||||
width="393"
|
|
||||||
height="438.42642"
|
|
||||||
id="svg2">
|
|
||||||
<defs
|
|
||||||
id="defs4">
|
|
||||||
<marker
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
id="Arrow1Lend"
|
|
||||||
style="overflow:visible">
|
|
||||||
<path
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
|
||||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
|
||||||
id="path3710"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
id="Arrow1Lstart"
|
|
||||||
style="overflow:visible">
|
|
||||||
<path
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
|
||||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
|
||||||
id="path3707"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
id="Arrow1Lstart-4"
|
|
||||||
style="overflow:visible">
|
|
||||||
<path
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
|
||||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
|
||||||
id="path3707-7"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
id="Arrow1Lend-2"
|
|
||||||
style="overflow:visible">
|
|
||||||
<path
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
|
||||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
|
||||||
id="path3710-3"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
|
||||||
</marker>
|
|
||||||
</defs>
|
|
||||||
<g
|
|
||||||
transform="translate(-34.54288,-505.04248)"
|
|
||||||
id="layer3"
|
|
||||||
style="display:inline">
|
|
||||||
<rect
|
|
||||||
width="58"
|
|
||||||
height="58"
|
|
||||||
x="386"
|
|
||||||
y="65.208893"
|
|
||||||
transform="translate(-343.95712,527.33359)"
|
|
||||||
id="rect11748"
|
|
||||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<rect
|
|
||||||
width="58"
|
|
||||||
height="58"
|
|
||||||
x="122.04288"
|
|
||||||
y="592.54248"
|
|
||||||
id="rect11778"
|
|
||||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<rect
|
|
||||||
width="58"
|
|
||||||
height="58"
|
|
||||||
x="202.04288"
|
|
||||||
y="592.54248"
|
|
||||||
id="rect11780"
|
|
||||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<rect
|
|
||||||
width="58"
|
|
||||||
height="58"
|
|
||||||
x="282.04288"
|
|
||||||
y="592.54248"
|
|
||||||
id="rect11782"
|
|
||||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<rect
|
|
||||||
width="58"
|
|
||||||
height="58"
|
|
||||||
x="362.04288"
|
|
||||||
y="592.54248"
|
|
||||||
id="rect11784"
|
|
||||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<rect
|
|
||||||
width="58"
|
|
||||||
height="58"
|
|
||||||
x="82.042877"
|
|
||||||
y="512.54248"
|
|
||||||
id="rect11786"
|
|
||||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<rect
|
|
||||||
width="58"
|
|
||||||
height="58"
|
|
||||||
x="162.04288"
|
|
||||||
y="512.54248"
|
|
||||||
id="rect11788"
|
|
||||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<rect
|
|
||||||
width="58"
|
|
||||||
height="58"
|
|
||||||
x="242.04288"
|
|
||||||
y="512.54248"
|
|
||||||
id="rect11790"
|
|
||||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<rect
|
|
||||||
width="58"
|
|
||||||
height="58"
|
|
||||||
x="322.04288"
|
|
||||||
y="512.54248"
|
|
||||||
id="rect11792"
|
|
||||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<text
|
|
||||||
x="57.815342"
|
|
||||||
y="633.93506"
|
|
||||||
id="text11796"
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
|
||||||
x="57.815342"
|
|
||||||
y="633.93506"
|
|
||||||
id="tspan11798"
|
|
||||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">C</tspan></text>
|
|
||||||
<text
|
|
||||||
x="137.81534"
|
|
||||||
y="633.93506"
|
|
||||||
id="text11800"
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
|
||||||
x="137.81534"
|
|
||||||
y="633.93506"
|
|
||||||
id="tspan11802"
|
|
||||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">V</tspan></text>
|
|
||||||
<text
|
|
||||||
x="217.81534"
|
|
||||||
y="633.93506"
|
|
||||||
id="text11804"
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
|
||||||
x="217.81534"
|
|
||||||
y="633.93506"
|
|
||||||
id="tspan11806"
|
|
||||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">B</tspan></text>
|
|
||||||
<text
|
|
||||||
x="297.81534"
|
|
||||||
y="633.93506"
|
|
||||||
id="text11808"
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
|
||||||
x="297.81534"
|
|
||||||
y="633.93506"
|
|
||||||
id="tspan11810"
|
|
||||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">N</tspan></text>
|
|
||||||
<text
|
|
||||||
x="377.81534"
|
|
||||||
y="633.93506"
|
|
||||||
id="text11812"
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
|
||||||
x="377.81534"
|
|
||||||
y="633.93506"
|
|
||||||
id="tspan11814"
|
|
||||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">M</tspan></text>
|
|
||||||
<text
|
|
||||||
x="337.81534"
|
|
||||||
y="553.93506"
|
|
||||||
id="text11816"
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
|
||||||
x="337.81534"
|
|
||||||
y="553.93506"
|
|
||||||
id="tspan11818"
|
|
||||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">J</tspan></text>
|
|
||||||
<text
|
|
||||||
x="257.81534"
|
|
||||||
y="553.93506"
|
|
||||||
id="text11820"
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
|
||||||
x="257.81534"
|
|
||||||
y="553.93506"
|
|
||||||
id="tspan11822"
|
|
||||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">H</tspan></text>
|
|
||||||
<text
|
|
||||||
x="177.81534"
|
|
||||||
y="553.93506"
|
|
||||||
id="text11824"
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
|
||||||
x="177.81534"
|
|
||||||
y="553.93506"
|
|
||||||
id="tspan11826"
|
|
||||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">G</tspan></text>
|
|
||||||
<text
|
|
||||||
x="97.815338"
|
|
||||||
y="553.93506"
|
|
||||||
id="text11828"
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
|
||||||
x="97.815338"
|
|
||||||
y="553.93506"
|
|
||||||
id="tspan11830"
|
|
||||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">F</tspan></text>
|
|
||||||
<path
|
|
||||||
d="m 590.15063,48.238251 a 12.628045,12.628045 0 1 1 -25.25609,0 12.628045,12.628045 0 1 1 25.25609,0 z"
|
|
||||||
transform="matrix(1.5,0,0,1.5,-635.24402,504.05633)"
|
|
||||||
id="path11832"
|
|
||||||
style="color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#e50000;stroke-width:2.33333325;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<g
|
|
||||||
transform="matrix(0.98314313,0.18283763,-0.18283763,0.98314313,38.34468,-177.34601)"
|
|
||||||
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 l -0.71428,0 -71.07143,12.14286 z"
|
|
||||||
id="path2820-6-6"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
|
||||||
<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;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<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="opacity:0.92000002;color:#000000;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
transform="translate(-34.54288,-505.04248)"
|
|
||||||
id="layer1"
|
|
||||||
style="display:inline">
|
|
||||||
<rect
|
|
||||||
width="135"
|
|
||||||
height="63"
|
|
||||||
x="55.166245"
|
|
||||||
y="782.95221"
|
|
||||||
id="rect11656"
|
|
||||||
style="color:#000000;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<rect
|
|
||||||
width="135"
|
|
||||||
height="63"
|
|
||||||
x="258.97995"
|
|
||||||
y="782.95221"
|
|
||||||
id="rect11656-7"
|
|
||||||
style="color:#000000;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<rect
|
|
||||||
width="64.642883"
|
|
||||||
height="68.303299"
|
|
||||||
x="192.25995"
|
|
||||||
y="778.95221"
|
|
||||||
id="rect11656-1"
|
|
||||||
style="color:#000000;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<g
|
|
||||||
transform="matrix(-0.96540637,0.18283763,0.17953908,0.98314313,431.3343,62.30631)"
|
|
||||||
id="g3663-9">
|
|
||||||
<path
|
|
||||||
d="m 359.78441,828.85231 -28.35583,-65.06155 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 47.45034,95.30837 47.45034,95.30837 l -63.38022,25.11033 z"
|
|
||||||
id="path2820-6"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1.00914431px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
|
||||||
<path
|
|
||||||
d="m 360.32021,827.78041 c 0,0 -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 49.57778,98.62829 49.57778,98.62829 0,0 -61.86167,24.42554 -61.86167,24.42554 z"
|
|
||||||
id="path2824-1"
|
|
||||||
style="color:#000000;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.00201829;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<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"
|
|
||||||
style="opacity:0.92000002;color:#000000;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
</g>
|
|
||||||
<path
|
|
||||||
d="m 232.30267,551.36809 0,46.72376"
|
|
||||||
id="path11849"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart-4);marker-end:url(#Arrow1Lend-2)" />
|
|
||||||
<path
|
|
||||||
d="m 255.66455,574.72997 -46.72376,0"
|
|
||||||
id="path12611"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart-4);marker-end:url(#Arrow1Lend-2)" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 17 KiB |
|
|
@ -1,106 +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"
|
|
||||||
width="89.829216mm"
|
|
||||||
height="59.06765mm"
|
|
||||||
viewBox="0 0 318.2925 209.29482"
|
|
||||||
id="svg4184"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="clickfinger-distance.svg">
|
|
||||||
<defs
|
|
||||||
id="defs4186" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="1.4"
|
|
||||||
inkscape:cx="235.68795"
|
|
||||||
inkscape:cy="163.39995"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
fit-margin-top="0"
|
|
||||||
fit-margin-left="0"
|
|
||||||
fit-margin-right="0"
|
|
||||||
fit-margin-bottom="0" />
|
|
||||||
<metadata
|
|
||||||
id="metadata4189">
|
|
||||||
<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>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-257.99662,-299.41313)">
|
|
||||||
<rect
|
|
||||||
width="313.09872"
|
|
||||||
height="167.89594"
|
|
||||||
x="260.59351"
|
|
||||||
y="302.01001"
|
|
||||||
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
|
|
||||||
style="opacity:0.92000002;fill:#7b0000;fill-opacity:0.2983426;stroke:#000000;stroke-width:1.00100005;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
id="rect4788"
|
|
||||||
width="188.57143"
|
|
||||||
height="79.285713"
|
|
||||||
x="355"
|
|
||||||
y="309.50507" />
|
|
||||||
<g
|
|
||||||
transform="matrix(0.79657897,0.11742288,-0.14814182,0.631399,276.6631,-158.96703)"
|
|
||||||
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 l -0.71428,0 -71.07143,12.14286 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>
|
|
||||||
<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:1.00100005;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="path2824-1-1-3"
|
|
||||||
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"
|
|
||||||
sodipodi:nodetypes="sszzzcss" />
|
|
||||||
<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-1-4-3"
|
|
||||||
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"
|
|
||||||
sodipodi:nodetypes="ccccc" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 5.9 KiB |
|
|
@ -1,207 +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="1084.4291"
|
|
||||||
height="218.18733"
|
|
||||||
id="svg2"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="clickfinger.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="1136"
|
|
||||||
id="namedview4312"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="0.81739538"
|
|
||||||
inkscape:cx="347.81182"
|
|
||||||
inkscape:cy="125.36322"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
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.61797,339.58481"
|
|
||||||
orientation="0,1"
|
|
||||||
id="guide4473" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<defs
|
|
||||||
id="defs4" />
|
|
||||||
<g
|
|
||||||
id="g4405"
|
|
||||||
transform="matrix(0.81023703,0,0,0.6422249,-2.3181067e-6,0.47063383)">
|
|
||||||
<rect
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:7.20000076;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="rect2858-0"
|
|
||||||
y="3.6000037"
|
|
||||||
x="3.6000032"
|
|
||||||
height="261.42856"
|
|
||||||
width="386.42856" />
|
|
||||||
<g
|
|
||||||
id="g3663-9-5"
|
|
||||||
transform="matrix(0.98314313,0.18283763,-0.18283763,0.98314313,-4.7772181,-625.20496)">
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="path2820-6-6"
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z" />
|
|
||||||
<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.002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="path2824-1-1"
|
|
||||||
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" />
|
|
||||||
<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-1-4"
|
|
||||||
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" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
id="g4394"
|
|
||||||
transform="matrix(0.81023703,0,0,0.6422249,-2.3181067e-6,0.47063383)">
|
|
||||||
<rect
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:7.20000076;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="rect2858"
|
|
||||||
y="3.6000218"
|
|
||||||
x="475.52567"
|
|
||||||
height="261.42856"
|
|
||||||
width="386.42856" />
|
|
||||||
<g
|
|
||||||
id="g3663"
|
|
||||||
transform="matrix(0.98196551,0.12493315,-0.14261338,1.1209308,508.26203,-717.12108)">
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:0.94553083px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="path2820"
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z" />
|
|
||||||
<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.00189106;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="path2824"
|
|
||||||
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" />
|
|
||||||
<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"
|
|
||||||
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" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
id="g3663-9"
|
|
||||||
transform="matrix(0.98314313,0.18283763,-0.18283763,0.98314313,458.58466,-619.69966)">
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="path2820-6"
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z" />
|
|
||||||
<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.002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="path2824-1"
|
|
||||||
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" />
|
|
||||||
<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-1"
|
|
||||||
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" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<rect
|
|
||||||
width="313.09872"
|
|
||||||
height="167.89594"
|
|
||||||
x="768.41345"
|
|
||||||
y="2.3120098"
|
|
||||||
id="rect2858-7"
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.19376326;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
|
||||||
<g
|
|
||||||
transform="matrix(0.79562482,0.08023518,-0.11555064,0.71988967,731.4982,-458.98163)"
|
|
||||||
id="g3663-3">
|
|
||||||
<path
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
|
||||||
id="path2820-0"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:0.94553083px;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-9"
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.00189106;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-8"
|
|
||||||
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(0.79657897,0.11742288,-0.14814182,0.631399,697.24775,-392.41517)"
|
|
||||||
id="g3663-9-8">
|
|
||||||
<path
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
|
||||||
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.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(0.79562482,0.08023518,-0.11555064,0.71988967,793.15605,-458.77793)"
|
|
||||||
id="g3663-3-0">
|
|
||||||
<path
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
|
||||||
id="path2820-0-5"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:0.94553083px;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-9-3"
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.00189106;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-8-8"
|
|
||||||
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: 16 KiB |
|
|
@ -1,126 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
version="1.1"
|
|
||||||
width="865.5542"
|
|
||||||
height="341.20889"
|
|
||||||
id="svg2">
|
|
||||||
<defs
|
|
||||||
id="defs4">
|
|
||||||
<marker
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
id="Arrow1Lend"
|
|
||||||
style="overflow:visible">
|
|
||||||
<path
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
|
||||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
|
||||||
id="path3710"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
id="Arrow1Lstart"
|
|
||||||
style="overflow:visible">
|
|
||||||
<path
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
|
||||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
|
||||||
id="path3707"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
id="Arrow1Lstart-4"
|
|
||||||
style="overflow:visible">
|
|
||||||
<path
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
|
||||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
|
||||||
id="path3707-7"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
id="Arrow1Lend-2"
|
|
||||||
style="overflow:visible">
|
|
||||||
<path
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
|
||||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
|
||||||
id="path3710-3"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
|
||||||
</marker>
|
|
||||||
</defs>
|
|
||||||
<g
|
|
||||||
transform="translate(343.95712,-527.33359)"
|
|
||||||
id="layer3"
|
|
||||||
style="display:inline">
|
|
||||||
<rect
|
|
||||||
width="386.42856"
|
|
||||||
height="261.42856"
|
|
||||||
x="-340.35712"
|
|
||||||
y="530.93359"
|
|
||||||
id="rect2858-0"
|
|
||||||
style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:7.20000076;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<path
|
|
||||||
d="m 21.360531,774.95272 0,-196.97975"
|
|
||||||
id="path8036"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lend)" />
|
|
||||||
<g
|
|
||||||
transform="matrix(0.98314313,0.18283763,-0.18283763,0.98314313,-175.46474,-125.7572)"
|
|
||||||
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 l -0.71428,0 -71.07143,12.14286 z"
|
|
||||||
id="path2820-6-6"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
|
||||||
<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;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<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="opacity:0.92000002;color:#000000;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
transform="translate(343.95712,-527.33359)"
|
|
||||||
id="layer1"
|
|
||||||
style="display:inline">
|
|
||||||
<rect
|
|
||||||
width="386.42856"
|
|
||||||
height="261.42856"
|
|
||||||
x="131.56854"
|
|
||||||
y="530.93359"
|
|
||||||
id="rect2858"
|
|
||||||
style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:7.20000076;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<path
|
|
||||||
d="m 455.56456,762.87232 c 0,0 -235.01231,1.01015 -235.01231,1.01015"
|
|
||||||
id="path3702"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow1Lstart-4);marker-end:url(#Arrow1Lend-2)" />
|
|
||||||
<g
|
|
||||||
transform="matrix(0.98314313,0.18283763,-0.18283763,0.98314313,132.81621,-12.620089)"
|
|
||||||
id="g3663-9">
|
|
||||||
<path
|
|
||||||
d="m 359.78441,828.85231 -28.35583,-65.06155 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 47.45034,95.30837 47.45034,95.30837 l -63.38022,25.11033 z"
|
|
||||||
id="path2820-6"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
|
||||||
<path
|
|
||||||
d="m 360.32021,827.78041 c 0,0 -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 49.57778,98.62829 49.57778,98.62829 0,0 -61.86167,24.42554 -61.86167,24.42554 z"
|
|
||||||
id="path2824-1"
|
|
||||||
style="color:#000000;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
<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"
|
|
||||||
style="opacity:0.92000002;color:#000000;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 7 KiB |
|
|
@ -1,496 +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"
|
|
||||||
width="210.95885mm"
|
|
||||||
height="65.170769mm"
|
|
||||||
viewBox="0 0 747.49199 230.92005"
|
|
||||||
id="svg4313"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="gesture-2fg-ambiguity.svg">
|
|
||||||
<defs
|
|
||||||
id="defs4315">
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow2Lend"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow2Lend"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4506"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Mend"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow1Mend"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4494"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
|
||||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Mstart"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow1Mstart"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4491"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
|
||||||
transform="matrix(0.4,0,0,0.4,4,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow2Lend"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="marker7694"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path7696"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Mend"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="marker7562"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path7564"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow2Lstart"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow2Lstart"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4995"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:isstock="true"
|
|
||||||
style="overflow:visible"
|
|
||||||
id="marker7356"
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
inkscape:stockid="Arrow1Mstart">
|
|
||||||
<path
|
|
||||||
transform="matrix(0.4,0,0,0.4,4,0)"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
id="path7358"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Send"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow1Send"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4992"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow2Sstart"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow2Sstart"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path5007"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
transform="matrix(0.3,0,0,0.3,-0.69,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:isstock="true"
|
|
||||||
style="overflow:visible"
|
|
||||||
id="marker6499"
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
inkscape:stockid="Arrow2Lstart">
|
|
||||||
<path
|
|
||||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
id="path6501"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Lstart"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="marker5837"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path5839"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:isstock="true"
|
|
||||||
style="overflow:visible"
|
|
||||||
id="marker5365"
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
inkscape:stockid="Arrow2Lend">
|
|
||||||
<path
|
|
||||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
id="path5367"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Lend"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="marker5291"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path5293"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;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="Arrow1Lend"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4980"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;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="path4977"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="1.8735525"
|
|
||||||
inkscape:cx="423.84385"
|
|
||||||
inkscape:cy="193.39486"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
fit-margin-top="0"
|
|
||||||
fit-margin-left="0"
|
|
||||||
fit-margin-right="0"
|
|
||||||
fit-margin-bottom="0" />
|
|
||||||
<metadata
|
|
||||||
id="metadata4318">
|
|
||||||
<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>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-1.110285,-124.21518)">
|
|
||||||
<rect
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.76355982;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="rect2858-0"
|
|
||||||
y="127.09696"
|
|
||||||
x="3.992065"
|
|
||||||
height="209.27208"
|
|
||||||
width="309.33386" />
|
|
||||||
<g
|
|
||||||
id="g4897"
|
|
||||||
transform="matrix(0.64785166,-0.12161418,0.12161418,0.64785166,-136.33634,-258.03322)">
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="path4899"
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z" />
|
|
||||||
<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.002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="path4901"
|
|
||||||
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" />
|
|
||||||
<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="path4903"
|
|
||||||
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" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
transform="matrix(0.64785166,-0.12161418,0.12161418,0.64785166,-167.25783,-222.59332)"
|
|
||||||
id="g5039">
|
|
||||||
<path
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
|
||||||
id="path5041"
|
|
||||||
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="path5043"
|
|
||||||
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="path5045"
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.92000002;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;enable-background:accumulate"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
id="g7665"
|
|
||||||
transform="matrix(0.98639446,-0.16439576,0.16439576,0.98639446,-43.838837,-4.728819)">
|
|
||||||
<path
|
|
||||||
sodipodi:nodetypes="sszzzcss"
|
|
||||||
d="m 136.26948,381.29633 c -24.01774,-7.29937 -29.0012,-10.10221 -30.51977,-10.54973 -10.672936,-3.14527 -18.270506,-5.54063 -23.777576,-13.4704 -5.50707,-7.92977 -5.34967,-20.78347 8.87612,-26.31603 14.225796,-5.53258 39.343506,8.79596 60.130606,16.16341 20.7871,7.36743 33.04562,11.44544 39.33421,13.8755 -8.10021,18.05041 -7.22128,21.15857 -10.11054,33.34117 -0.0481,0.20261 -17.87458,-5.12433 -43.93305,-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 107.01743,369.53232 c -10.672936,-1.94747 -17.884406,-5.64477 -21.626906,-8.75386 -8.11652,-9.03765 -6.31775,-15.03428 -3.3272,-13.99784 8.90495,-0.9097 30.203836,9.01528 33.860416,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>
|
|
||||||
<g
|
|
||||||
id="g9940"
|
|
||||||
transform="matrix(0.64785166,-0.12161418,0.12161418,0.64785166,-167.25783,-222.59332)">
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="path9942"
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z" />
|
|
||||||
<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.002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="path9944"
|
|
||||||
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" />
|
|
||||||
<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="path9946"
|
|
||||||
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" />
|
|
||||||
</g>
|
|
||||||
<rect
|
|
||||||
width="309.33386"
|
|
||||||
height="209.27208"
|
|
||||||
x="423.99207"
|
|
||||||
y="127.09696"
|
|
||||||
id="rect9948"
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.76355982;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
|
||||||
<g
|
|
||||||
transform="matrix(0.64785166,-0.12161418,0.12161418,0.64785166,283.66366,-258.03322)"
|
|
||||||
id="g9950">
|
|
||||||
<path
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
|
||||||
id="path9952"
|
|
||||||
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="path9954"
|
|
||||||
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="path9956"
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.92000002;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;enable-background:accumulate"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
id="g9958"
|
|
||||||
transform="matrix(0.64785166,-0.12161418,0.12161418,0.64785166,252.74217,-222.59332)">
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="path9960"
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z" />
|
|
||||||
<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.002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="path9962"
|
|
||||||
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" />
|
|
||||||
<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="path9964"
|
|
||||||
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" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
transform="matrix(0.64785166,-0.12161418,0.12161418,0.64785166,252.74217,-222.59332)"
|
|
||||||
id="g9972">
|
|
||||||
<path
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
|
||||||
id="path9974"
|
|
||||||
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="path9976"
|
|
||||||
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="path9978"
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.92000002;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;enable-background:accumulate"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
id="g9980"
|
|
||||||
transform="matrix(0.64785166,-0.12161418,0.12161418,0.64785166,342.56693,-256.56067)">
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="path9982"
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z" />
|
|
||||||
<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.002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="path9984"
|
|
||||||
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" />
|
|
||||||
<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="path9986"
|
|
||||||
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" />
|
|
||||||
</g>
|
|
||||||
<path
|
|
||||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
d="m 146.82277,201.01077 419.52386,-1.0675"
|
|
||||||
id="path9992"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
<rect
|
|
||||||
y="188.0482"
|
|
||||||
x="330.96494"
|
|
||||||
height="22.417305"
|
|
||||||
width="77.393082"
|
|
||||||
id="rect10086"
|
|
||||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.97799999;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.78531075" />
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-style:normal;font-weight:normal;font-size:17.5px;line-height:125%;font-family:Sans;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"
|
|
||||||
x="336.83612"
|
|
||||||
y="205.01161"
|
|
||||||
id="text10074"
|
|
||||||
sodipodi:linespacing="125%"><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
id="tspan10076"
|
|
||||||
x="336.83612"
|
|
||||||
y="205.01161">Touch 1</tspan></text>
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path10082"
|
|
||||||
d="m 180.82277,169.01077 419.52386,-1.0675"
|
|
||||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
|
||||||
<rect
|
|
||||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.97799999;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.78531075"
|
|
||||||
id="rect10084"
|
|
||||||
width="77.393082"
|
|
||||||
height="22.417305"
|
|
||||||
x="330.96494"
|
|
||||||
y="156.0482" />
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-style:normal;font-weight:normal;font-size:17.5px;line-height:125%;font-family:Sans;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"
|
|
||||||
x="335.76865"
|
|
||||||
y="173.66182"
|
|
||||||
id="text10078"
|
|
||||||
sodipodi:linespacing="125%"><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
id="tspan10080"
|
|
||||||
x="335.76865"
|
|
||||||
y="173.66182">Touch 2</tspan></text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 28 KiB |
|
|
@ -1,201 +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="393.62857"
|
|
||||||
height="268.62857"
|
|
||||||
id="svg2"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="palm-detection.svg">
|
|
||||||
<metadata
|
|
||||||
id="metadata3479">
|
|
||||||
<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>
|
|
||||||
<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="1016"
|
|
||||||
id="namedview3477"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="3.5662625"
|
|
||||||
inkscape:cx="180.54059"
|
|
||||||
inkscape:cy="269.48563"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="svg2"
|
|
||||||
inkscape:document-rotation="0" />
|
|
||||||
<defs
|
|
||||||
id="defs4">
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Lstart"
|
|
||||||
orient="auto"
|
|
||||||
refY="0.0"
|
|
||||||
refX="0.0"
|
|
||||||
id="marker4663"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4407"
|
|
||||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
|
||||||
transform="scale(0.8) translate(12.5,0)" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
id="Arrow1Lend"
|
|
||||||
style="overflow:visible">
|
|
||||||
<path
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
|
||||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
|
||||||
id="path3710"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
id="Arrow1Lstart"
|
|
||||||
style="overflow:visible">
|
|
||||||
<path
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
|
||||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
|
||||||
id="path3707"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
id="Arrow1Lstart-4"
|
|
||||||
style="overflow:visible">
|
|
||||||
<path
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
|
||||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
|
||||||
id="path3707-7"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
id="Arrow1Lend-2"
|
|
||||||
style="overflow:visible">
|
|
||||||
<path
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
|
||||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
|
||||||
id="path3710-3"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
|
||||||
</marker>
|
|
||||||
</defs>
|
|
||||||
<rect
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:7.20000076;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="rect2858-0"
|
|
||||||
y="3.6000037"
|
|
||||||
x="3.6000032"
|
|
||||||
height="261.42856"
|
|
||||||
width="386.42856" />
|
|
||||||
<rect
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ff0000;fill-opacity:0.32017547;fill-rule:nonzero;stroke:none;stroke-width:3.5;marker:none;enable-background:accumulate"
|
|
||||||
id="rect12924"
|
|
||||||
y="7.1355872"
|
|
||||||
x="7.0710421"
|
|
||||||
height="254.3844"
|
|
||||||
width="65.281105" />
|
|
||||||
<rect
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ff0000;fill-opacity:0.32017547;fill-rule:nonzero;stroke:none;stroke-width:3.5;marker:none;enable-background:accumulate"
|
|
||||||
id="rect13482"
|
|
||||||
y="6.8830237"
|
|
||||||
x="321.22849"
|
|
||||||
height="254.3844"
|
|
||||||
width="65.281105" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:6, 1;stroke-dashoffset:0;stroke-opacity:1;marker-mid:none;marker-end:url(#Arrow1Lend-2)"
|
|
||||||
id="path13492"
|
|
||||||
d="m 38.928571,67.914286 c 0,0 3.508205,24.810617 9.642857,57.857144 6.134651,33.04652 23.277202,79.68584 89.642852,90.35714" />
|
|
||||||
<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"
|
|
||||||
xml:space="preserve"
|
|
||||||
id="text13874"
|
|
||||||
y="63.628628"
|
|
||||||
x="33.214291"><tspan
|
|
||||||
style="font-size:18px;font-family:Arial;-inkscape-font-specification:Arial"
|
|
||||||
id="tspan13876"
|
|
||||||
y="63.628628"
|
|
||||||
x="33.214291">A</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"
|
|
||||||
y="98.748993"
|
|
||||||
x="351.85422"><tspan
|
|
||||||
style="font-size:18px;font-family:Arial;-inkscape-font-specification:Arial"
|
|
||||||
id="tspan13876-7"
|
|
||||||
y="98.748993"
|
|
||||||
x="351.85422">B</tspan></text>
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend-2)"
|
|
||||||
id="path13903"
|
|
||||||
d="m 347.5,90.414286 c 0,0 -28.20972,-6.408104 -85,-6.071429 -22.06971,0.130838 -66.07143,4.285715 -66.07143,4.285715" />
|
|
||||||
<g
|
|
||||||
transform="translate(343.95712,-527.33359)"
|
|
||||||
id="layer1"
|
|
||||||
style="display:inline" />
|
|
||||||
<text
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:0%;font-family:Utopia;-inkscape-font-specification:Utopia;text-align:start;writing-mode:lr-tb;text-anchor:start;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
|
||||||
xml:space="preserve"
|
|
||||||
id="text13874-8-1"
|
|
||||||
y="46.009491"
|
|
||||||
x="342.27759"><tspan
|
|
||||||
style="font-size:18px;font-family:Arial;-inkscape-font-specification:Arial"
|
|
||||||
id="tspan13876-7-9"
|
|
||||||
y="46.009491"
|
|
||||||
x="342.27759">C</tspan></text>
|
|
||||||
<circle
|
|
||||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1"
|
|
||||||
id="path4401"
|
|
||||||
cx="-360.181"
|
|
||||||
cy="24.53549"
|
|
||||||
r="4.0658817"
|
|
||||||
transform="scale(-1,1)" />
|
|
||||||
<rect
|
|
||||||
width="248.87633"
|
|
||||||
height="6.8111157"
|
|
||||||
x="72.35215"
|
|
||||||
y="7.1355872"
|
|
||||||
id="rect4355"
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ff0000;fill-opacity:0.32017547;fill-rule:nonzero;stroke:none;stroke-width:1.11822701;marker:none;enable-background:accumulate" />
|
|
||||||
<rect
|
|
||||||
y="7.1355872"
|
|
||||||
x="72.35215"
|
|
||||||
height="6.8111153"
|
|
||||||
width="248.87634"
|
|
||||||
id="rect4353"
|
|
||||||
style="fill:#000000;fill-opacity:0.3559322;fill-rule:evenodd;stroke:none;stroke-width:1.44321382px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 7.5 KiB |
|
|
@ -1,365 +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"
|
|
||||||
width="88.927498mm"
|
|
||||||
height="60.687836mm"
|
|
||||||
viewBox="0 0 315.09744 215.03564"
|
|
||||||
id="svg4313"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="pinch-gestures-softbuttons.svg">
|
|
||||||
<defs
|
|
||||||
id="defs4315">
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow2Lend"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow2Lend"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4506"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Mend"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow1Mend"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4494"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
|
||||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Mstart"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow1Mstart"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4491"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
|
|
||||||
transform="matrix(0.4,0,0,0.4,4,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow2Lend"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="marker7694"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path7696"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Mend"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="marker7562"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path7564"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow2Lstart"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow2Lstart"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4995"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:isstock="true"
|
|
||||||
style="overflow:visible"
|
|
||||||
id="marker7356"
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
inkscape:stockid="Arrow1Mstart">
|
|
||||||
<path
|
|
||||||
transform="matrix(0.4,0,0,0.4,4,0)"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
id="path7358"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Send"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow1Send"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4992"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow2Sstart"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow2Sstart"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path5007"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
transform="matrix(0.3,0,0,0.3,-0.69,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:isstock="true"
|
|
||||||
style="overflow:visible"
|
|
||||||
id="marker6499"
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
inkscape:stockid="Arrow2Lstart">
|
|
||||||
<path
|
|
||||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
id="path6501"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Lstart"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="marker5837"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path5839"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:isstock="true"
|
|
||||||
style="overflow:visible"
|
|
||||||
id="marker5365"
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
inkscape:stockid="Arrow2Lend">
|
|
||||||
<path
|
|
||||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
id="path5367"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Lend"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="marker5291"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path5293"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;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="Arrow1Lend"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4980"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;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="path4977"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="2.6496034"
|
|
||||||
inkscape:cx="131.47222"
|
|
||||||
inkscape:cy="93.839318"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
fit-margin-top="0"
|
|
||||||
fit-margin-left="0"
|
|
||||||
fit-margin-right="0"
|
|
||||||
fit-margin-bottom="0" />
|
|
||||||
<metadata
|
|
||||||
id="metadata4318">
|
|
||||||
<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>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-1.110285,-124.21518)">
|
|
||||||
<rect
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.76355982;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="rect2858-0"
|
|
||||||
y="127.09696"
|
|
||||||
x="3.992065"
|
|
||||||
height="209.27208"
|
|
||||||
width="309.33386" />
|
|
||||||
<g
|
|
||||||
id="g4897"
|
|
||||||
transform="matrix(0.64785166,-0.12161418,0.12161418,0.64785166,-136.33634,-278.03322)">
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="path4899"
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z" />
|
|
||||||
<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.002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="path4901"
|
|
||||||
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" />
|
|
||||||
<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="path4903"
|
|
||||||
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" />
|
|
||||||
</g>
|
|
||||||
<rect
|
|
||||||
style="opacity:0.92000002;fill:#ff0000;fill-opacity:0.31073447;stroke:#000000;stroke-width:0.97799999;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.78531075"
|
|
||||||
id="rect8337"
|
|
||||||
width="303.45676"
|
|
||||||
height="57.133244"
|
|
||||||
x="6.9702415"
|
|
||||||
y="276.61765" />
|
|
||||||
<g
|
|
||||||
transform="matrix(0.64785166,-0.12161418,0.12161418,0.64785166,-167.25783,-242.59332)"
|
|
||||||
id="g5039">
|
|
||||||
<path
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
|
||||||
id="path5041"
|
|
||||||
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="path5043"
|
|
||||||
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="path5045"
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.92000002;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;enable-background:accumulate"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
id="g7665"
|
|
||||||
transform="matrix(0.98639446,-0.16439576,0.16439576,0.98639446,-83.838837,-24.728819)">
|
|
||||||
<path
|
|
||||||
sodipodi:nodetypes="sszzzcss"
|
|
||||||
d="m 136.26948,381.29633 c -24.01774,-7.29937 -29.0012,-10.10221 -30.51977,-10.54973 -10.672936,-3.14527 -18.270506,-5.54063 -23.777576,-13.4704 -5.50707,-7.92977 -5.34967,-20.78347 8.87612,-26.31603 14.225796,-5.53258 39.343506,8.79596 60.130606,16.16341 20.7871,7.36743 33.04562,11.44544 39.33421,13.8755 -8.10021,18.05041 -7.22128,21.15857 -10.11054,33.34117 -0.0481,0.20261 -17.87458,-5.12433 -43.93305,-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 107.01743,369.53232 c -10.672936,-1.94747 -17.884406,-5.64477 -21.626906,-8.75386 -8.11652,-9.03765 -6.31775,-15.03428 -3.3272,-13.99784 8.90495,-0.9097 30.203836,9.01528 33.860416,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>
|
|
||||||
<path
|
|
||||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
|
||||||
d="m 126.40547,189.76337 -18.14734,34.1597"
|
|
||||||
id="path8341"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path8343"
|
|
||||||
d="m 94.40547,249.76337 -18.14734,34.1597"
|
|
||||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Lstart)" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 16 KiB |
|
|
@ -1,612 +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"
|
|
||||||
width="193.91415mm"
|
|
||||||
height="71.032608mm"
|
|
||||||
viewBox="0 0 687.09741 251.69034"
|
|
||||||
id="svg4313"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.91 r13725"
|
|
||||||
sodipodi:docname="pinch-gestures.svg">
|
|
||||||
<defs
|
|
||||||
id="defs4315">
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow2Lend"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="marker7694"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path7696"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Mend"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="marker7562"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path7564"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow2Lstart"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow2Lstart"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4995"
|
|
||||||
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:isstock="true"
|
|
||||||
style="overflow:visible"
|
|
||||||
id="marker7356"
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
inkscape:stockid="Arrow1Mstart">
|
|
||||||
<path
|
|
||||||
transform="matrix(0.4,0,0,0.4,4,0)"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
id="path7358"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:isstock="true"
|
|
||||||
style="overflow:visible"
|
|
||||||
id="marker7250"
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
inkscape:stockid="Arrow1Mend"
|
|
||||||
inkscape:collect="always">
|
|
||||||
<path
|
|
||||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
id="path7252"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Mend"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow1Mend"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true"
|
|
||||||
inkscape:collect="always">
|
|
||||||
<path
|
|
||||||
id="path4986"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Send"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow1Send"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4992"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Mstart"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow1Mstart"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true"
|
|
||||||
inkscape:collect="always">
|
|
||||||
<path
|
|
||||||
id="path4983"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
transform="matrix(0.4,0,0,0.4,4,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow2Sstart"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow2Sstart"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path5007"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
transform="matrix(0.3,0,0,0.3,-0.69,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:isstock="true"
|
|
||||||
style="overflow:visible"
|
|
||||||
id="marker6499"
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
inkscape:stockid="Arrow2Lstart">
|
|
||||||
<path
|
|
||||||
transform="matrix(1.1,0,0,1.1,1.1,0)"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
id="path6501"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:isstock="true"
|
|
||||||
style="overflow:visible"
|
|
||||||
id="marker6261"
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
inkscape:stockid="Arrow2Lend"
|
|
||||||
inkscape:collect="always">
|
|
||||||
<path
|
|
||||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
id="path6263"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Lstart"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="marker5837"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path5839"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:isstock="true"
|
|
||||||
style="overflow:visible"
|
|
||||||
id="marker5365"
|
|
||||||
refX="0"
|
|
||||||
refY="0"
|
|
||||||
orient="auto"
|
|
||||||
inkscape:stockid="Arrow2Lend">
|
|
||||||
<path
|
|
||||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
id="path5367"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow2Lend"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="Arrow2Lend"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true"
|
|
||||||
inkscape:collect="always">
|
|
||||||
<path
|
|
||||||
id="path4998"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
|
||||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
|
||||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
<marker
|
|
||||||
inkscape:stockid="Arrow1Lend"
|
|
||||||
orient="auto"
|
|
||||||
refY="0"
|
|
||||||
refX="0"
|
|
||||||
id="marker5291"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path5293"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;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="Arrow1Lend"
|
|
||||||
style="overflow:visible"
|
|
||||||
inkscape:isstock="true">
|
|
||||||
<path
|
|
||||||
id="path4980"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;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="path4977"
|
|
||||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
|
||||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
|
||||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</marker>
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="0.93677625"
|
|
||||||
inkscape:cx="60.063165"
|
|
||||||
inkscape:cy="195.28138"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1136"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
fit-margin-top="0"
|
|
||||||
fit-margin-left="0"
|
|
||||||
fit-margin-right="0"
|
|
||||||
fit-margin-bottom="0" />
|
|
||||||
<metadata
|
|
||||||
id="metadata4318">
|
|
||||||
<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>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-1.110285,-124.21518)">
|
|
||||||
<rect
|
|
||||||
width="309.33386"
|
|
||||||
height="209.27208"
|
|
||||||
x="375.99207"
|
|
||||||
y="127.09696"
|
|
||||||
id="rect14688"
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.76355982;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" />
|
|
||||||
<rect
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5.76355982;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="rect2858-0"
|
|
||||||
y="127.09696"
|
|
||||||
x="3.992065"
|
|
||||||
height="209.27208"
|
|
||||||
width="309.33386" />
|
|
||||||
<g
|
|
||||||
id="g3663-9-5"
|
|
||||||
transform="matrix(0.64805599,0.12052062,-0.12052062,0.64805599,-40.638425,-251.35321)">
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="path2820-6-6"
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z" />
|
|
||||||
<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.002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="path2824-1-1"
|
|
||||||
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" />
|
|
||||||
<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-1-4"
|
|
||||||
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" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
transform="matrix(0.64805599,0.12052062,-0.12052062,0.64805599,87.872503,-305.95371)"
|
|
||||||
id="g4877">
|
|
||||||
<path
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
|
||||||
id="path4879"
|
|
||||||
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="path4881"
|
|
||||||
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="path4883"
|
|
||||||
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(0.64805599,0.12052062,-0.12052062,0.64805599,-40.638425,-251.35321)"
|
|
||||||
id="g4889">
|
|
||||||
<path
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
|
||||||
id="path4891"
|
|
||||||
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="path4893"
|
|
||||||
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="path4895"
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.92000002;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;enable-background:accumulate"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
id="g4897"
|
|
||||||
transform="matrix(0.64805599,0.12052062,-0.12052062,0.64805599,87.872503,-305.95371)">
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="path4899"
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z" />
|
|
||||||
<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.002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="path4901"
|
|
||||||
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" />
|
|
||||||
<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="path4903"
|
|
||||||
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" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
transform="matrix(0.64805599,0.12052062,-0.12052062,0.64805599,327.582,-251.35321)"
|
|
||||||
id="g4915">
|
|
||||||
<path
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
|
||||||
id="path4917"
|
|
||||||
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="path4919"
|
|
||||||
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="path4921"
|
|
||||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.92000002;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;enable-background:accumulate"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
id="g4923"
|
|
||||||
transform="matrix(0.64805599,0.12052062,-0.12052062,0.64805599,456.09293,-305.95371)">
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="path4925"
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z" />
|
|
||||||
<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.002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="path4927"
|
|
||||||
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" />
|
|
||||||
<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="path4929"
|
|
||||||
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" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
id="g4931"
|
|
||||||
transform="matrix(0.64805599,0.12052062,-0.12052062,0.64805599,327.582,-251.35321)">
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="path4933"
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z" />
|
|
||||||
<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.002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
|
||||||
id="path4935"
|
|
||||||
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" />
|
|
||||||
<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="path4937"
|
|
||||||
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" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
transform="matrix(0.64805599,0.12052062,-0.12052062,0.64805599,456.09293,-305.95371)"
|
|
||||||
id="g4939">
|
|
||||||
<path
|
|
||||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
|
||||||
id="path4941"
|
|
||||||
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="path4943"
|
|
||||||
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="path4945"
|
|
||||||
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>
|
|
||||||
<path
|
|
||||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.31833494;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
|
|
||||||
d="M 237.82329,186.65441 272.448,168.6762"
|
|
||||||
id="path4971"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path5363"
|
|
||||||
d="m 43.293248,279.41755 34.62471,-17.97821"
|
|
||||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.31833494;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#marker6499)" />
|
|
||||||
<circle
|
|
||||||
style="opacity:0.92000002;fill:#ffdd55;fill-opacity:0.07734806;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
id="path6880"
|
|
||||||
cx="158.49547"
|
|
||||||
cy="227.65926"
|
|
||||||
r="5.3374538" />
|
|
||||||
<path
|
|
||||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.97016698px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker7356);marker-end:url(#marker7250)"
|
|
||||||
d="M 88.03522,236.61109 213.47708,179.47406"
|
|
||||||
id="path6882"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path6884"
|
|
||||||
d="M 25.998133,239.56832 257.65533,138.66416"
|
|
||||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.97016698px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Mstart);marker-end:url(#Arrow1Mend)"
|
|
||||||
sodipodi:nodetypes="cc" />
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-style:normal;font-weight:normal;font-size:12.50000095px;line-height:125%;font-family:Sans;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"
|
|
||||||
x="139.81439"
|
|
||||||
y="246.73911"
|
|
||||||
id="text6886"
|
|
||||||
sodipodi:linespacing="125%"><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
id="tspan6888"
|
|
||||||
x="139.81439"
|
|
||||||
y="246.73911">logical</tspan><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
x="139.81439"
|
|
||||||
y="262.36411"
|
|
||||||
id="tspan6890">center</tspan></text>
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-style:normal;font-weight:normal;font-size:12.50000095px;line-height:125%;font-family:Sans;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"
|
|
||||||
x="-0.65095264"
|
|
||||||
y="247.5675"
|
|
||||||
id="text6892"
|
|
||||||
sodipodi:linespacing="125%"
|
|
||||||
transform="matrix(0.90931568,-0.41610697,0.41610692,0.90931568,0,0)"><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
id="tspan6894"
|
|
||||||
x="-0.65095264"
|
|
||||||
y="247.5675">initial scale (1.0)</tspan></text>
|
|
||||||
<text
|
|
||||||
transform="matrix(0.90931568,-0.41610697,0.41610692,0.90931568,0,0)"
|
|
||||||
sodipodi:linespacing="125%"
|
|
||||||
id="text6896"
|
|
||||||
y="225.43965"
|
|
||||||
x="-16.939013"
|
|
||||||
style="font-style:normal;font-weight:normal;font-size:12.50000095px;line-height:125%;font-family:Sans;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="225.43965"
|
|
||||||
x="-16.939013"
|
|
||||||
id="tspan6898"
|
|
||||||
sodipodi:role="line">current scale (> 1.0)</tspan></text>
|
|
||||||
<circle
|
|
||||||
r="5.3374538"
|
|
||||||
cy="226.45061"
|
|
||||||
cx="529.7337"
|
|
||||||
id="circle7474"
|
|
||||||
style="opacity:0.92000002;fill:#ffdd55;fill-opacity:0.07734806;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
|
||||||
<text
|
|
||||||
sodipodi:linespacing="125%"
|
|
||||||
id="text7476"
|
|
||||||
y="245.53046"
|
|
||||||
x="511.05258"
|
|
||||||
style="font-style:normal;font-weight:normal;font-size:12.50000095px;line-height:125%;font-family:Sans;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="245.53046"
|
|
||||||
x="511.05258"
|
|
||||||
id="tspan7478"
|
|
||||||
sodipodi:role="line">logical</tspan><tspan
|
|
||||||
id="tspan7480"
|
|
||||||
y="261.15546"
|
|
||||||
x="511.05258"
|
|
||||||
sodipodi:role="line">center</tspan></text>
|
|
||||||
<path
|
|
||||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker6261)"
|
|
||||||
d="m 470.41432,259.01526 c 18.14735,33.09222 51.23956,27.22102 51.23956,27.22102"
|
|
||||||
id="path7554"
|
|
||||||
inkscape:connector-curvature="0" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path7692"
|
|
||||||
d="M 592.09959,192.40501 C 567.10018,164.13044 536.11794,177.15603 536.11794,177.15603"
|
|
||||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker7694)" />
|
|
||||||
<path
|
|
||||||
style="fill:#ff0000;fill-rule:evenodd;stroke:#dd0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
d="M 469.81386,258.48153 636.94289,169.34604"
|
|
||||||
id="path9270"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="cc" />
|
|
||||||
<path
|
|
||||||
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
d="M 540.33497,130.38263 523.25512,286.23628"
|
|
||||||
id="path9272"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="cc" />
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-style:normal;font-weight:normal;font-size:12.5px;line-height:125%;font-family:Sans;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"
|
|
||||||
x="575.56219"
|
|
||||||
y="156.53615"
|
|
||||||
id="text9274"
|
|
||||||
sodipodi:linespacing="125%"><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
id="tspan9276"
|
|
||||||
x="575.56219"
|
|
||||||
y="156.53615">delta</tspan><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
x="575.56219"
|
|
||||||
y="172.16115"
|
|
||||||
id="tspan9278">angle</tspan></text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 27 KiB |