mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-28 09:40:07 +01:00
Merge branch 'master' into tablet-support
This commit is contained in:
commit
a7bd84a7ee
45 changed files with 11641 additions and 3808 deletions
|
|
@ -1,7 +1,7 @@
|
|||
AC_PREREQ([2.64])
|
||||
|
||||
m4_define([libinput_major_version], [0])
|
||||
m4_define([libinput_minor_version], [19])
|
||||
m4_define([libinput_minor_version], [20])
|
||||
m4_define([libinput_micro_version], [0])
|
||||
m4_define([libinput_version],
|
||||
[libinput_major_version.libinput_minor_version.libinput_micro_version])
|
||||
|
|
@ -31,7 +31,7 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
|
|||
# b) If interfaces have been changed or added, but binary compatibility has
|
||||
# been preserved, change to C+1:0:A+1
|
||||
# c) If the interface is the same as the previous version, change to C:R+1:A
|
||||
LIBINPUT_LT_VERSION=13:0:3
|
||||
LIBINPUT_LT_VERSION=14:0:4
|
||||
AC_SUBST(LIBINPUT_LT_VERSION)
|
||||
|
||||
AM_SILENT_RULES([yes])
|
||||
|
|
|
|||
|
|
@ -17,12 +17,14 @@ header_files = \
|
|||
$(srcdir)/gestures.dox \
|
||||
$(srcdir)/normalization-of-relative-motion.dox \
|
||||
$(srcdir)/palm-detection.dox \
|
||||
$(srcdir)/page-hierarchy.dox \
|
||||
$(srcdir)/scrolling.dox \
|
||||
$(srcdir)/seats.dox \
|
||||
$(srcdir)/t440-support.dox \
|
||||
$(srcdir)/tablet-support.dox \
|
||||
$(srcdir)/tapping.dox \
|
||||
$(srcdir)/test-suite.dox
|
||||
$(srcdir)/test-suite.dox \
|
||||
$(srcdir)/tools.dox
|
||||
|
||||
diagram_files = \
|
||||
$(srcdir)/dot/seats-sketch.gv \
|
||||
|
|
@ -38,11 +40,18 @@ diagram_files = \
|
|||
$(srcdir)/svg/pinch-gestures.svg \
|
||||
$(srcdir)/svg/swipe-gestures.svg \
|
||||
$(srcdir)/svg/tap-n-drag.svg \
|
||||
$(srcdir)/svg/thumb-detection.svg \
|
||||
$(srcdir)/svg/top-software-buttons.svg \
|
||||
$(srcdir)/svg/touchscreen-gestures.svg \
|
||||
$(srcdir)/svg/twofinger-scrolling.svg
|
||||
|
||||
html/index.html: libinput.doxygen $(header_files) $(diagram_files)
|
||||
style_files = \
|
||||
style/header.html \
|
||||
style/footer.html \
|
||||
style/customdoxygen.css \
|
||||
style/bootstrap.css
|
||||
|
||||
html/index.html: libinput.doxygen $(header_files) $(diagram_files) $(style_files)
|
||||
$(AM_V_GEN)(cat $<; \
|
||||
echo "INPUT = $(header_files)"; \
|
||||
) | $(DOXYGEN) -
|
||||
|
|
@ -51,8 +60,11 @@ clean-local:
|
|||
$(AM_V_at)rm -rf html
|
||||
|
||||
doc_src= $(shell find html -type f -printf "html/%P\n" 2>/dev/null)
|
||||
EXTRA_DIST += $(builddir)/html/index.html $(doc_src) $(diagram_files) $(header_files)
|
||||
|
||||
EXTRA_DIST += $(builddir)/html/index.html \
|
||||
$(doc_src) \
|
||||
$(diagram_files) \
|
||||
$(header_files) \
|
||||
$(style_files)
|
||||
endif
|
||||
|
||||
# make sure doc was built before running dist
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
34
doc/page-hierarchy.dox
Normal file
34
doc/page-hierarchy.dox
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
@page touchpads Touchpads
|
||||
|
||||
- @subpage scrolling
|
||||
- @subpage clickpad_softbuttons
|
||||
- @subpage tapping
|
||||
- @subpage gestures
|
||||
- @subpage palm_detection
|
||||
- @subpage t440_support
|
||||
|
||||
@page touchscreens Touchscreens
|
||||
|
||||
- @subpage absolute_axes
|
||||
|
||||
@page pointers Mice, Trackballs, etc.
|
||||
|
||||
- @subpage motion_normalization
|
||||
|
||||
@page general General setup
|
||||
|
||||
- @subpage udev_config
|
||||
- @subpage seats
|
||||
|
||||
@page misc Users
|
||||
|
||||
- @subpage faq
|
||||
- @subpage tools
|
||||
|
||||
@page developers Developers
|
||||
|
||||
- @subpage test-suite
|
||||
- @subpage tools
|
||||
|
||||
*/
|
||||
|
|
@ -80,4 +80,32 @@ Notable behaviors of libinput's disable-while-typing feature:
|
|||
- Physical buttons work even while the touchpad is disabled. This includes
|
||||
software-emulated buttons.
|
||||
|
||||
@section thumb-detection Thumb detection
|
||||
|
||||
Many users rest their thumb on the touchpad while using the index finger to
|
||||
move the finger around. For clicks, often the thumb is used rather than the
|
||||
finger. The thumb should otherwise be ignored as a touch, i.e. it should not
|
||||
count towards @ref clickfinger and it should not cause a single-finger
|
||||
movement to trigger @ref twofinger_scrolling.
|
||||
|
||||
libinput uses two triggers for thumb detection: pressure and
|
||||
location. A touch exceeding a pressure threshold is considered a thumb if it
|
||||
is within the thumb detection zone.
|
||||
|
||||
@note "Pressure" on touchpads is synonymous with "contact area", a large
|
||||
touch surface area has a higher pressure and thus hints at a thumb or palm
|
||||
touching the surface.
|
||||
|
||||
Pressure readings are unreliable at the far bottom of the touchpad as a
|
||||
thumb hanging mostly off the touchpad will have a small surface area.
|
||||
libinput has a definitive thumb zone where any touch is considered a resting
|
||||
thumb.
|
||||
|
||||
@image html thumb-detection.svg
|
||||
|
||||
The picture above shows the two detection areas. In the larger (light red)
|
||||
area, a touch is labelled as thumb when it exceeds a device-specific
|
||||
pressure threshold. In the lower (dark red) area, a touch is labelled as
|
||||
thumb if it remains in that area for a time without moving outside.
|
||||
|
||||
*/
|
||||
|
|
|
|||
229
doc/style/LICENSE
Normal file
229
doc/style/LICENSE
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
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/style/bootstrap.css
vendored
Normal file
7500
doc/style/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load diff
255
doc/style/customdoxygen.css
Normal file
255
doc/style/customdoxygen.css
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
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;
|
||||
}
|
||||
|
||||
26
doc/style/footer.html
Normal file
26
doc/style/footer.html
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<!-- 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>
|
||||
42
doc/style/header.html
Normal file
42
doc/style/header.html
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<!-- 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
|
||||
|
||||
<link href="bootstrap.css" rel="stylesheet" type="text/css" />
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="doxy-boot.js"></script>
|
||||
</head>
|
||||
<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 -->
|
||||
116
doc/svg/thumb-detection.svg
Normal file
116
doc/svg/thumb-detection.svg
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
<?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="thumb-detection.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.979899"
|
||||
inkscape:cx="270.39655"
|
||||
inkscape:cy="139.75035"
|
||||
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 />
|
||||
</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:0.97031647;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4788"
|
||||
width="307.88782"
|
||||
height="45.628574"
|
||||
x="262.8418"
|
||||
y="421.0347" />
|
||||
<rect
|
||||
y="445.40848"
|
||||
x="262.68912"
|
||||
height="21.407471"
|
||||
width="308.19318"
|
||||
id="rect4149"
|
||||
style="opacity:0.92000002;fill:#7b0000;fill-opacity:0.2983426;stroke:#000000;stroke-width:0.66495597;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<g
|
||||
id="g4151">
|
||||
<path
|
||||
sodipodi:nodetypes="sszzzcss"
|
||||
d="m 353.70196,495.15765 c -24.01774,-7.29937 -29.0012,-10.10221 -30.51977,-10.54973 -10.67294,-3.14527 -18.27051,-5.54063 -23.77758,-13.4704 -5.50707,-7.92977 -5.34967,-20.78347 8.87612,-26.31604 14.2258,-5.53257 39.34351,8.79597 60.13061,16.16341 20.7871,7.36744 33.04563,11.44545 39.33422,13.87551 -8.10022,18.05041 -7.22129,21.15857 -10.11054,33.34117 -0.0481,0.20261 -17.87459,-5.12433 -43.93306,-13.04392 z"
|
||||
id="path2824-1-1-3"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00100005;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
d="m 324.44991,483.39364 c -10.67294,-1.94747 -17.88441,-5.64478 -21.62691,-8.75386 -8.11652,-9.03765 -6.31775,-15.03428 -3.3272,-13.99784 8.90495,-0.9097 30.20384,9.01528 33.86042,10.17935 -5.80268,11.37909 -1.08919,13.70271 -8.90631,12.57235 z"
|
||||
id="path2824-7-1-4-3"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.92000002;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;enable-background:accumulate"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<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>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.3 KiB |
102
doc/tools.dox
Normal file
102
doc/tools.dox
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
@page tools Helper tools
|
||||
|
||||
libinput provides a couple of tools to query state and events. Two of these
|
||||
tools are usually installed, others are @ref developer_tools only.
|
||||
|
||||
@section user_tools User tools
|
||||
|
||||
libinput ships with two tools to gather information about devices:
|
||||
@ref libinput-list-devices and @ref libinput-debug-events. Both tools must
|
||||
be run as root to have acess to the kernel's @c /dev/input/event* device
|
||||
files.
|
||||
|
||||
@subsection libinput-list-devices
|
||||
|
||||
The libinput-list-devices tool shows information about devices recognized by
|
||||
libinput and can help identifying why a device behaves different than
|
||||
expected. For example, if a device does not show up in the output, it is not
|
||||
a supported input device.
|
||||
|
||||
@verbatim
|
||||
$ sudo libinput-list-devices
|
||||
[...]
|
||||
Device: SynPS/2 Synaptics TouchPad
|
||||
Kernel: /dev/input/event4
|
||||
Group: 9
|
||||
Seat: seat0, default
|
||||
Size: 97.33x66.86mm
|
||||
Capabilities: pointer
|
||||
Tap-to-click: disabled
|
||||
Tap drag lock: disabled
|
||||
Left-handed: disabled
|
||||
Nat.scrolling: disabled
|
||||
Middle emulation: n/a
|
||||
Calibration: n/a
|
||||
Scroll methods: *two-finger
|
||||
Click methods: *button-areas clickfinger
|
||||
[...]
|
||||
@endverbatim
|
||||
|
||||
The above listing shows example output for a touchpad. The
|
||||
libinput-list-devices tool lists general information about the device (the
|
||||
kernel event node) but also the configuration options. If an option is
|
||||
"n/a" it does not exist on this device. Otherwise, the tool will show the
|
||||
default configuration for this device, for options that have more than a
|
||||
binary state all available options are listed, with the default one prefixed
|
||||
with an asterisk (*). In the example above, the default click method is
|
||||
button-areas but clickinger is available.
|
||||
|
||||
Note that the default configuration may differ from the configuration
|
||||
applied by the desktop environment.
|
||||
|
||||
@note This tool is intended to be human-readable and may change its output
|
||||
at any time.
|
||||
|
||||
@subsection libinput-debug-events
|
||||
This is an installed version of the @ref event-debug developer tool. It
|
||||
prints events from devices and can help to identify why a device behaves
|
||||
different than expected.
|
||||
|
||||
@verbatim
|
||||
$ sudo libinput-debug-events --enable-tapping --set-click-method=clickfinger
|
||||
@endverbatim
|
||||
|
||||
See the man page or the @c --help output for information about the available
|
||||
options.
|
||||
|
||||
@section developer_tools Developer tools
|
||||
|
||||
The two most common tools used by developers are @ref event-debug and @ref
|
||||
event-gui.
|
||||
|
||||
@subsection event-debug
|
||||
This is the in-tree version of the @ref libinput-debug-events tool and is
|
||||
linked to allow for easy debugging (i.e. it avoids libtool shenanigans). The
|
||||
code is the same. For debugging, run it against a single device only and
|
||||
enable the --verbose flag. This will print the various state machine
|
||||
transitions in addition to the events.
|
||||
|
||||
@verbatim
|
||||
$ sudo ./tools/event-debug --verbose --device /dev/input/event3
|
||||
@endverbatim
|
||||
|
||||
See the @c --help output for information about the available options.
|
||||
|
||||
@subsection event-gui
|
||||
|
||||
A simple GTK-based graphical tool that shows the behavior and location of
|
||||
touch events, pointer motion, scroll axes and gestures. Since this tool
|
||||
gathers data directly from libinput, it is thus suitable for
|
||||
pointer-acceleration testing.
|
||||
|
||||
@verbatim
|
||||
$ sudo ./tools/event-gui
|
||||
@endverbatim
|
||||
|
||||
See the @c --help output for information about the available options.
|
||||
|
||||
@note The @c --grab flag puts an exclusive @c EVIOCGRAB on the device to
|
||||
avoid interference with the desktiop while testing.
|
||||
|
||||
*/
|
||||
|
|
@ -43,8 +43,6 @@
|
|||
* as-is.
|
||||
*/
|
||||
|
||||
#define CASE_RETURN_STRING(a) case a: return #a;
|
||||
|
||||
static inline const char*
|
||||
middlebutton_state_to_str(enum evdev_middlebutton_state state)
|
||||
{
|
||||
|
|
@ -612,7 +610,7 @@ evdev_middlebutton_filter_button(struct evdev_device *device,
|
|||
if (button < BTN_LEFT ||
|
||||
bit >= sizeof(device->middlebutton.button_mask) * 8) {
|
||||
log_bug_libinput(device->base.seat->libinput,
|
||||
"Button mask too small for %d\n",
|
||||
"Button mask too small for %s\n",
|
||||
libevdev_event_code_get_name(EV_KEY,
|
||||
button));
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -46,8 +46,6 @@
|
|||
* The state machine only affects the soft button area code.
|
||||
*/
|
||||
|
||||
#define CASE_RETURN_STRING(a) case a: return #a;
|
||||
|
||||
static inline const char*
|
||||
button_state_to_str(enum button_state state) {
|
||||
switch(state) {
|
||||
|
|
@ -530,7 +528,7 @@ tp_init_softbuttons(struct tp_dispatch *tp,
|
|||
width = device->abs.dimensions.x;
|
||||
height = device->abs.dimensions.y;
|
||||
|
||||
/* button height: 10mm or 15% orf the touchpad height,
|
||||
/* button height: 10mm or 15% or the touchpad height,
|
||||
whichever is smaller */
|
||||
if ((height * 0.15)/yres > 10) {
|
||||
tp->buttons.bottom_area.top_edge =
|
||||
|
|
@ -641,22 +639,19 @@ static enum libinput_config_click_method
|
|||
tp_click_get_default_method(struct tp_dispatch *tp)
|
||||
{
|
||||
struct evdev_device *device = tp->device;
|
||||
uint32_t clickfinger_models = EVDEV_MODEL_CHROMEBOOK |
|
||||
EVDEV_MODEL_SYSTEM76_BONOBO |
|
||||
EVDEV_MODEL_SYSTEM76_GALAGO |
|
||||
EVDEV_MODEL_SYSTEM76_KUDU |
|
||||
EVDEV_MODEL_CLEVO_W740SU;
|
||||
|
||||
if (!tp->buttons.is_clickpad)
|
||||
return LIBINPUT_CONFIG_CLICK_METHOD_NONE;
|
||||
else if (libevdev_get_id_vendor(tp->device->evdev) == VENDOR_ID_APPLE)
|
||||
return LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
|
||||
|
||||
switch (device->model) {
|
||||
case EVDEV_MODEL_CHROMEBOOK:
|
||||
case EVDEV_MODEL_SYSTEM76_BONOBO:
|
||||
case EVDEV_MODEL_SYSTEM76_GALAGO:
|
||||
case EVDEV_MODEL_SYSTEM76_KUDU:
|
||||
case EVDEV_MODEL_CLEVO_W740SU:
|
||||
if (device->model_flags & clickfinger_models)
|
||||
return LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
|
||||
}
|
||||
|
|
@ -688,7 +683,7 @@ tp_init_middlebutton_emulation(struct tp_dispatch *tp,
|
|||
if (!libevdev_has_event_code(device->evdev, EV_KEY, BTN_MIDDLE)) {
|
||||
enable_by_default = true;
|
||||
want_config_option = false;
|
||||
} else if (device->model == EVDEV_MODEL_ALPS_TOUCHPAD) {
|
||||
} else if (device->model_flags & EVDEV_MODEL_ALPS_TOUCHPAD) {
|
||||
enable_by_default = true;
|
||||
want_config_option = true;
|
||||
} else
|
||||
|
|
@ -812,7 +807,8 @@ tp_check_clickfinger_distance(struct tp_dispatch *tp,
|
|||
if (!t1 || !t2)
|
||||
return 0;
|
||||
|
||||
if (t1->is_thumb || t2->is_thumb)
|
||||
if (t1->thumb.state == THUMB_STATE_YES ||
|
||||
t2->thumb.state == THUMB_STATE_YES)
|
||||
return 0;
|
||||
|
||||
x = abs(t1->point.x - t2->point.x);
|
||||
|
|
@ -874,6 +870,9 @@ tp_clickfinger_set_button(struct tp_dispatch *tp)
|
|||
if (t->state != TOUCH_BEGIN && t->state != TOUCH_UPDATE)
|
||||
continue;
|
||||
|
||||
if (t->thumb.state == THUMB_STATE_YES)
|
||||
continue;
|
||||
|
||||
if (!first)
|
||||
first = t;
|
||||
else if (!second)
|
||||
|
|
@ -904,9 +903,8 @@ out:
|
|||
case 0:
|
||||
case 1: button = BTN_LEFT; break;
|
||||
case 2: button = BTN_RIGHT; break;
|
||||
case 3: button = BTN_MIDDLE; break;
|
||||
default:
|
||||
button = 0;
|
||||
button = BTN_MIDDLE; break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -971,7 +969,6 @@ tp_post_clickpadbutton_buttons(struct tp_dispatch *tp, uint64_t time)
|
|||
|
||||
current = tp->buttons.state;
|
||||
old = tp->buttons.old_state;
|
||||
button = 0;
|
||||
is_top = 0;
|
||||
|
||||
if (!tp->buttons.click_pending && current == old)
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@
|
|||
|
||||
#include "evdev-mt-touchpad.h"
|
||||
|
||||
#define CASE_RETURN_STRING(a) case a: return #a
|
||||
|
||||
/* Use a reasonably large threshold until locked into scrolling mode, to
|
||||
avoid accidentally locking in scrolling mode when trying to use the entire
|
||||
touchpad to move the pointer. The user can wait for the timeout to trigger
|
||||
|
|
@ -287,30 +285,11 @@ int
|
|||
tp_edge_scroll_init(struct tp_dispatch *tp, struct evdev_device *device)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
int width, height;
|
||||
int edge_width, edge_height;
|
||||
|
||||
width = device->abs.dimensions.x;
|
||||
height = device->abs.dimensions.y;
|
||||
|
||||
switch (tp->model) {
|
||||
case MODEL_ALPS:
|
||||
edge_width = width * .15;
|
||||
edge_height = height * .15;
|
||||
break;
|
||||
case MODEL_APPLETOUCH: /* unibody are all clickpads, so N/A */
|
||||
edge_width = width * .085;
|
||||
edge_height = height * .085;
|
||||
break;
|
||||
default:
|
||||
/* For elantech and synaptics, note for lenovo #40 series,
|
||||
* e.g. the T440s min/max are the absolute edges, not the
|
||||
* recommended ones as usual with synaptics.
|
||||
*/
|
||||
edge_width = width * .04;
|
||||
edge_height = height * .054;
|
||||
break;
|
||||
}
|
||||
/* 7mm edge size */
|
||||
edge_width = device->abs.absinfo_x->resolution * 7;
|
||||
edge_height = device->abs.absinfo_y->resolution * 7;
|
||||
|
||||
tp->scroll.right_edge = device->abs.absinfo_x->maximum - edge_width;
|
||||
tp->scroll.bottom_edge = device->abs.absinfo_y->maximum - edge_height;
|
||||
|
|
@ -381,6 +360,11 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
if (t->palm.state != PALM_NONE)
|
||||
continue;
|
||||
|
||||
/* only scroll with the finger in the previous edge */
|
||||
if (t->scroll.edge &&
|
||||
(tp_touch_get_edge(tp, t) & t->scroll.edge) == 0)
|
||||
continue;
|
||||
|
||||
switch (t->scroll.edge) {
|
||||
case EDGE_NONE:
|
||||
if (t->scroll.direction != -1) {
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@
|
|||
#define DEFAULT_GESTURE_SWITCH_TIMEOUT 100 /* ms */
|
||||
#define DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT 1000 /* ms */
|
||||
|
||||
#define CASE_RETURN_STRING(a) case a: return #a
|
||||
|
||||
static inline const char*
|
||||
gesture_state_to_str(enum tp_gesture_2fg_state state)
|
||||
{
|
||||
|
|
@ -195,9 +193,10 @@ tp_gesture_get_direction(struct tp_dispatch *tp, struct tp_touch *touch)
|
|||
if (tp->semi_mt)
|
||||
move_threshold = TP_MM_TO_DPI_NORMALIZED(4);
|
||||
else
|
||||
move_threshold = TP_MM_TO_DPI_NORMALIZED(3);
|
||||
move_threshold = TP_MM_TO_DPI_NORMALIZED(2);
|
||||
|
||||
delta = device_delta(touch->point, touch->gesture.initial);
|
||||
|
||||
normalized = tp_normalize_delta(tp, delta);
|
||||
|
||||
if (normalized_length(normalized) < move_threshold)
|
||||
|
|
@ -546,34 +545,15 @@ tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
{
|
||||
unsigned int active_touches = 0;
|
||||
struct tp_touch *t;
|
||||
uint32_t old_thumb_mask, thumb_mask = 0;
|
||||
int i = 0;
|
||||
|
||||
tp_for_each_touch(tp, t) {
|
||||
if (tp_touch_active(tp, t))
|
||||
active_touches++;
|
||||
|
||||
if (t->is_thumb)
|
||||
thumb_mask |= 1 << i;
|
||||
i++;
|
||||
}
|
||||
|
||||
old_thumb_mask = tp->gesture.thumb_mask;
|
||||
tp->gesture.thumb_mask = thumb_mask;
|
||||
|
||||
/* active touches does not include thumb touches, need to count those
|
||||
* separately, in a bitmask.
|
||||
* then, if the finger count changes and/or the thumb count changes
|
||||
* -> cancel gesture.
|
||||
*/
|
||||
if (thumb_mask != old_thumb_mask) {
|
||||
/* if a thumb is detected during a gesture, that gesture is
|
||||
* cancelled and the user effectively needs to restart. we
|
||||
* could be smarter, but the complexity isn't worth it */
|
||||
tp_gesture_cancel(tp, time);
|
||||
return;
|
||||
}
|
||||
|
||||
if (active_touches != tp->gesture.finger_count) {
|
||||
/* If all fingers are lifted immediately end the gesture */
|
||||
if (active_touches == 0) {
|
||||
|
|
|
|||
|
|
@ -35,8 +35,6 @@
|
|||
|
||||
#include "evdev-mt-touchpad.h"
|
||||
|
||||
#define CASE_RETURN_STRING(a) case a: return #a
|
||||
|
||||
#define DEFAULT_TAP_TIMEOUT_PERIOD 180
|
||||
#define DEFAULT_DRAG_TIMEOUT_PERIOD 300
|
||||
#define DEFAULT_TAP_MOVE_THRESHOLD TP_MM_TO_DPI_NORMALIZED(3)
|
||||
|
|
@ -98,7 +96,6 @@ tap_event_to_str(enum tap_event event)
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
#undef CASE_RETURN_STRING
|
||||
|
||||
static void
|
||||
tp_tap_notify(struct tp_dispatch *tp,
|
||||
|
|
@ -743,7 +740,7 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
/* The simple version: if a touch is a thumb on
|
||||
* begin we ignore it. All other thumb touches
|
||||
* follow the normal tap state for now */
|
||||
if (t->is_thumb) {
|
||||
if (t->thumb.state == THUMB_STATE_YES) {
|
||||
t->tap.is_thumb = true;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -775,7 +772,7 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
|
||||
tp_tap_handle_event(tp, t, TAP_EVENT_MOTION, time);
|
||||
} else if (tp->tap.state != TAP_STATE_IDLE &&
|
||||
t->is_thumb &&
|
||||
t->thumb.state == THUMB_STATE_YES &&
|
||||
!t->tap.is_thumb) {
|
||||
tp_tap_handle_event(tp, t, TAP_EVENT_THUMB, time);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,10 +30,6 @@
|
|||
|
||||
#include "evdev-mt-touchpad.h"
|
||||
|
||||
/* Number found by trial-and error, seems to be 1200, divided by the
|
||||
* TP_MAGIC_SLOWDOWN in filter.c */
|
||||
#define DEFAULT_ACCEL_NUMERATOR 3000.0
|
||||
#define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
|
||||
#define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT 300 /* ms */
|
||||
#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1 200 /* ms */
|
||||
#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2 500 /* ms */
|
||||
|
|
@ -212,7 +208,8 @@ tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
t->millis = time;
|
||||
tp->nfingers_down++;
|
||||
t->palm.time = time;
|
||||
t->is_thumb = false;
|
||||
t->thumb.state = THUMB_STATE_MAYBE;
|
||||
t->thumb.first_touch_time = time;
|
||||
t->tap.is_thumb = false;
|
||||
assert(tp->nfingers_down >= 1);
|
||||
}
|
||||
|
|
@ -318,6 +315,8 @@ tp_process_absolute(struct tp_dispatch *tp,
|
|||
break;
|
||||
case ABS_MT_PRESSURE:
|
||||
t->pressure = e->value;
|
||||
t->dirty = true;
|
||||
tp->queued |= TOUCHPAD_EVENT_MOTION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -345,6 +344,40 @@ tp_process_absolute_st(struct tp_dispatch *tp,
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
tp_restore_synaptics_touches(struct tp_dispatch *tp,
|
||||
uint64_t time)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int nfake_touches;
|
||||
|
||||
nfake_touches = tp_fake_finger_count(tp);
|
||||
if (nfake_touches < 3)
|
||||
return;
|
||||
|
||||
if (tp->nfingers_down >= nfake_touches ||
|
||||
tp->nfingers_down == tp->num_slots)
|
||||
return;
|
||||
|
||||
/* Synaptics devices may end touch 2 on BTN_TOOL_TRIPLETAP
|
||||
* and start it again on the next frame with different coordinates
|
||||
* (#91352). We search the touches we have, if there is one that has
|
||||
* just ended despite us being on tripletap, we move it back to
|
||||
* update.
|
||||
*/
|
||||
for (i = 0; i < tp->num_slots; i++) {
|
||||
struct tp_touch *t = tp_get_touch(tp, i);
|
||||
|
||||
if (t->state != TOUCH_END)
|
||||
continue;
|
||||
|
||||
/* new touch, move it through begin to update immediately */
|
||||
tp_new_touch(tp, t, time);
|
||||
tp_begin_touch(tp, t, time);
|
||||
t->state = TOUCH_UPDATE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_process_fake_touches(struct tp_dispatch *tp,
|
||||
uint64_t time)
|
||||
|
|
@ -357,6 +390,10 @@ tp_process_fake_touches(struct tp_dispatch *tp,
|
|||
if (nfake_touches == FAKE_FINGER_OVERFLOW)
|
||||
return;
|
||||
|
||||
if (tp->device->model_flags &
|
||||
EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD)
|
||||
tp_restore_synaptics_touches(tp, time);
|
||||
|
||||
start = tp->has_mt ? tp->num_slots : 0;
|
||||
for (i = start; i < tp->ntouches; i++) {
|
||||
t = tp_get_touch(tp, i);
|
||||
|
|
@ -375,8 +412,7 @@ tp_process_trackpoint_button(struct tp_dispatch *tp,
|
|||
struct evdev_dispatch *dispatch;
|
||||
struct input_event event;
|
||||
|
||||
if (!tp->buttons.trackpoint ||
|
||||
(tp->device->tags & EVDEV_TAG_TOUCHPAD_TRACKPOINT) == 0)
|
||||
if (!tp->buttons.trackpoint)
|
||||
return;
|
||||
|
||||
dispatch = tp->buttons.trackpoint->dispatch;
|
||||
|
|
@ -442,8 +478,8 @@ tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
ydist = abs(t->point.y - t->pinned.center.y);
|
||||
ydist *= tp->buttons.motion_dist.y_scale_coeff;
|
||||
|
||||
/* 3mm movement -> unpin */
|
||||
if (vector_length(xdist, ydist) >= 3.0) {
|
||||
/* 1.5mm movement -> unpin */
|
||||
if (hypot(xdist, ydist) >= 1.5) {
|
||||
t->pinned.is_pinned = false;
|
||||
return;
|
||||
}
|
||||
|
|
@ -466,7 +502,7 @@ tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
|
||||
t->palm.state == PALM_NONE &&
|
||||
!t->pinned.is_pinned &&
|
||||
!t->is_thumb &&
|
||||
t->thumb.state != THUMB_STATE_YES &&
|
||||
tp_button_touch_active(tp, t) &&
|
||||
tp_edge_scroll_touch_active(tp, t);
|
||||
}
|
||||
|
|
@ -495,7 +531,8 @@ tp_palm_tap_is_palm(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
static int
|
||||
tp_palm_detect_dwt(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
||||
{
|
||||
if (tp->dwt.keyboard_active &&
|
||||
if (tp->dwt.dwt_enabled &&
|
||||
tp->dwt.keyboard_active &&
|
||||
t->state == TOUCH_BEGIN) {
|
||||
t->palm.state = PALM_TYPING;
|
||||
t->palm.first = t->point;
|
||||
|
|
@ -608,20 +645,63 @@ out:
|
|||
t->palm.state == PALM_TYPING ? "typing" : "trackpoint");
|
||||
}
|
||||
|
||||
static void
|
||||
tp_thumb_detect(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
static inline const char*
|
||||
thumb_state_to_str(enum tp_thumb_state state)
|
||||
{
|
||||
/* once a thumb, always a thumb */
|
||||
if (!tp->thumb.detect_thumbs || t->is_thumb)
|
||||
switch(state){
|
||||
CASE_RETURN_STRING(THUMB_STATE_NO);
|
||||
CASE_RETURN_STRING(THUMB_STATE_YES);
|
||||
CASE_RETURN_STRING(THUMB_STATE_MAYBE);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_thumb_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
||||
{
|
||||
enum tp_thumb_state state = t->thumb.state;
|
||||
|
||||
/* once a thumb, always a thumb, once ruled out always ruled out */
|
||||
if (!tp->thumb.detect_thumbs ||
|
||||
t->thumb.state != THUMB_STATE_MAYBE)
|
||||
return;
|
||||
|
||||
if (t->point.y < tp->thumb.upper_thumb_line) {
|
||||
/* if a potential thumb is above the line, it won't ever
|
||||
* label as thumb */
|
||||
t->thumb.state = THUMB_STATE_NO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If the thumb moves by more than 7mm, it's not a resting thumb */
|
||||
if (t->state == TOUCH_BEGIN)
|
||||
t->thumb.initial = t->point;
|
||||
else if (t->state == TOUCH_UPDATE) {
|
||||
struct device_float_coords delta;
|
||||
struct normalized_coords normalized;
|
||||
|
||||
delta = device_delta(t->point, t->thumb.initial);
|
||||
normalized = tp_normalize_delta(tp, delta);
|
||||
if (normalized_length(normalized) >
|
||||
TP_MM_TO_DPI_NORMALIZED(7)) {
|
||||
t->thumb.state = THUMB_STATE_NO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: a thumb at the edge of the touchpad won't trigger the
|
||||
* threshold, the surface areas is usually too small.
|
||||
* threshold, the surface area is usually too small. So we have a
|
||||
* two-stage detection: pressure and time within the area.
|
||||
* A finger that remains at the very bottom of the touchpad becomes
|
||||
* a thumb.
|
||||
*/
|
||||
if (t->pressure < tp->thumb.threshold)
|
||||
return;
|
||||
|
||||
t->is_thumb = true;
|
||||
if (t->pressure > tp->thumb.threshold)
|
||||
t->thumb.state = THUMB_STATE_YES;
|
||||
else if (t->point.y > tp->thumb.lower_thumb_line &&
|
||||
tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE &&
|
||||
t->thumb.first_touch_time + 300 < time)
|
||||
t->thumb.state = THUMB_STATE_YES;
|
||||
|
||||
/* now what? we marked it as thumb, so:
|
||||
*
|
||||
|
|
@ -629,10 +709,16 @@ tp_thumb_detect(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
* - clickfinger must ignore this touch for finger count
|
||||
* - software buttons are unaffected
|
||||
* - edge scrolling unaffected
|
||||
* - gestures: cancel
|
||||
* - gestures: unaffected
|
||||
* - tapping: honour thumb on begin, ignore it otherwise for now,
|
||||
* this gets a tad complicated otherwise
|
||||
*/
|
||||
out:
|
||||
if (t->thumb.state != state)
|
||||
log_debug(tp_libinput_context(tp),
|
||||
"thumb state: %s → %s\n",
|
||||
thumb_state_to_str(state),
|
||||
thumb_state_to_str(t->thumb.state));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -726,34 +812,95 @@ tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
|
|||
|
||||
}
|
||||
|
||||
static inline void
|
||||
tp_position_fake_touches(struct tp_dispatch *tp)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
struct tp_touch *topmost = NULL;
|
||||
unsigned int start, i;
|
||||
|
||||
if (tp_fake_finger_count(tp) <= tp->num_slots)
|
||||
return;
|
||||
|
||||
/* We have at least one fake touch down. Find the top-most real
|
||||
* touch and copy its coordinates over to to all fake touches.
|
||||
* This is more reliable than just taking the first touch.
|
||||
*/
|
||||
for (i = 0; i < tp->num_slots; i++) {
|
||||
t = tp_get_touch(tp, i);
|
||||
if (t->state == TOUCH_END ||
|
||||
t->state == TOUCH_NONE)
|
||||
continue;
|
||||
|
||||
if (topmost == NULL || t->point.y < topmost->point.y)
|
||||
topmost = t;
|
||||
}
|
||||
|
||||
if (!topmost) {
|
||||
log_bug_libinput(tp_libinput_context(tp),
|
||||
"Unable to find topmost touch\n");
|
||||
return;
|
||||
}
|
||||
|
||||
start = tp->has_mt ? tp->num_slots : 1;
|
||||
for (i = start; i < tp->ntouches; i++) {
|
||||
t = tp_get_touch(tp, i);
|
||||
if (t->state == TOUCH_NONE)
|
||||
continue;
|
||||
|
||||
t->point = topmost->point;
|
||||
if (!t->dirty)
|
||||
t->dirty = topmost->dirty;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
tp_need_motion_history_reset(struct tp_dispatch *tp)
|
||||
{
|
||||
/* semi-mt finger postions may "jump" when nfingers changes */
|
||||
if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down)
|
||||
return true;
|
||||
|
||||
/* if we're transitioning between slots and fake touches in either
|
||||
* direction, we may get a coordinate jump
|
||||
*/
|
||||
if (tp->nfingers_down != tp->old_nfingers_down &&
|
||||
(tp->nfingers_down > tp->num_slots ||
|
||||
tp->old_nfingers_down > tp->num_slots))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_process_state(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
struct tp_touch *first = tp_get_touch(tp, 0);
|
||||
unsigned int i;
|
||||
bool restart_filter = false;
|
||||
bool want_motion_reset;
|
||||
|
||||
tp_process_fake_touches(tp, time);
|
||||
tp_unhover_touches(tp, time);
|
||||
tp_position_fake_touches(tp);
|
||||
|
||||
want_motion_reset = tp_need_motion_history_reset(tp);
|
||||
|
||||
for (i = 0; i < tp->ntouches; i++) {
|
||||
t = tp_get_touch(tp, i);
|
||||
|
||||
/* semi-mt finger postions may "jump" when nfingers changes */
|
||||
if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down)
|
||||
if (want_motion_reset) {
|
||||
tp_motion_history_reset(t);
|
||||
|
||||
if (i >= tp->num_slots && t->state != TOUCH_NONE) {
|
||||
t->point = first->point;
|
||||
if (!t->dirty)
|
||||
t->dirty = first->dirty;
|
||||
t->quirks.reset_motion_history = true;
|
||||
} else if (t->quirks.reset_motion_history) {
|
||||
tp_motion_history_reset(t);
|
||||
t->quirks.reset_motion_history = false;
|
||||
}
|
||||
|
||||
if (!t->dirty)
|
||||
continue;
|
||||
|
||||
tp_thumb_detect(tp, t);
|
||||
tp_thumb_detect(tp, t, time);
|
||||
tp_palm_detect(tp, t, time);
|
||||
|
||||
tp_motion_hysteresis(tp, t);
|
||||
|
|
@ -1069,6 +1216,9 @@ tp_keyboard_event(uint64_t time, struct libinput_event *event, void *data)
|
|||
struct libinput_event_keyboard *kbdev;
|
||||
unsigned int timeout;
|
||||
|
||||
if (!tp->dwt.dwt_enabled)
|
||||
return;
|
||||
|
||||
if (event->type != LIBINPUT_EVENT_KEYBOARD_KEY)
|
||||
return;
|
||||
|
||||
|
|
@ -1099,6 +1249,22 @@ tp_keyboard_event(uint64_t time, struct libinput_event *event, void *data)
|
|||
time + timeout);
|
||||
}
|
||||
|
||||
static bool
|
||||
tp_dwt_device_is_blacklisted(struct evdev_device *device)
|
||||
{
|
||||
unsigned int bus = libevdev_get_id_bustype(device->evdev);
|
||||
|
||||
/* evemu will set the right bus type */
|
||||
if (bus == BUS_BLUETOOTH || bus == BUS_VIRTUAL)
|
||||
return true;
|
||||
|
||||
/* Wacom makes touchpads, but not internal ones */
|
||||
if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_WACOM)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
tp_want_dwt(struct evdev_device *touchpad,
|
||||
struct evdev_device *keyboard)
|
||||
|
|
@ -1106,11 +1272,8 @@ tp_want_dwt(struct evdev_device *touchpad,
|
|||
unsigned int bus_tp = libevdev_get_id_bustype(touchpad->evdev),
|
||||
bus_kbd = libevdev_get_id_bustype(keyboard->evdev);
|
||||
|
||||
if (bus_tp == BUS_BLUETOOTH || bus_kbd == BUS_BLUETOOTH)
|
||||
return false;
|
||||
|
||||
/* evemu will set the right bus type */
|
||||
if (bus_tp == BUS_VIRTUAL || bus_kbd == BUS_VIRTUAL)
|
||||
if (tp_dwt_device_is_blacklisted(touchpad) ||
|
||||
tp_dwt_device_is_blacklisted(keyboard))
|
||||
return false;
|
||||
|
||||
/* If the touchpad is on serio, the keyboard is too, so ignore any
|
||||
|
|
@ -1118,10 +1281,6 @@ tp_want_dwt(struct evdev_device *touchpad,
|
|||
if (bus_tp == BUS_I8042 && bus_kbd != bus_tp)
|
||||
return false;
|
||||
|
||||
/* Wacom makes touchpads, but not internal ones */
|
||||
if (libevdev_get_id_vendor(touchpad->evdev) == VENDOR_ID_WACOM)
|
||||
return false;
|
||||
|
||||
/* everything else we don't really know, so we have to assume
|
||||
they go together */
|
||||
|
||||
|
|
@ -1228,14 +1387,10 @@ evdev_tag_touchpad(struct evdev_device *device,
|
|||
*/
|
||||
bustype = libevdev_get_id_bustype(device->evdev);
|
||||
if (bustype == BUS_USB) {
|
||||
if (device->model == EVDEV_MODEL_APPLE_TOUCHPAD)
|
||||
if (device->model_flags & EVDEV_MODEL_APPLE_TOUCHPAD)
|
||||
device->tags |= EVDEV_TAG_INTERNAL_TOUCHPAD;
|
||||
} else if (bustype != BUS_BLUETOOTH)
|
||||
device->tags |= EVDEV_TAG_INTERNAL_TOUCHPAD;
|
||||
|
||||
if (udev_device_get_property_value(udev_device,
|
||||
"TOUCHPAD_HAS_TRACKPOINT_BUTTONS"))
|
||||
device->tags |= EVDEV_TAG_TOUCHPAD_TRACKPOINT;
|
||||
}
|
||||
|
||||
static struct evdev_dispatch_interface tp_interface = {
|
||||
|
|
@ -1355,14 +1510,10 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal)
|
|||
tp->accel.x_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_x;
|
||||
tp->accel.y_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_y;
|
||||
|
||||
switch (tp->device->model) {
|
||||
case EVDEV_MODEL_LENOVO_X230:
|
||||
if (tp->device->model_flags & EVDEV_MODEL_LENOVO_X230)
|
||||
profile = touchpad_lenovo_x230_accel_profile;
|
||||
break;
|
||||
default:
|
||||
else
|
||||
profile = touchpad_accel_profile_linear;
|
||||
break;
|
||||
}
|
||||
|
||||
if (evdev_device_init_pointer_acceleration(tp->device, profile) == -1)
|
||||
return -1;
|
||||
|
|
@ -1450,6 +1601,77 @@ tp_init_scroll(struct tp_dispatch *tp, struct evdev_device *device)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_dwt_config_is_available(struct libinput_device *device)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static enum libinput_config_status
|
||||
tp_dwt_config_set(struct libinput_device *device,
|
||||
enum libinput_config_dwt_state enable)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
|
||||
|
||||
switch(enable) {
|
||||
case LIBINPUT_CONFIG_DWT_ENABLED:
|
||||
case LIBINPUT_CONFIG_DWT_DISABLED:
|
||||
break;
|
||||
default:
|
||||
return LIBINPUT_CONFIG_STATUS_INVALID;
|
||||
}
|
||||
|
||||
tp->dwt.dwt_enabled = (enable == LIBINPUT_CONFIG_DWT_ENABLED);
|
||||
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static enum libinput_config_dwt_state
|
||||
tp_dwt_config_get(struct libinput_device *device)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
|
||||
|
||||
return tp->dwt.dwt_enabled ?
|
||||
LIBINPUT_CONFIG_DWT_ENABLED :
|
||||
LIBINPUT_CONFIG_DWT_DISABLED;
|
||||
}
|
||||
|
||||
static bool
|
||||
tp_dwt_default_enabled(struct tp_dispatch *tp)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static enum libinput_config_dwt_state
|
||||
tp_dwt_config_get_default(struct libinput_device *device)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
|
||||
|
||||
return tp_dwt_default_enabled(tp) ?
|
||||
LIBINPUT_CONFIG_DWT_ENABLED :
|
||||
LIBINPUT_CONFIG_DWT_DISABLED;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_init_dwt(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
if (tp_dwt_device_is_blacklisted(device))
|
||||
return 0;
|
||||
|
||||
tp->dwt.config.is_available = tp_dwt_config_is_available;
|
||||
tp->dwt.config.set_enabled = tp_dwt_config_set;
|
||||
tp->dwt.config.get_enabled = tp_dwt_config_get;
|
||||
tp->dwt.config.get_default_enabled = tp_dwt_config_get_default;
|
||||
tp->dwt.dwt_enabled = tp_dwt_default_enabled(tp);
|
||||
device->base.config.dwt = &tp->dwt.config;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_init_palmdetect(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
|
|
@ -1465,18 +1687,13 @@ tp_init_palmdetect(struct tp_dispatch *tp,
|
|||
|
||||
/* Wacom doesn't have internal touchpads,
|
||||
* Apple touchpads are always big enough to warrant palm detection */
|
||||
if (device->model == EVDEV_MODEL_WACOM_TOUCHPAD) {
|
||||
if (device->model_flags & EVDEV_MODEL_WACOM_TOUCHPAD)
|
||||
return 0;
|
||||
} else if (device->model != EVDEV_MODEL_APPLE_TOUCHPAD) {
|
||||
/* We don't know how big the touchpad is */
|
||||
if (device->abs.absinfo_x->resolution == 1)
|
||||
return 0;
|
||||
|
||||
/* Enable palm detection on touchpads >= 70 mm. Anything smaller
|
||||
probably won't need it, until we find out it does */
|
||||
if (width/device->abs.absinfo_x->resolution < 70)
|
||||
return 0;
|
||||
}
|
||||
/* Enable palm detection on touchpads >= 70 mm. Anything smaller
|
||||
probably won't need it, until we find out it does */
|
||||
if (width/device->abs.absinfo_x->resolution < 70)
|
||||
return 0;
|
||||
|
||||
/* palm edges are 5% of the width on each side */
|
||||
tp->palm.right_edge = device->abs.absinfo_x->maximum - width * 0.05;
|
||||
|
|
@ -1507,6 +1724,13 @@ tp_init_thumb(struct tp_dispatch *tp)
|
|||
{
|
||||
struct evdev_device *device = tp->device;
|
||||
const struct input_absinfo *abs;
|
||||
double w = 0.0, h = 0.0;
|
||||
int xres, yres;
|
||||
int ymax;
|
||||
double threshold;
|
||||
|
||||
if (!tp->buttons.is_clickpad)
|
||||
return 0;
|
||||
|
||||
abs = libevdev_get_abs_info(device->evdev, ABS_MT_PRESSURE);
|
||||
if (!abs)
|
||||
|
|
@ -1515,14 +1739,33 @@ tp_init_thumb(struct tp_dispatch *tp)
|
|||
if (abs->maximum - abs->minimum < 255)
|
||||
return 0;
|
||||
|
||||
/* The touchpads we looked at so far have a clear thumb threshold of
|
||||
* ~100, you don't reach that with a normal finger interaction.
|
||||
/* if the touchpad is less than 50mm high, skip thumb detection.
|
||||
* it's too small to meaningfully interact with a thumb on the
|
||||
* touchpad */
|
||||
evdev_device_get_size(device, &w, &h);
|
||||
if (h < 50)
|
||||
return 0;
|
||||
|
||||
/* Our reference touchpad is the T440s with 42x42 resolution.
|
||||
* Higher-res touchpads exhibit higher pressure for the same
|
||||
* interaction. On the T440s, the threshold value is 100, you don't
|
||||
* reach that with a normal finger interaction.
|
||||
* Note: "thumb" means massive touch that should not interact, not
|
||||
* "using the tip of my thumb for a pinch gestures".
|
||||
*/
|
||||
tp->thumb.threshold = 100;
|
||||
xres = tp->device->abs.absinfo_x->resolution;
|
||||
yres = tp->device->abs.absinfo_y->resolution;
|
||||
threshold = 100.0 * hypot(xres, yres)/hypot(42, 42);
|
||||
tp->thumb.threshold = max(100, threshold);
|
||||
tp->thumb.detect_thumbs = true;
|
||||
|
||||
/* detect thumbs by pressure in the bottom 15mm, detect thumbs by
|
||||
* lingering in the bottom 8mm */
|
||||
ymax = tp->device->abs.absinfo_y->maximum;
|
||||
yres = tp->device->abs.absinfo_y->resolution;
|
||||
tp->thumb.upper_thumb_line = ymax - yres * 15;
|
||||
tp->thumb.lower_thumb_line = ymax - yres * 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1546,7 +1789,8 @@ tp_sanity_check(struct tp_dispatch *tp,
|
|||
|
||||
error:
|
||||
log_bug_kernel(libinput,
|
||||
"device %s failed touchpad sanity checks\n");
|
||||
"device %s failed touchpad sanity checks\n",
|
||||
device->devname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -1629,6 +1873,9 @@ tp_init(struct tp_dispatch *tp,
|
|||
if (tp_init_buttons(tp, device) != 0)
|
||||
return -1;
|
||||
|
||||
if (tp_init_dwt(tp, device) != 0)
|
||||
return -1;
|
||||
|
||||
if (tp_init_palmdetect(tp, device) != 0)
|
||||
return -1;
|
||||
|
||||
|
|
|
|||
|
|
@ -136,17 +136,31 @@ enum tp_gesture_2fg_state {
|
|||
GESTURE_2FG_STATE_PINCH,
|
||||
};
|
||||
|
||||
enum tp_thumb_state {
|
||||
THUMB_STATE_NO,
|
||||
THUMB_STATE_YES,
|
||||
THUMB_STATE_MAYBE,
|
||||
};
|
||||
|
||||
struct tp_touch {
|
||||
struct tp_dispatch *tp;
|
||||
enum touch_state state;
|
||||
bool has_ended; /* TRACKING_ID == -1 */
|
||||
bool dirty;
|
||||
bool is_thumb;
|
||||
struct device_coords point;
|
||||
uint64_t millis;
|
||||
int distance; /* distance == 0 means touch */
|
||||
int pressure;
|
||||
|
||||
struct {
|
||||
/* A quirk mostly used on Synaptics touchpads. In a
|
||||
transition to/from fake touches > num_slots, the current
|
||||
event data is likely garbage and the subsequent event
|
||||
is likely too. This marker tells us to reset the motion
|
||||
history again -> this effectively swallows any motion */
|
||||
bool reset_motion_history;
|
||||
} quirks;
|
||||
|
||||
struct {
|
||||
struct device_coords samples[TOUCHPAD_HISTORY_LENGTH];
|
||||
unsigned int index;
|
||||
|
|
@ -195,6 +209,12 @@ struct tp_touch {
|
|||
struct {
|
||||
struct device_coords initial;
|
||||
} gesture;
|
||||
|
||||
struct {
|
||||
enum tp_thumb_state state;
|
||||
uint64_t first_touch_time;
|
||||
struct device_coords initial;
|
||||
} thumb;
|
||||
};
|
||||
|
||||
struct tp_dispatch {
|
||||
|
|
@ -237,7 +257,6 @@ struct tp_dispatch {
|
|||
double prev_scale;
|
||||
double angle;
|
||||
struct device_float_coords center;
|
||||
uint32_t thumb_mask;
|
||||
} gesture;
|
||||
|
||||
struct {
|
||||
|
|
@ -314,6 +333,9 @@ struct tp_dispatch {
|
|||
} sendevents;
|
||||
|
||||
struct {
|
||||
struct libinput_device_config_dwt config;
|
||||
bool dwt_enabled;
|
||||
|
||||
bool keyboard_active;
|
||||
struct libinput_event_listener keyboard_listener;
|
||||
struct libinput_timer keyboard_timer;
|
||||
|
|
@ -325,6 +347,8 @@ struct tp_dispatch {
|
|||
struct {
|
||||
bool detect_thumbs;
|
||||
int threshold;
|
||||
int upper_thumb_line;
|
||||
int lower_thumb_line;
|
||||
} thumb;
|
||||
};
|
||||
|
||||
|
|
|
|||
51
src/evdev.c
51
src/evdev.c
|
|
@ -563,7 +563,7 @@ evdev_process_touch(struct evdev_device *device,
|
|||
case ABS_MT_SLOT:
|
||||
if ((size_t)e->value >= device->mt.slots_len) {
|
||||
log_bug_libinput(device->base.seat->libinput,
|
||||
"%s exceeds slots (%d of %d)\n",
|
||||
"%s exceeds slots (%d of %zd)\n",
|
||||
device->devname,
|
||||
e->value,
|
||||
device->mt.slots_len);
|
||||
|
|
@ -1481,6 +1481,10 @@ evdev_get_trackpoint_dpi(struct evdev_device *device)
|
|||
DEFAULT_TRACKPOINT_ACCEL);
|
||||
accel = DEFAULT_TRACKPOINT_ACCEL;
|
||||
}
|
||||
log_info(libinput,
|
||||
"Device '%s' set to const accel %.2f\n",
|
||||
device->devname,
|
||||
accel);
|
||||
}
|
||||
|
||||
return DEFAULT_MOUSE_DPI / accel;
|
||||
|
|
@ -1522,8 +1526,8 @@ evdev_read_dpi_prop(struct evdev_device *device)
|
|||
return dpi;
|
||||
}
|
||||
|
||||
static inline enum evdev_device_model
|
||||
evdev_read_model(struct evdev_device *device)
|
||||
static inline uint32_t
|
||||
evdev_read_model_flags(struct evdev_device *device)
|
||||
{
|
||||
const struct model_map {
|
||||
const char *property;
|
||||
|
|
@ -1538,18 +1542,37 @@ evdev_read_model(struct evdev_device *device)
|
|||
{ "LIBINPUT_MODEL_APPLE_TOUCHPAD", EVDEV_MODEL_APPLE_TOUCHPAD },
|
||||
{ "LIBINPUT_MODEL_WACOM_TOUCHPAD", EVDEV_MODEL_WACOM_TOUCHPAD },
|
||||
{ "LIBINPUT_MODEL_ALPS_TOUCHPAD", EVDEV_MODEL_ALPS_TOUCHPAD },
|
||||
{ "LIBINPUT_MODEL_SYNAPTICS_SERIAL_TOUCHPAD", EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD },
|
||||
{ NULL, EVDEV_MODEL_DEFAULT },
|
||||
};
|
||||
const struct model_map *m = model_map;
|
||||
uint32_t model_flags = 0;
|
||||
|
||||
while (m->property) {
|
||||
if (!!udev_device_get_property_value(device->udev_device,
|
||||
m->property))
|
||||
break;
|
||||
model_flags |= m->model;
|
||||
m++;
|
||||
}
|
||||
|
||||
return m->model;
|
||||
return model_flags;
|
||||
}
|
||||
|
||||
static inline int
|
||||
evdev_read_attr_res_prop(struct evdev_device *device,
|
||||
size_t *xres,
|
||||
size_t *yres)
|
||||
{
|
||||
struct udev_device *udev;
|
||||
const char *res_prop;
|
||||
|
||||
udev = device->udev_device;
|
||||
res_prop = udev_device_get_property_value(udev,
|
||||
"LIBINPUT_ATTR_RESOLUTION_HINT");
|
||||
if (!res_prop)
|
||||
return false;
|
||||
|
||||
return parse_dimension_property(res_prop, xres, yres);
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
|
@ -1579,8 +1602,8 @@ evdev_fix_abs_resolution(struct evdev_device *device,
|
|||
struct libevdev *evdev = device->evdev;
|
||||
const struct input_absinfo *absx, *absy;
|
||||
size_t widthmm = 0, heightmm = 0;
|
||||
int xres = EVDEV_FAKE_RESOLUTION,
|
||||
yres = EVDEV_FAKE_RESOLUTION;
|
||||
size_t xres = EVDEV_FAKE_RESOLUTION,
|
||||
yres = EVDEV_FAKE_RESOLUTION;
|
||||
|
||||
if (!(xcode == ABS_X && ycode == ABS_Y) &&
|
||||
!(xcode == ABS_MT_POSITION_X && ycode == ABS_MT_POSITION_Y)) {
|
||||
|
|
@ -1601,7 +1624,8 @@ evdev_fix_abs_resolution(struct evdev_device *device,
|
|||
* property is only for general size hints where we can make
|
||||
* educated guesses but don't know better.
|
||||
*/
|
||||
if (evdev_read_attr_size_prop(device, &widthmm, &heightmm)) {
|
||||
if (!evdev_read_attr_res_prop(device, &xres, &yres) &&
|
||||
evdev_read_attr_size_prop(device, &widthmm, &heightmm)) {
|
||||
xres = (absx->maximum - absx->minimum)/widthmm;
|
||||
yres = (absy->maximum - absy->minimum)/heightmm;
|
||||
}
|
||||
|
|
@ -1953,6 +1977,10 @@ evdev_configure_device(struct evdev_device *device)
|
|||
|
||||
if (udev_tags & EVDEV_UDEV_TAG_MOUSE ||
|
||||
udev_tags & EVDEV_UDEV_TAG_POINTINGSTICK) {
|
||||
evdev_tag_external_mouse(device, device->udev_device);
|
||||
evdev_tag_trackpoint(device, device->udev_device);
|
||||
device->dpi = evdev_read_dpi_prop(device);
|
||||
|
||||
if (libevdev_has_event_code(evdev, EV_REL, REL_X) &&
|
||||
libevdev_has_event_code(evdev, EV_REL, REL_Y) &&
|
||||
evdev_init_accel(device) == -1)
|
||||
|
|
@ -1970,9 +1998,6 @@ evdev_configure_device(struct evdev_device *device)
|
|||
device->scroll.natural_scrolling_enabled = true;
|
||||
/* want button scrolling config option */
|
||||
device->scroll.want_button = 1;
|
||||
|
||||
evdev_tag_external_mouse(device, device->udev_device);
|
||||
evdev_tag_trackpoint(device, device->udev_device);
|
||||
}
|
||||
|
||||
if (udev_tags & EVDEV_UDEV_TAG_KEYBOARD) {
|
||||
|
|
@ -2144,8 +2169,8 @@ evdev_device_create(struct libinput_seat *seat,
|
|||
device->scroll.direction = 0;
|
||||
device->scroll.wheel_click_angle =
|
||||
evdev_read_wheel_click_prop(device);
|
||||
device->model = evdev_read_model(device);
|
||||
device->dpi = evdev_read_dpi_prop(device);
|
||||
device->model_flags = evdev_read_model_flags(device);
|
||||
device->dpi = DEFAULT_MOUSE_DPI;
|
||||
|
||||
/* at most 5 SYN_DROPPED log-messages per 30s */
|
||||
ratelimit_init(&device->syn_drop_limit, 30ULL * 1000, 5);
|
||||
|
|
|
|||
26
src/evdev.h
26
src/evdev.h
|
|
@ -68,8 +68,7 @@ enum evdev_device_tags {
|
|||
EVDEV_TAG_EXTERNAL_MOUSE = (1 << 0),
|
||||
EVDEV_TAG_INTERNAL_TOUCHPAD = (1 << 1),
|
||||
EVDEV_TAG_TRACKPOINT = (1 << 2),
|
||||
EVDEV_TAG_TOUCHPAD_TRACKPOINT = (1 << 3),
|
||||
EVDEV_TAG_KEYBOARD = (1 << 4),
|
||||
EVDEV_TAG_KEYBOARD = (1 << 3),
|
||||
};
|
||||
|
||||
enum evdev_middlebutton_state {
|
||||
|
|
@ -96,16 +95,17 @@ enum evdev_middlebutton_event {
|
|||
};
|
||||
|
||||
enum evdev_device_model {
|
||||
EVDEV_MODEL_DEFAULT,
|
||||
EVDEV_MODEL_LENOVO_X230,
|
||||
EVDEV_MODEL_CHROMEBOOK,
|
||||
EVDEV_MODEL_SYSTEM76_BONOBO,
|
||||
EVDEV_MODEL_SYSTEM76_GALAGO,
|
||||
EVDEV_MODEL_SYSTEM76_KUDU,
|
||||
EVDEV_MODEL_CLEVO_W740SU,
|
||||
EVDEV_MODEL_APPLE_TOUCHPAD,
|
||||
EVDEV_MODEL_WACOM_TOUCHPAD,
|
||||
EVDEV_MODEL_ALPS_TOUCHPAD,
|
||||
EVDEV_MODEL_DEFAULT = 0,
|
||||
EVDEV_MODEL_LENOVO_X230 = (1 << 0),
|
||||
EVDEV_MODEL_CHROMEBOOK = (1 << 1),
|
||||
EVDEV_MODEL_SYSTEM76_BONOBO = (1 << 2),
|
||||
EVDEV_MODEL_SYSTEM76_GALAGO = (1 << 3),
|
||||
EVDEV_MODEL_SYSTEM76_KUDU = (1 << 4),
|
||||
EVDEV_MODEL_CLEVO_W740SU = (1 << 5),
|
||||
EVDEV_MODEL_APPLE_TOUCHPAD = (1 << 6),
|
||||
EVDEV_MODEL_WACOM_TOUCHPAD = (1 << 7),
|
||||
EVDEV_MODEL_ALPS_TOUCHPAD = (1 << 8),
|
||||
EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD = (1 << 9),
|
||||
};
|
||||
|
||||
struct mt_slot {
|
||||
|
|
@ -222,7 +222,7 @@ struct evdev_device {
|
|||
int dpi; /* HW resolution */
|
||||
struct ratelimit syn_drop_limit; /* ratelimit for SYN_DROPPED logging */
|
||||
|
||||
enum evdev_device_model model;
|
||||
uint32_t model_flags;
|
||||
};
|
||||
|
||||
#define EVDEV_UNHANDLED_DEVICE ((struct evdev_device *) 1)
|
||||
|
|
|
|||
|
|
@ -200,6 +200,17 @@ struct libinput_device_config_middle_emulation {
|
|||
struct libinput_device *device);
|
||||
};
|
||||
|
||||
struct libinput_device_config_dwt {
|
||||
int (*is_available)(struct libinput_device *device);
|
||||
enum libinput_config_status (*set_enabled)(
|
||||
struct libinput_device *device,
|
||||
enum libinput_config_dwt_state enable);
|
||||
enum libinput_config_dwt_state (*get_enabled)(
|
||||
struct libinput_device *device);
|
||||
enum libinput_config_dwt_state (*get_default_enabled)(
|
||||
struct libinput_device *device);
|
||||
};
|
||||
|
||||
struct libinput_device_config {
|
||||
struct libinput_device_config_tap *tap;
|
||||
struct libinput_device_config_calibration *calibration;
|
||||
|
|
@ -210,6 +221,7 @@ struct libinput_device_config {
|
|||
struct libinput_device_config_scroll_method *scroll_method;
|
||||
struct libinput_device_config_click_method *click_method;
|
||||
struct libinput_device_config_middle_emulation *middle_emulation;
|
||||
struct libinput_device_config_dwt *dwt;
|
||||
};
|
||||
|
||||
struct libinput_device_group {
|
||||
|
|
@ -262,13 +274,15 @@ typedef void (*libinput_source_dispatch_t)(void *data);
|
|||
void
|
||||
log_msg(struct libinput *libinput,
|
||||
enum libinput_log_priority priority,
|
||||
const char *format, ...);
|
||||
const char *format, ...)
|
||||
LIBINPUT_ATTRIBUTE_PRINTF(3, 4);
|
||||
|
||||
void
|
||||
log_msg_va(struct libinput *libinput,
|
||||
enum libinput_log_priority priority,
|
||||
const char *format,
|
||||
va_list args);
|
||||
va_list args)
|
||||
LIBINPUT_ATTRIBUTE_PRINTF(3, 0);
|
||||
|
||||
int
|
||||
libinput_init(struct libinput *libinput,
|
||||
|
|
|
|||
|
|
@ -37,10 +37,14 @@
|
|||
|
||||
#define VENDOR_ID_APPLE 0x5ac
|
||||
#define VENDOR_ID_WACOM 0x56a
|
||||
#define VENDOR_ID_SYNAPTICS_SERIAL 0x002
|
||||
#define PRODUCT_ID_SYNAPTICS_SERIAL 0x007
|
||||
|
||||
/* The HW DPI rate we normalize to before calculating pointer acceleration */
|
||||
#define DEFAULT_MOUSE_DPI 1000
|
||||
|
||||
#define CASE_RETURN_STRING(a) case a: return #a;
|
||||
|
||||
void
|
||||
set_logging_enabled(int enabled);
|
||||
|
||||
|
|
@ -324,10 +328,4 @@ int parse_mouse_wheel_click_angle_property(const char *prop);
|
|||
double parse_trackpoint_accel_property(const char *prop);
|
||||
bool parse_dimension_property(const char *prop, size_t *width, size_t *height);
|
||||
|
||||
static inline double
|
||||
vector_length(double x, double y)
|
||||
{
|
||||
return sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
#endif /* LIBINPUT_UTIL_H */
|
||||
|
|
|
|||
|
|
@ -2782,3 +2782,45 @@ libinput_device_config_scroll_get_default_button(struct libinput_device *device)
|
|||
|
||||
return device->config.scroll_method->get_default_button(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_config_dwt_is_available(struct libinput_device *device)
|
||||
{
|
||||
if (!device->config.dwt)
|
||||
return 0;
|
||||
|
||||
return device->config.dwt->is_available(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_status
|
||||
libinput_device_config_dwt_set_enabled(struct libinput_device *device,
|
||||
enum libinput_config_dwt_state enable)
|
||||
{
|
||||
if (enable != LIBINPUT_CONFIG_DWT_ENABLED &&
|
||||
enable != LIBINPUT_CONFIG_DWT_DISABLED)
|
||||
return LIBINPUT_CONFIG_STATUS_INVALID;
|
||||
|
||||
if (!libinput_device_config_dwt_is_available(device))
|
||||
return enable ? LIBINPUT_CONFIG_STATUS_UNSUPPORTED :
|
||||
LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
|
||||
return device->config.dwt->set_enabled(device, enable);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_dwt_state
|
||||
libinput_device_config_dwt_get_enabled(struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_dwt_is_available(device))
|
||||
return LIBINPUT_CONFIG_DWT_DISABLED;
|
||||
|
||||
return device->config.dwt->get_enabled(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_dwt_state
|
||||
libinput_device_config_dwt_get_default_enabled(struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_dwt_is_available(device))
|
||||
return LIBINPUT_CONFIG_DWT_DISABLED;
|
||||
|
||||
return device->config.dwt->get_default_enabled(device);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3574,6 +3574,96 @@ libinput_device_config_scroll_get_button(struct libinput_device *device);
|
|||
uint32_t
|
||||
libinput_device_config_scroll_get_default_button(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Possible states for the disable-while-typing feature. See @ref
|
||||
* disable-while-typing for details.
|
||||
*/
|
||||
enum libinput_config_dwt_state {
|
||||
LIBINPUT_CONFIG_DWT_DISABLED,
|
||||
LIBINPUT_CONFIG_DWT_ENABLED,
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Check if this device supports configurable disable-while-typing feature.
|
||||
* This feature is usally available on built-in touchpads and disables the
|
||||
* touchpad while typing. See @ref disable-while-typing for details.
|
||||
*
|
||||
* @param device The device to configure
|
||||
* @return 0 if this device does not support disable-while-typing, or 1
|
||||
* otherwise.
|
||||
*
|
||||
* @see libinput_device_config_dwt_set_enabled
|
||||
* @see libinput_device_config_dwt_get_enabled
|
||||
* @see libinput_device_config_dwt_get_default_enabled
|
||||
*/
|
||||
int
|
||||
libinput_device_config_dwt_is_available(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Enable or disable the disable-while-typing feature. When enabled, the
|
||||
* device will be disabled while typing and for a short period after. See
|
||||
* @ref disable-while-typing for details.
|
||||
*
|
||||
* @note Enabling or disabling disable-while-typing may not take effect
|
||||
* immediately.
|
||||
*
|
||||
* @param device The device to configure
|
||||
* @param enable @ref LIBINPUT_CONFIG_DWT_DISABLED to disable
|
||||
* disable-while-typing, @ref LIBINPUT_CONFIG_DWT_ENABLED to enable
|
||||
*
|
||||
* @return A config status code. Disabling disable-while-typing on a
|
||||
* device that does not support the feature always succeeds.
|
||||
*
|
||||
* @see libinput_device_config_dwt_is_available
|
||||
* @see libinput_device_config_dwt_get_enabled
|
||||
* @see libinput_device_config_dwt_get_default_enabled
|
||||
*/
|
||||
enum libinput_config_status
|
||||
libinput_device_config_dwt_set_enabled(struct libinput_device *device,
|
||||
enum libinput_config_dwt_state enable);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Check if the disable-while typing feature is currently enabled on this
|
||||
* device. If the device does not support disable-while-typing, this
|
||||
* function returns @ref LIBINPUT_CONFIG_DWT_DISABLED.
|
||||
*
|
||||
* @param device The device to configure
|
||||
* @return @ref LIBINPUT_CONFIG_DWT_DISABLED if disabled, @ref
|
||||
* LIBINPUT_CONFIG_DWT_ENABLED if enabled.
|
||||
*
|
||||
* @see libinput_device_config_dwt_is_available
|
||||
* @see libinput_device_config_dwt_set_enabled
|
||||
* @see libinput_device_config_dwt_get_default_enabled
|
||||
*/
|
||||
enum libinput_config_dwt_state
|
||||
libinput_device_config_dwt_get_enabled(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Check if the disable-while typing feature is enabled on this device by
|
||||
* default. If the device does not support disable-while-typing, this
|
||||
* function returns @ref LIBINPUT_CONFIG_DWT_DISABLED.
|
||||
*
|
||||
* @param device The device to configure
|
||||
* @return @ref LIBINPUT_CONFIG_DWT_DISABLED if disabled, @ref
|
||||
* LIBINPUT_CONFIG_DWT_ENABLED if enabled.
|
||||
*
|
||||
* @see libinput_device_config_dwt_is_available
|
||||
* @see libinput_device_config_dwt_set_enabled
|
||||
* @see libinput_device_config_dwt_get_enabled
|
||||
*/
|
||||
enum libinput_config_dwt_state
|
||||
libinput_device_config_dwt_get_default_enabled(struct libinput_device *device);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -163,6 +163,13 @@ LIBINPUT_0.20.0 {
|
|||
libinput_event_get_gesture_event;
|
||||
} LIBINPUT_0.19.0;
|
||||
|
||||
LIBINPUT_0.21.0 {
|
||||
libinput_device_config_dwt_is_available;
|
||||
libinput_device_config_dwt_set_enabled;
|
||||
libinput_device_config_dwt_get_enabled;
|
||||
libinput_device_config_dwt_get_default_enabled;
|
||||
} LIBINPUT_0.20.0;
|
||||
|
||||
/* tablet APIs, they are not part of any stable API promise yet.
|
||||
* keep them separate */
|
||||
LIBINPUT_TABLET_SUPPORT {
|
||||
|
|
@ -189,4 +196,4 @@ LIBINPUT_TABLET_SUPPORT {
|
|||
libinput_tool_ref;
|
||||
libinput_tool_set_user_data;
|
||||
libinput_tool_unref;
|
||||
} LIBINPUT_0.20.0;
|
||||
} LIBINPUT_0.21.0;
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ udev_device_from_devnode(struct libinput *libinput,
|
|||
dev = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
|
||||
|
||||
count++;
|
||||
if (count > 50) {
|
||||
if (count > 200) {
|
||||
log_bug_libinput(libinput,
|
||||
"udev device never initialized (%s)\n",
|
||||
devnode);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ liblitest_la_SOURCES = \
|
|||
litest.c
|
||||
liblitest_la_LIBADD = $(top_builddir)/src/libinput-util.la
|
||||
liblitest_la_CFLAGS = $(AM_CFLAGS) \
|
||||
-DLIBINPUT_UDEV_RULES_FILE="\"$(abs_top_srcdir)/udev/90-libinput-model-quirks-litest.rules\"" \
|
||||
-DLIBINPUT_UDEV_RULES_FILE="\"$(abs_top_builddir)/udev/90-libinput-model-quirks-litest.rules\"" \
|
||||
-DLIBINPUT_UDEV_HWDB_FILE="\"$(abs_top_srcdir)/udev/90-libinput-model-quirks.hwdb\""
|
||||
if HAVE_LIBUNWIND
|
||||
liblitest_la_LIBADD += $(LIBUNWIND_LIBS) -ldl
|
||||
|
|
@ -60,8 +60,10 @@ endif
|
|||
run_tests = \
|
||||
test-touchpad \
|
||||
test-touchpad-tap \
|
||||
test-touchpad-buttons \
|
||||
test-tablet \
|
||||
test-device \
|
||||
test-gestures \
|
||||
test-pointer \
|
||||
test-touch \
|
||||
test-trackpoint \
|
||||
|
|
@ -116,6 +118,10 @@ test_touchpad_tap_SOURCES = touchpad-tap.c
|
|||
test_touchpad_tap_LDADD = $(TEST_LIBS)
|
||||
test_touchpad_tap_LDFLAGS = -no-install
|
||||
|
||||
test_touchpad_buttons_SOURCES = touchpad-buttons.c
|
||||
test_touchpad_buttons_LDADD = $(TEST_LIBS)
|
||||
test_touchpad_buttons_LDFLAGS = -no-install
|
||||
|
||||
test_trackpoint_SOURCES = trackpoint.c
|
||||
test_trackpoint_LDADD = $(TEST_LIBS)
|
||||
test_trackpoint_LDFLAGS = -no-install
|
||||
|
|
@ -132,6 +138,10 @@ test_device_SOURCES = device.c
|
|||
test_device_LDADD = $(TEST_LIBS)
|
||||
test_device_LDFLAGS = -no-install
|
||||
|
||||
test_gestures_SOURCES = gestures.c
|
||||
test_gestures_LDADD = $(TEST_LIBS)
|
||||
test_gestures_LDFLAGS = -no-install
|
||||
|
||||
test_litest_selftest_SOURCES = litest-selftest.c litest.c litest-int.h litest.h
|
||||
test_litest_selftest_CFLAGS = -DLITEST_DISABLE_BACKTRACE_LOGGING -DLITEST_NO_MAIN $(liblitest_la_CFLAGS)
|
||||
test_litest_selftest_LDADD = $(TEST_LIBS)
|
||||
|
|
|
|||
|
|
@ -1009,6 +1009,27 @@ START_TEST(device_udev_tag_apple)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_udev_tag_synaptics_serial)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
struct udev_device *d;
|
||||
const char *prop;
|
||||
|
||||
d = libinput_device_get_udev_device(device);
|
||||
prop = udev_device_get_property_value(d,
|
||||
"LIBINPUT_MODEL_SYNAPTICS_SERIAL_TOUCHPAD");
|
||||
|
||||
if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_SYNAPTICS_SERIAL &&
|
||||
libevdev_get_id_product(dev->evdev) == PRODUCT_ID_SYNAPTICS_SERIAL)
|
||||
ck_assert_notnull(prop);
|
||||
else
|
||||
ck_assert(prop == NULL);
|
||||
|
||||
udev_device_unref(d);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_udev_tag_wacom_tablet)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -1071,5 +1092,6 @@ litest_setup_tests(void)
|
|||
litest_add("device:udev tags", device_udev_tag_alps, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("device:udev tags", device_udev_tag_wacom, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("device:udev tags", device_udev_tag_apple, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("device:udev tags", device_udev_tag_synaptics_serial, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("device:udev tags", device_udev_tag_wacom_tablet, LITEST_TABLET, LITEST_ANY);
|
||||
}
|
||||
|
|
|
|||
364
test/gestures.c
Normal file
364
test/gestures.c
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
/*
|
||||
* Copyright © 2015 Red Hat, 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 (including the next
|
||||
* paragraph) 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <check.h>
|
||||
#include <libinput.h>
|
||||
|
||||
#include "libinput-util.h"
|
||||
#include "litest.h"
|
||||
|
||||
START_TEST(gestures_cap)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
|
||||
ck_assert(libinput_device_has_capability(device,
|
||||
LIBINPUT_DEVICE_CAP_GESTURE));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(gestures_nocap)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
|
||||
ck_assert(!libinput_device_has_capability(device,
|
||||
LIBINPUT_DEVICE_CAP_GESTURE));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(gestures_swipe_3fg)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_gesture *gevent;
|
||||
double dx, dy;
|
||||
int cardinal = _i; /* ranged test */
|
||||
double dir_x, dir_y;
|
||||
int cardinals[8][2] = {
|
||||
{ 0, 30 },
|
||||
{ 30, 30 },
|
||||
{ 30, 0 },
|
||||
{ 30, -30 },
|
||||
{ 0, -30 },
|
||||
{ -30, -30 },
|
||||
{ -30, 0 },
|
||||
{ -30, 30 },
|
||||
};
|
||||
|
||||
if (libevdev_get_num_slots(dev->evdev) < 3)
|
||||
return;
|
||||
|
||||
dir_x = cardinals[cardinal][0];
|
||||
dir_y = cardinals[cardinal][1];
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 40, 40);
|
||||
litest_touch_down(dev, 1, 40, 50);
|
||||
litest_touch_down(dev, 2, 40, 60);
|
||||
libinput_dispatch(li);
|
||||
litest_touch_move_three_touches(dev,
|
||||
40, 40,
|
||||
40, 50,
|
||||
40, 60,
|
||||
dir_x, dir_y,
|
||||
10, 2);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
gevent = litest_is_gesture_event(event,
|
||||
LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN,
|
||||
3);
|
||||
dx = libinput_event_gesture_get_dx(gevent);
|
||||
dy = libinput_event_gesture_get_dy(gevent);
|
||||
ck_assert(dx == 0.0);
|
||||
ck_assert(dy == 0.0);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
while ((event = libinput_get_event(li)) != NULL) {
|
||||
gevent = litest_is_gesture_event(event,
|
||||
LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
|
||||
3);
|
||||
|
||||
dx = libinput_event_gesture_get_dx(gevent);
|
||||
dy = libinput_event_gesture_get_dy(gevent);
|
||||
debug_trace("delta: %.2f/%.2f\n", dx, dy);
|
||||
if (dir_x == 0.0)
|
||||
ck_assert(dx == 0.0);
|
||||
else if (dir_x < 0.0)
|
||||
ck_assert(dx < 0.0);
|
||||
else if (dir_x > 0.0)
|
||||
ck_assert(dx > 0.0);
|
||||
|
||||
if (dir_y == 0.0)
|
||||
ck_assert(dy == 0.0);
|
||||
else if (dir_y < 0.0)
|
||||
ck_assert(dy < 0.0);
|
||||
else if (dir_y > 0.0)
|
||||
ck_assert(dy > 0.0);
|
||||
|
||||
dx = libinput_event_gesture_get_dx_unaccelerated(gevent);
|
||||
dy = libinput_event_gesture_get_dy_unaccelerated(gevent);
|
||||
if (dir_x == 0.0)
|
||||
ck_assert(dx == 0.0);
|
||||
else if (dir_x < 0.0)
|
||||
ck_assert(dx < 0.0);
|
||||
else if (dir_x > 0.0)
|
||||
ck_assert(dx > 0.0);
|
||||
|
||||
if (dir_y == 0.0)
|
||||
ck_assert(dy == 0.0);
|
||||
else if (dir_y < 0.0)
|
||||
ck_assert(dy < 0.0);
|
||||
else if (dir_y > 0.0)
|
||||
ck_assert(dy > 0.0);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
litest_touch_up(dev, 2);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
gevent = litest_is_gesture_event(event,
|
||||
LIBINPUT_EVENT_GESTURE_SWIPE_END,
|
||||
3);
|
||||
ck_assert(!libinput_event_gesture_get_cancelled(gevent));
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(gestures_pinch)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_gesture *gevent;
|
||||
double dx, dy;
|
||||
int cardinal = _i; /* ranged test */
|
||||
double dir_x, dir_y;
|
||||
int i;
|
||||
double scale, oldscale;
|
||||
double angle;
|
||||
int cardinals[8][2] = {
|
||||
{ 0, 30 },
|
||||
{ 30, 30 },
|
||||
{ 30, 0 },
|
||||
{ 30, -30 },
|
||||
{ 0, -30 },
|
||||
{ -30, -30 },
|
||||
{ -30, 0 },
|
||||
{ -30, 30 },
|
||||
};
|
||||
|
||||
if (libevdev_get_num_slots(dev->evdev) < 3)
|
||||
return;
|
||||
|
||||
dir_x = cardinals[cardinal][0];
|
||||
dir_y = cardinals[cardinal][1];
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 50 + dir_x, 50 + dir_y);
|
||||
litest_touch_down(dev, 1, 50 - dir_x, 50 - dir_y);
|
||||
libinput_dispatch(li);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
litest_push_event_frame(dev);
|
||||
if (dir_x > 0.0)
|
||||
dir_x -= 3;
|
||||
else if (dir_x < 0.0)
|
||||
dir_x += 3;
|
||||
if (dir_y > 0.0)
|
||||
dir_y -= 3;
|
||||
else if (dir_y < 0.0)
|
||||
dir_y += 3;
|
||||
litest_touch_move(dev,
|
||||
0,
|
||||
50 + dir_x,
|
||||
50 + dir_y);
|
||||
litest_touch_move(dev,
|
||||
1,
|
||||
50 - dir_x,
|
||||
50 - dir_y);
|
||||
litest_pop_event_frame(dev);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
event = libinput_get_event(li);
|
||||
gevent = litest_is_gesture_event(event,
|
||||
LIBINPUT_EVENT_GESTURE_PINCH_BEGIN,
|
||||
2);
|
||||
dx = libinput_event_gesture_get_dx(gevent);
|
||||
dy = libinput_event_gesture_get_dy(gevent);
|
||||
scale = libinput_event_gesture_get_scale(gevent);
|
||||
ck_assert(dx == 0.0);
|
||||
ck_assert(dy == 0.0);
|
||||
ck_assert(scale == 1.0);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
|
||||
while ((event = libinput_get_event(li)) != NULL) {
|
||||
gevent = litest_is_gesture_event(event,
|
||||
LIBINPUT_EVENT_GESTURE_PINCH_UPDATE,
|
||||
2);
|
||||
|
||||
oldscale = scale;
|
||||
scale = libinput_event_gesture_get_scale(gevent);
|
||||
|
||||
ck_assert(scale < oldscale);
|
||||
|
||||
angle = libinput_event_gesture_get_angle_delta(gevent);
|
||||
ck_assert_double_le(fabs(angle), 1.0);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
gevent = litest_is_gesture_event(event,
|
||||
LIBINPUT_EVENT_GESTURE_PINCH_END,
|
||||
2);
|
||||
ck_assert(!libinput_event_gesture_get_cancelled(gevent));
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(gestures_spread)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_gesture *gevent;
|
||||
double dx, dy;
|
||||
int cardinal = _i; /* ranged test */
|
||||
double dir_x, dir_y;
|
||||
int i;
|
||||
double scale, oldscale;
|
||||
double angle;
|
||||
int cardinals[8][2] = {
|
||||
{ 0, 1 },
|
||||
{ 1, 1 },
|
||||
{ 1, 0 },
|
||||
{ 1, -1 },
|
||||
{ 0, -1 },
|
||||
{ -1, -1 },
|
||||
{ -1, 0 },
|
||||
{ -1, 1 },
|
||||
};
|
||||
|
||||
if (libevdev_get_num_slots(dev->evdev) < 3)
|
||||
return;
|
||||
|
||||
dir_x = cardinals[cardinal][0];
|
||||
dir_y = cardinals[cardinal][1];
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 50 + dir_x, 50 + dir_y);
|
||||
litest_touch_down(dev, 1, 50 - dir_x, 50 - dir_y);
|
||||
libinput_dispatch(li);
|
||||
|
||||
for (i = 0; i < 15; i++) {
|
||||
litest_push_event_frame(dev);
|
||||
if (dir_x > 0.0)
|
||||
dir_x += 2;
|
||||
else if (dir_x < 0.0)
|
||||
dir_x -= 2;
|
||||
if (dir_y > 0.0)
|
||||
dir_y += 2;
|
||||
else if (dir_y < 0.0)
|
||||
dir_y -= 2;
|
||||
litest_touch_move(dev,
|
||||
0,
|
||||
50 + dir_x,
|
||||
50 + dir_y);
|
||||
litest_touch_move(dev,
|
||||
1,
|
||||
50 - dir_x,
|
||||
50 - dir_y);
|
||||
litest_pop_event_frame(dev);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
event = libinput_get_event(li);
|
||||
gevent = litest_is_gesture_event(event,
|
||||
LIBINPUT_EVENT_GESTURE_PINCH_BEGIN,
|
||||
2);
|
||||
dx = libinput_event_gesture_get_dx(gevent);
|
||||
dy = libinput_event_gesture_get_dy(gevent);
|
||||
scale = libinput_event_gesture_get_scale(gevent);
|
||||
ck_assert(dx == 0.0);
|
||||
ck_assert(dy == 0.0);
|
||||
ck_assert(scale == 1.0);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
|
||||
while ((event = libinput_get_event(li)) != NULL) {
|
||||
gevent = litest_is_gesture_event(event,
|
||||
LIBINPUT_EVENT_GESTURE_PINCH_UPDATE,
|
||||
2);
|
||||
oldscale = scale;
|
||||
scale = libinput_event_gesture_get_scale(gevent);
|
||||
ck_assert(scale > oldscale);
|
||||
|
||||
angle = libinput_event_gesture_get_angle_delta(gevent);
|
||||
ck_assert_double_le(fabs(angle), 1.0);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
gevent = litest_is_gesture_event(event,
|
||||
LIBINPUT_EVENT_GESTURE_PINCH_END,
|
||||
2);
|
||||
ck_assert(!libinput_event_gesture_get_cancelled(gevent));
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
litest_setup_tests(void)
|
||||
{
|
||||
/* N, NE, ... */
|
||||
struct range cardinals = { 0, 8 };
|
||||
|
||||
litest_add("gestures:cap", gestures_cap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("gestures:cap", gestures_nocap, LITEST_ANY, LITEST_TOUCHPAD);
|
||||
|
||||
litest_add_ranged("gestures:swipe", gestures_swipe_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals);
|
||||
litest_add_ranged("gestures:pinch", gestures_pinch, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals);
|
||||
litest_add_ranged("gestures:pinch", gestures_spread, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals);
|
||||
}
|
||||
|
|
@ -114,16 +114,6 @@ static struct input_absinfo absinfo[] = {
|
|||
{ .value = -1 }
|
||||
};
|
||||
|
||||
static const char udev_rule[] =
|
||||
"ACTION==\"remove\", GOTO=\"touchpad_end\"\n"
|
||||
"KERNEL!=\"event*\", GOTO=\"touchpad_end\"\n"
|
||||
"ENV{ID_INPUT_TOUCHPAD}==\"\", GOTO=\"touchpad_end\"\n"
|
||||
"\n"
|
||||
"ATTRS{name}==\"litest*X1C3rd*\",\\\n"
|
||||
" ENV{TOUCHPAD_HAS_TRACKPOINT_BUTTONS}=\"1\"\n"
|
||||
"\n"
|
||||
"LABEL=\"touchpad_end\"";
|
||||
|
||||
struct litest_test_device litest_synaptics_carbon3rd_device = {
|
||||
.type = LITEST_SYNAPTICS_TRACKPOINT_BUTTONS,
|
||||
.features = LITEST_TOUCHPAD | LITEST_CLICKPAD | LITEST_BUTTON,
|
||||
|
|
@ -135,5 +125,4 @@ struct litest_test_device litest_synaptics_carbon3rd_device = {
|
|||
.id = &input_id,
|
||||
.events = events,
|
||||
.absinfo = absinfo,
|
||||
.udev_rule = udev_rule,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ const char *filter_device = NULL;
|
|||
const char *filter_group = NULL;
|
||||
|
||||
static inline void litest_remove_model_quirks(void);
|
||||
static void litest_init_udev_rules(void);
|
||||
|
||||
/* defined for the litest selftest */
|
||||
#ifndef LITEST_DISABLE_BACKTRACE_LOGGING
|
||||
|
|
@ -214,13 +215,13 @@ litest_backtrace(void)
|
|||
}
|
||||
|
||||
if (have_lineno) {
|
||||
litest_log("%u: %s() (%s:%d)\n",
|
||||
litest_log("%d: %s() (%s:%d)\n",
|
||||
i,
|
||||
procname,
|
||||
file,
|
||||
line);
|
||||
} else {
|
||||
litest_log("%u: %s (%s%s+%#x) [%p]\n",
|
||||
litest_log("%d: %s (%s%s+%#x) [%p]\n",
|
||||
i,
|
||||
filename,
|
||||
procname,
|
||||
|
|
@ -452,7 +453,7 @@ litest_drop_udev_rules(void)
|
|||
&entries,
|
||||
litest_udev_rule_filter,
|
||||
alphasort);
|
||||
if (n < 0)
|
||||
if (n <= 0)
|
||||
return;
|
||||
|
||||
while (n--) {
|
||||
|
|
@ -472,7 +473,6 @@ litest_drop_udev_rules(void)
|
|||
}
|
||||
free(entries);
|
||||
|
||||
litest_remove_model_quirks();
|
||||
litest_reload_udev_rules();
|
||||
}
|
||||
|
||||
|
|
@ -832,6 +832,8 @@ litest_run(int argc, char **argv)
|
|||
if (getenv("LITEST_VERBOSE"))
|
||||
verbose = 1;
|
||||
|
||||
litest_init_udev_rules();
|
||||
|
||||
srunner_run_all(sr, CK_ENV);
|
||||
failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
|
|
@ -850,6 +852,9 @@ litest_run(int argc, char **argv)
|
|||
free(s);
|
||||
}
|
||||
|
||||
litest_remove_model_quirks();
|
||||
litest_reload_udev_rules();
|
||||
|
||||
return failed;
|
||||
}
|
||||
|
||||
|
|
@ -967,12 +972,10 @@ litest_remove_model_quirks(void)
|
|||
unlink(UDEV_COMMON_HWDB_FILE);
|
||||
}
|
||||
|
||||
static char *
|
||||
litest_init_udev_rules(struct litest_test_device *dev)
|
||||
static void
|
||||
litest_init_udev_rules(void)
|
||||
{
|
||||
int rc;
|
||||
FILE *f;
|
||||
char *path = NULL;
|
||||
|
||||
rc = mkdir(UDEV_RULES_D, 0755);
|
||||
if (rc == -1 && errno != EEXIST)
|
||||
|
|
@ -985,10 +988,18 @@ litest_init_udev_rules(struct litest_test_device *dev)
|
|||
strerror(errno));
|
||||
|
||||
litest_install_model_quirks();
|
||||
litest_reload_udev_rules();
|
||||
}
|
||||
|
||||
static char *
|
||||
litest_init_device_udev_rules(struct litest_test_device *dev)
|
||||
{
|
||||
int rc;
|
||||
FILE *f;
|
||||
char *path = NULL;
|
||||
|
||||
/* device-specific udev rules */
|
||||
if (!dev->udev_rule)
|
||||
goto out;
|
||||
return NULL;
|
||||
|
||||
rc = xasprintf(&path,
|
||||
"%s/%s%s.rules",
|
||||
|
|
@ -1005,7 +1016,6 @@ litest_init_udev_rules(struct litest_test_device *dev)
|
|||
litest_assert_int_ge(fputs(dev->udev_rule, f), 0);
|
||||
fclose(f);
|
||||
|
||||
out:
|
||||
litest_reload_udev_rules();
|
||||
|
||||
return path;
|
||||
|
|
@ -1039,13 +1049,11 @@ litest_create(enum litest_device_type which,
|
|||
d = zalloc(sizeof(*d));
|
||||
litest_assert(d != NULL);
|
||||
|
||||
udev_file = litest_init_udev_rules(*dev);
|
||||
|
||||
udev_file = litest_init_device_udev_rules(*dev);
|
||||
/* device has custom create method */
|
||||
if ((*dev)->create) {
|
||||
(*dev)->create(d);
|
||||
if (abs_override || events_override) {
|
||||
litest_remove_model_quirks();
|
||||
if (udev_file)
|
||||
unlink(udev_file);
|
||||
litest_abort_msg("Custom create cannot be overridden");
|
||||
|
|
@ -1196,10 +1204,10 @@ litest_delete_device(struct litest_device *d)
|
|||
return;
|
||||
|
||||
if (d->udev_rule_file) {
|
||||
litest_remove_model_quirks();
|
||||
unlink(d->udev_rule_file);
|
||||
free(d->udev_rule_file);
|
||||
d->udev_rule_file = NULL;
|
||||
litest_reload_udev_rules();
|
||||
}
|
||||
|
||||
libinput_device_unref(d->libinput_device);
|
||||
|
|
@ -1233,6 +1241,9 @@ axis_replacement_value(struct axis_replacement *axes,
|
|||
{
|
||||
struct axis_replacement *axis = axes;
|
||||
|
||||
if (!axes)
|
||||
return false;
|
||||
|
||||
while (axis->evcode != -1) {
|
||||
if (axis->evcode == evcode) {
|
||||
*value = axis->value;
|
||||
|
|
@ -1277,9 +1288,6 @@ litest_auto_assign_value(struct litest_device *d,
|
|||
break;
|
||||
default:
|
||||
value = -1;
|
||||
if (!axes)
|
||||
break;
|
||||
|
||||
if (!axis_replacement_value(axes, ev->code, &value) &&
|
||||
d->interface->get_axis_default)
|
||||
d->interface->get_axis_default(d, ev->code, &value);
|
||||
|
|
@ -1555,6 +1563,32 @@ litest_touch_move_two_touches(struct litest_device *d,
|
|||
litest_touch_move(d, 1, x1 + dx, y1 + dy);
|
||||
}
|
||||
|
||||
void
|
||||
litest_touch_move_three_touches(struct litest_device *d,
|
||||
double x0, double y0,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double dx, double dy,
|
||||
int steps, int sleep_ms)
|
||||
{
|
||||
for (int i = 0; i < steps - 1; i++) {
|
||||
litest_touch_move(d, 0, x0 + dx / steps * i,
|
||||
y0 + dy / steps * i);
|
||||
litest_touch_move(d, 1, x1 + dx / steps * i,
|
||||
y1 + dy / steps * i);
|
||||
litest_touch_move(d, 2, x2 + dx / steps * i,
|
||||
y2 + dy / steps * i);
|
||||
if (sleep_ms) {
|
||||
libinput_dispatch(d->libinput);
|
||||
msleep(sleep_ms);
|
||||
libinput_dispatch(d->libinput);
|
||||
}
|
||||
}
|
||||
litest_touch_move(d, 0, x0 + dx, y0 + dy);
|
||||
litest_touch_move(d, 1, x1 + dx, y1 + dy);
|
||||
litest_touch_move(d, 2, x2 + dx, y2 + dy);
|
||||
}
|
||||
|
||||
void
|
||||
litest_hover_start(struct litest_device *d,
|
||||
unsigned int slot,
|
||||
|
|
@ -2019,6 +2053,7 @@ litest_create_uinput_device_from_description(const char *name,
|
|||
struct udev_device *udev_device;
|
||||
const char *udev_action;
|
||||
const char *udev_syspath = NULL;
|
||||
int rc;
|
||||
|
||||
udev = udev_new();
|
||||
litest_assert_notnull(udev);
|
||||
|
|
@ -2027,7 +2062,8 @@ litest_create_uinput_device_from_description(const char *name,
|
|||
udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input",
|
||||
NULL);
|
||||
/* remove O_NONBLOCK */
|
||||
fcntl(udev_monitor_get_fd(udev_monitor), F_SETFL, 0);
|
||||
rc = fcntl(udev_monitor_get_fd(udev_monitor), F_SETFL, 0);
|
||||
litest_assert_int_ne(rc, -1);
|
||||
litest_assert_int_eq(udev_monitor_enable_receiving(udev_monitor),
|
||||
0);
|
||||
|
||||
|
|
@ -2233,6 +2269,25 @@ litest_is_keyboard_event(struct libinput_event *event,
|
|||
return kevent;
|
||||
}
|
||||
|
||||
struct libinput_event_gesture *
|
||||
litest_is_gesture_event(struct libinput_event *event,
|
||||
enum libinput_event_type type,
|
||||
int nfingers)
|
||||
{
|
||||
struct libinput_event_gesture *gevent;
|
||||
|
||||
litest_assert(event != NULL);
|
||||
litest_assert_int_eq(libinput_event_get_type(event), type);
|
||||
|
||||
gevent = libinput_event_get_gesture_event(event);
|
||||
litest_assert(gevent != NULL);
|
||||
|
||||
if (nfingers != -1)
|
||||
litest_assert_int_eq(libinput_event_gesture_get_finger_count(gevent),
|
||||
nfingers);
|
||||
return gevent;
|
||||
}
|
||||
|
||||
void
|
||||
litest_assert_tablet_button_event(struct libinput *li, unsigned int button,
|
||||
enum libinput_button_state state)
|
||||
|
|
@ -2366,6 +2421,12 @@ litest_timeout_dwt_long(void)
|
|||
msleep(520);
|
||||
}
|
||||
|
||||
void
|
||||
litest_timeout_gesture(void)
|
||||
{
|
||||
msleep(120);
|
||||
}
|
||||
|
||||
void
|
||||
litest_push_event_frame(struct litest_device *dev)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -334,6 +334,12 @@ void litest_touch_move_two_touches(struct litest_device *d,
|
|||
double x1, double y1,
|
||||
double dx, double dy,
|
||||
int steps, int sleep_ms);
|
||||
void litest_touch_move_three_touches(struct litest_device *d,
|
||||
double x0, double y0,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double dx, double dy,
|
||||
int steps, int sleep_ms);
|
||||
|
||||
void litest_tablet_proximity_in(struct litest_device *d,
|
||||
int x, int y,
|
||||
|
|
@ -392,6 +398,11 @@ struct libinput_event_keyboard * litest_is_keyboard_event(
|
|||
struct libinput_event *event,
|
||||
unsigned int key,
|
||||
enum libinput_key_state state);
|
||||
struct libinput_event_gesture * litest_is_gesture_event(
|
||||
struct libinput_event *event,
|
||||
enum libinput_event_type type,
|
||||
int nfingers);
|
||||
|
||||
void litest_assert_button_event(struct libinput *li,
|
||||
unsigned int button,
|
||||
enum libinput_button_state state);
|
||||
|
|
@ -438,6 +449,7 @@ void litest_timeout_finger_switch(void);
|
|||
void litest_timeout_middlebutton(void);
|
||||
void litest_timeout_dwt_short(void);
|
||||
void litest_timeout_dwt_long(void);
|
||||
void litest_timeout_gesture(void);
|
||||
|
||||
void litest_push_event_frame(struct litest_device *dev);
|
||||
void litest_pop_event_frame(struct litest_device *dev);
|
||||
|
|
|
|||
54
test/misc.c
54
test/misc.c
|
|
@ -132,6 +132,7 @@ START_TEST(event_conversion_device_notify)
|
|||
ck_assert(libinput_event_get_pointer_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_keyboard_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_gesture_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
|
|
@ -187,6 +188,7 @@ START_TEST(event_conversion_pointer)
|
|||
ck_assert(libinput_event_get_device_notify_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_keyboard_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_gesture_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
|
|
@ -236,6 +238,7 @@ START_TEST(event_conversion_pointer_abs)
|
|||
ck_assert(libinput_event_get_device_notify_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_keyboard_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_gesture_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
|
|
@ -278,6 +281,7 @@ START_TEST(event_conversion_key)
|
|||
ck_assert(libinput_event_get_device_notify_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_pointer_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_gesture_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
|
|
@ -327,6 +331,7 @@ START_TEST(event_conversion_touch)
|
|||
ck_assert(libinput_event_get_device_notify_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_pointer_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_keyboard_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_gesture_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
|
|
@ -337,6 +342,54 @@ START_TEST(event_conversion_touch)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(event_conversion_gesture)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
int gestures = 0;
|
||||
int i;
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_touch_down(dev, 0, 70, 30);
|
||||
litest_touch_down(dev, 1, 30, 70);
|
||||
for (i = 0; i < 8; i++) {
|
||||
litest_push_event_frame(dev);
|
||||
litest_touch_move(dev, 0, 70 - i * 5, 30 + i * 5);
|
||||
litest_touch_move(dev, 1, 30 + i * 5, 70 - i * 5);
|
||||
litest_pop_event_frame(dev);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
while ((event = libinput_get_event(li))) {
|
||||
enum libinput_event_type type;
|
||||
type = libinput_event_get_type(event);
|
||||
|
||||
if (type >= LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN &&
|
||||
type <= LIBINPUT_EVENT_GESTURE_PINCH_END) {
|
||||
struct libinput_event_gesture *g;
|
||||
struct libinput_event *base;
|
||||
g = libinput_event_get_gesture_event(event);
|
||||
base = libinput_event_gesture_get_base_event(g);
|
||||
ck_assert(event == base);
|
||||
|
||||
gestures++;
|
||||
|
||||
litest_disable_log_handler(li);
|
||||
ck_assert(libinput_event_get_device_notify_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_pointer_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_keyboard_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
ck_assert_int_gt(gestures, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(event_conversion_tablet)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -728,6 +781,7 @@ litest_setup_tests(void)
|
|||
litest_add_for_device("events:conversion", event_conversion_pointer_abs, LITEST_XEN_VIRTUAL_POINTER);
|
||||
litest_add_for_device("events:conversion", event_conversion_key, LITEST_KEYBOARD);
|
||||
litest_add_for_device("events:conversion", event_conversion_touch, LITEST_WACOM_TOUCH);
|
||||
litest_add_for_device("events:conversion", event_conversion_gesture, LITEST_BCM5974);
|
||||
litest_add_for_device("events:conversion", event_conversion_tablet, LITEST_WACOM_CINTIQ);
|
||||
litest_add_no_device("bitfield_helpers", bitfield_helpers);
|
||||
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ START_TEST(pointer_motion_relative_min_decel)
|
|||
ck_assert((evx == 0.0) == (dx == 0));
|
||||
ck_assert((evy == 0.0) == (dy == 0));
|
||||
|
||||
len = vector_length(evx, evy);
|
||||
len = hypot(evx, evy);
|
||||
ck_assert(fabs(len) >= 0.3);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
|
|
@ -251,7 +251,6 @@ START_TEST(pointer_absolute_initial_state)
|
|||
struct libinput_event_pointer *p1, *p2;
|
||||
int axis = _i; /* looped test */
|
||||
|
||||
dev = litest_current_device();
|
||||
libinput1 = dev->libinput;
|
||||
litest_touch_down(dev, 0, 40, 60);
|
||||
litest_touch_up(dev, 0);
|
||||
|
|
|
|||
1552
test/touchpad-buttons.c
Normal file
1552
test/touchpad-buttons.c
Normal file
File diff suppressed because it is too large
Load diff
1817
test/touchpad.c
1817
test/touchpad.c
File diff suppressed because it is too large
Load diff
|
|
@ -206,6 +206,14 @@ print_device_notify(struct libinput_event *ev)
|
|||
printf("-clickfinger");
|
||||
}
|
||||
|
||||
if (libinput_device_config_dwt_is_available(dev)) {
|
||||
if (libinput_device_config_dwt_get_enabled(dev) ==
|
||||
LIBINPUT_CONFIG_DWT_ENABLED)
|
||||
printf(" dwt-on");
|
||||
else
|
||||
printf(" dwt-off)");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
|
|
@ -564,8 +572,6 @@ print_gesture_event_with_coords(struct libinput_event *ev)
|
|||
double dy = libinput_event_gesture_get_dy(t);
|
||||
double dx_unaccel = libinput_event_gesture_get_dx_unaccelerated(t);
|
||||
double dy_unaccel = libinput_event_gesture_get_dy_unaccelerated(t);
|
||||
double scale = libinput_event_gesture_get_scale(t);
|
||||
double angle = libinput_event_gesture_get_angle_delta(t);
|
||||
|
||||
print_event_time(libinput_event_gesture_get_time(t));
|
||||
|
||||
|
|
@ -573,10 +579,15 @@ print_gesture_event_with_coords(struct libinput_event *ev)
|
|||
libinput_event_gesture_get_finger_count(t),
|
||||
dx, dy, dx_unaccel, dy_unaccel);
|
||||
|
||||
if (libinput_event_get_type(ev) == LIBINPUT_EVENT_GESTURE_PINCH_UPDATE)
|
||||
if (libinput_event_get_type(ev) ==
|
||||
LIBINPUT_EVENT_GESTURE_PINCH_UPDATE) {
|
||||
double scale = libinput_event_gesture_get_scale(t);
|
||||
double angle = libinput_event_gesture_get_angle_delta(t);
|
||||
|
||||
printf(" %5.2f @ %5.2f\n", scale, angle);
|
||||
else
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
|
|
@ -654,6 +654,7 @@ main(int argc, char *argv[])
|
|||
|
||||
window_init(&w);
|
||||
sockets_init(li);
|
||||
handle_event_libinput(NULL, 0, li);
|
||||
|
||||
gtk_main();
|
||||
|
||||
|
|
|
|||
|
|
@ -35,15 +35,6 @@
|
|||
|
||||
#include "shared.h"
|
||||
|
||||
static inline const char*
|
||||
bool_to_str(bool b)
|
||||
{
|
||||
if (b)
|
||||
return "yes";
|
||||
else
|
||||
return "no";
|
||||
}
|
||||
|
||||
static const char *
|
||||
tap_default(struct libinput_device *device)
|
||||
{
|
||||
|
|
@ -181,6 +172,18 @@ click_defaults(struct libinput_device *device)
|
|||
return str;
|
||||
}
|
||||
|
||||
static const char *
|
||||
dwt_default(struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_dwt_is_available(device))
|
||||
return "n/a";
|
||||
|
||||
if (libinput_device_config_dwt_get_default_enabled(device))
|
||||
return "enabled";
|
||||
else
|
||||
return "disabled";
|
||||
}
|
||||
|
||||
static void
|
||||
print_device_notify(struct libinput_event *ev)
|
||||
{
|
||||
|
|
@ -247,6 +250,8 @@ print_device_notify(struct libinput_event *ev)
|
|||
printf("Click methods: %s\n", str);
|
||||
free(str);
|
||||
|
||||
printf("Disable-w-typing: %s\n", dwt_default(dev));
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ enum options {
|
|||
OPT_LEFT_HANDED_DISABLE,
|
||||
OPT_MIDDLEBUTTON_ENABLE,
|
||||
OPT_MIDDLEBUTTON_DISABLE,
|
||||
OPT_DWT_ENABLE,
|
||||
OPT_DWT_DISABLE,
|
||||
OPT_CLICK_METHOD,
|
||||
OPT_SCROLL_METHOD,
|
||||
OPT_SCROLL_BUTTON,
|
||||
|
|
@ -87,6 +89,8 @@ tools_usage()
|
|||
"--disable-left-handed.... enable/disable left-handed button configuration\n"
|
||||
"--enable-middlebutton\n"
|
||||
"--disable-middlebutton.... enable/disable middle button emulation\n"
|
||||
"--enable-dwt\n"
|
||||
"--disable-dwt..... enable/disable disable-while-typing\n"
|
||||
"--set-click-method=[none|clickfinger|buttonareas] .... set the desired click method\n"
|
||||
"--set-scroll-method=[none|twofinger|edge|button] ... set the desired scroll method\n"
|
||||
"--set-scroll-button=BTN_MIDDLE ... set the button to the given button code\n"
|
||||
|
|
@ -115,6 +119,7 @@ tools_init_context(struct tools_context *context)
|
|||
options->natural_scroll = -1;
|
||||
options->left_handed = -1;
|
||||
options->middlebutton = -1;
|
||||
options->dwt = -1;
|
||||
options->click_method = -1;
|
||||
options->scroll_method = -1;
|
||||
options->scroll_button = -1;
|
||||
|
|
@ -147,6 +152,8 @@ tools_parse_args(int argc, char **argv, struct tools_context *context)
|
|||
{ "disable-left-handed", 0, 0, OPT_LEFT_HANDED_DISABLE },
|
||||
{ "enable-middlebutton", 0, 0, OPT_MIDDLEBUTTON_ENABLE },
|
||||
{ "disable-middlebutton", 0, 0, OPT_MIDDLEBUTTON_DISABLE },
|
||||
{ "enable-dwt", 0, 0, OPT_DWT_ENABLE },
|
||||
{ "disable-dwt", 0, 0, OPT_DWT_DISABLE },
|
||||
{ "set-click-method", 1, 0, OPT_CLICK_METHOD },
|
||||
{ "set-scroll-method", 1, 0, OPT_SCROLL_METHOD },
|
||||
{ "set-scroll-button", 1, 0, OPT_SCROLL_BUTTON },
|
||||
|
|
@ -212,6 +219,12 @@ tools_parse_args(int argc, char **argv, struct tools_context *context)
|
|||
case OPT_MIDDLEBUTTON_DISABLE:
|
||||
options->middlebutton = 0;
|
||||
break;
|
||||
case OPT_DWT_ENABLE:
|
||||
options->dwt = LIBINPUT_CONFIG_DWT_ENABLED;
|
||||
break;
|
||||
case OPT_DWT_DISABLE:
|
||||
options->dwt = LIBINPUT_CONFIG_DWT_DISABLED;
|
||||
break;
|
||||
case OPT_CLICK_METHOD:
|
||||
if (!optarg) {
|
||||
tools_usage();
|
||||
|
|
@ -419,6 +432,9 @@ tools_device_apply_config(struct libinput_device *device,
|
|||
libinput_device_config_middle_emulation_set_enabled(device,
|
||||
options->middlebutton);
|
||||
|
||||
if (options->dwt != -1)
|
||||
libinput_device_config_dwt_set_enabled(device, options->dwt);
|
||||
|
||||
if (options->click_method != -1)
|
||||
libinput_device_config_click_set_method(device, options->click_method);
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ struct tools_options {
|
|||
enum libinput_config_scroll_method scroll_method;
|
||||
int scroll_button;
|
||||
double speed;
|
||||
int dwt;
|
||||
};
|
||||
|
||||
struct tools_context {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,12 @@ libinput:touchpad:input:b0005v05ACp*
|
|||
LIBINPUT_MODEL_APPLE_TOUCHPAD=1
|
||||
LIBINPUT_ATTR_SIZE_HINT=104x75
|
||||
|
||||
##########################################
|
||||
# Elantech
|
||||
##########################################
|
||||
libinput:name:*ETPS/2 Elantech Touchpad*:dmi:*
|
||||
LIBINPUT_ATTR_RESOLUTION_HINT=31x31
|
||||
|
||||
##########################################
|
||||
# Google
|
||||
##########################################
|
||||
|
|
@ -64,6 +70,12 @@ libinput:name:Atmel maXTouch Touchpad:dmi:*svn*GOOGLE*:pn*Samus*
|
|||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPadX230*
|
||||
LIBINPUT_MODEL_LENOVO_X230=1
|
||||
|
||||
##########################################
|
||||
# Synaptics
|
||||
##########################################
|
||||
libinput:touchpad:input:b0011v0002p0007*
|
||||
LIBINPUT_MODEL_SYNAPTICS_SERIAL_TOUCHPAD=1
|
||||
|
||||
##########################################
|
||||
# System76
|
||||
##########################################
|
||||
|
|
|
|||
|
|
@ -25,18 +25,12 @@ KERNELS=="*input*", \
|
|||
IMPORT{builtin}="hwdb 'libinput:name:$attr{name}:fwversion:$env{LIBINPUT_MODEL_FIRMWARE_VERSION}'"
|
||||
# End of touchpad firmware detection
|
||||
|
||||
# Matches below are exclusive, if one matches we skip the rest
|
||||
# hwdb matches:
|
||||
#
|
||||
# libinput:touchpad:<modalias>
|
||||
ENV{ID_INPUT_TOUCHPAD}=="1", \
|
||||
IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=libinput:touchpad:", \
|
||||
GOTO="libinput_model_quirks_end"
|
||||
IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=libinput:touchpad:"
|
||||
|
||||
# libinput:name:<name>:dmi:<dmi string>
|
||||
KERNELS=="input*", \
|
||||
IMPORT{builtin}="hwdb 'libinput:name:$attr{name}:$attr{[dmi/id]modalias}'", \
|
||||
GOTO="libinput_model_quirks_end"
|
||||
|
||||
IMPORT{builtin}="hwdb 'libinput:name:$attr{name}:$attr{[dmi/id]modalias}'"
|
||||
|
||||
LABEL="libinput_model_quirks_end"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ udev_PROGRAMS = libinput-device-group \
|
|||
|
||||
litest_rules = 80-libinput-device-groups-litest.rules \
|
||||
90-libinput-model-quirks-litest.rules
|
||||
udev_SCRIPTS = $(litest_rules)
|
||||
noinst_SCRIPTS = $(litest_rules)
|
||||
|
||||
libinput_device_group_SOURCES = libinput-device-group.c
|
||||
libinput_device_group_CFLAGS = $(LIBUDEV_CFLAGS) $(GCC_CFLAGS)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue