mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-10 11:30:14 +01:00
Merge branch 'master' into tablet-support
This commit is contained in:
commit
087d25a54e
69 changed files with 10085 additions and 1379 deletions
1
COPYING
1
COPYING
|
|
@ -1,3 +1,4 @@
|
|||
Copyright © 2006-2009 Simon Thum
|
||||
Copyright © 2008-2012 Kristian Høgsberg
|
||||
Copyright © 2010-2012 Intel Corporation
|
||||
Copyright © 2010-2011 Benjamin Franzke
|
||||
|
|
|
|||
19
configure.ac
19
configure.ac
|
|
@ -1,7 +1,7 @@
|
|||
AC_PREREQ([2.64])
|
||||
|
||||
m4_define([libinput_major_version], [0])
|
||||
m4_define([libinput_minor_version], [13])
|
||||
m4_define([libinput_minor_version], [15])
|
||||
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=10:1:0
|
||||
LIBINPUT_LT_VERSION=12:0:2
|
||||
AC_SUBST(LIBINPUT_LT_VERSION)
|
||||
|
||||
AM_SILENT_RULES([yes])
|
||||
|
|
@ -60,6 +60,20 @@ PKG_PROG_PKG_CONFIG()
|
|||
PKG_CHECK_MODULES(MTDEV, [mtdev >= 1.1.0])
|
||||
PKG_CHECK_MODULES(LIBUDEV, [libudev])
|
||||
PKG_CHECK_MODULES(LIBEVDEV, [libevdev >= 0.4])
|
||||
PKG_CHECK_MODULES(LIBUNWIND,
|
||||
[libunwind],
|
||||
[HAVE_LIBUNWIND=yes],
|
||||
[HAVE_LIBUNWIND=no])
|
||||
if test "x$HAVE_LIBUNWIND" = "xyes"; then
|
||||
AC_DEFINE(HAVE_LIBUNWIND, 1, [Have libunwind support])
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_LIBUNWIND, [test "x$HAVE_LIBUNWIND" = xyes])
|
||||
AC_PATH_PROG(ADDR2LINE, [addr2line])
|
||||
if test "x$ADDR2LINE" != "x"; then
|
||||
AC_DEFINE_UNQUOTED(HAVE_ADDR2LINE, 1, [addr2line found])
|
||||
AC_DEFINE_UNQUOTED(ADDR2LINE, ["$ADDR2LINE"], [Path to addr2line])
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB([m], [atan2])
|
||||
AC_CHECK_LIB([rt], [clock_gettime])
|
||||
|
||||
|
|
@ -201,5 +215,6 @@ AC_MSG_RESULT([
|
|||
Build documentation ${build_documentation}
|
||||
Build tests ${build_tests}
|
||||
Tests use valgrind ${VALGRIND}
|
||||
Tests use libunwind ${HAVE_LIBUNWIND}
|
||||
Build GUI event tool ${build_eventgui}
|
||||
])
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
EXTRA_DIST = touchpad-tap-state-machine.svg touchpad-softbutton-state-machine.svg
|
||||
EXTRA_DIST = \
|
||||
middle-button-emulation.svg \
|
||||
touchpad-tap-state-machine.svg \
|
||||
touchpad-softbutton-state-machine.svg
|
||||
|
||||
if BUILD_DOCS
|
||||
|
||||
|
|
@ -16,7 +19,8 @@ header_files = \
|
|||
$(srcdir)/seats.dox \
|
||||
$(srcdir)/t440-support.dox \
|
||||
$(srcdir)/tablet-support.dox \
|
||||
$(srcdir)/tapping.dox
|
||||
$(srcdir)/tapping.dox \
|
||||
$(srcdir)/test-suite.dox
|
||||
|
||||
diagram_files = \
|
||||
$(srcdir)/dot/seats-sketch.gv \
|
||||
|
|
|
|||
|
|
@ -44,7 +44,10 @@ udev_device_type.</dt>
|
|||
ID_INPUT_TOUCHSCREEN, ID_INPUT_TABLET, ID_INPUT_JOYSTICK,
|
||||
ID_INPUT_ACCELEROMETER</dt>
|
||||
<dd>If any of the above is set, libinput initializes the device as the given
|
||||
type, see @ref udev_device_type.</dd>
|
||||
type, see @ref udev_device_type. Note that for historical reasons more than
|
||||
one of these may be set at any time, libinput will select only one of these
|
||||
to determine the device type. To ensure libinput selects the correct device
|
||||
type, only set one of them.</dd>
|
||||
<dt>WL_SEAT</dt>
|
||||
<dd>Assigns the logical seat for this device. See
|
||||
libinput_seat_get_logical_name()
|
||||
|
|
@ -57,6 +60,13 @@ See @ref motion_normalization for details.
|
|||
<dd>The angle in degrees for each click on a mouse wheel. See
|
||||
libinput_pointer_get_axis_source() for details.
|
||||
</dd>
|
||||
<dt>POINTINGSTICK_CONST_ACCEL</dt>
|
||||
<dd>A constant (linear) acceleration factor to apply to pointingstick deltas
|
||||
to normalize them.
|
||||
<dt>LIBINPUT_MODEL_*</dt>
|
||||
<dd><b>This prefix is reserved as private API, do not use.</b>. See @ref
|
||||
model_specific_configuration for details.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
Below is an example udev rule to assign "seat1" to a device from vendor
|
||||
|
|
@ -91,4 +101,16 @@ ACTION=="add|change", KERNEL=="event[0-9]*", ENV{ID_VENDOR_ID}=="012a", \
|
|||
ENV{ID_MODEL_ID}=="034b", ENV{ID_INPUT_TOUCHPAD}="", ENV{ID_INPUT_TABLET}="1"
|
||||
@endcode
|
||||
|
||||
@section model_specific_configuration Model-specific configuration
|
||||
|
||||
libinput reserves the property prefix <b>LIBINPUT_MODEL_</b> for
|
||||
model-specific configuration. <b>This prefix is reserved as private API, do
|
||||
not use.</b>
|
||||
|
||||
The effect of this property may be to enable or disable certain
|
||||
features on a specific device or set of devices, to change configuration
|
||||
defaults or any other reason. The effects of setting this property, the
|
||||
format of the property and the value of the property are subject to change
|
||||
at any time.
|
||||
|
||||
*/
|
||||
|
|
|
|||
1315
doc/middle-button-emulation.svg
Normal file
1315
doc/middle-button-emulation.svg
Normal file
File diff suppressed because it is too large
Load diff
|
After Width: | Height: | Size: 112 KiB |
|
|
@ -23,6 +23,10 @@ screen, it is common for a finger to start inside an exclusion zone and move
|
|||
rapidly across the touchpad. libinput detects such movements and avoids palm
|
||||
detection on such touch sequences.
|
||||
|
||||
Each exclusion zone is divided into a top part and a bottom part. A touch
|
||||
starting in the top part of the exclusion zone does not trigger a
|
||||
tap (see @ref tapping).
|
||||
|
||||
In the diagram below, the exclusion zones are painted red.
|
||||
Touch 'A' starts inside the exclusion zone and moves
|
||||
almost vertically. It is considered a palm and ignored for cursor movement,
|
||||
|
|
@ -31,6 +35,11 @@ despite moving out of the exclusion zone.
|
|||
Touch 'B' starts inside the exclusion zone but moves horizontally out of the
|
||||
zone. It is considered a valid touch and controls the cursor.
|
||||
|
||||
Touch 'C' occurs in the top part of the exclusion zone. Despite being a
|
||||
tapping motion, it does not generate an emulated button event. Touch 'D'
|
||||
likewise occurs within the exclusion zone but in the bottom half. libinput
|
||||
will generate a button event for this touch.
|
||||
|
||||
@image html palm-detection.svg
|
||||
|
||||
@section trackpoint-disabling Palm detection during trackpoint use
|
||||
|
|
@ -48,5 +57,26 @@ the palm on the touchpad while using the trackstick).
|
|||
If the touchpad is disabled, the @ref t440_support "top software buttons"
|
||||
remain enabled.
|
||||
|
||||
@section disable-while-typing Disable-while-typing
|
||||
|
||||
libinput automatically disables the touchpad for a timeout after a key
|
||||
press, a feature traditionally referred to as "disable while typing" and
|
||||
previously available through the
|
||||
[syndaemon(1)](http://linux.die.net/man/1/syndaemon) command. libinput does
|
||||
not require an external command and the feature is currently enabled for all
|
||||
touchpads but will be reduced in the future to only apply to touchpads where
|
||||
finger width or pressure data is unreliable.
|
||||
|
||||
Notable behaviors of libinput's disable-while-typing feature:
|
||||
- Two different timeouts are used, after a single key press the timeout is
|
||||
short to ensure responsiveness. After multiple key events, the timeout is
|
||||
longer to avoid accidental pointer manipulation while typing.
|
||||
- Some keys do not trigger the timeout, specifically some modifier keys
|
||||
(Ctrl, Alt, Shift, and Fn). Actions such as Ctrl + click thus stay
|
||||
responsive.
|
||||
- Touches started while the touchpad is disabled do not control the cursor,
|
||||
it is thus possible to rest the palm on the touchpad while typing.
|
||||
- Physical buttons work even while the touchpad is disabled. This includes
|
||||
software-emulated buttons.
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,7 +1,20 @@
|
|||
/**
|
||||
@page scrolling Scrolling
|
||||
|
||||
libinput supports three different types of scrolling behavior.
|
||||
libinput supports three different types of scrolling methods: @ref
|
||||
twofinger_scrolling, @ref edge_scrolling and @ref button_scrolling. Some devices
|
||||
support multiple methods, though only one can be enabled at a time. See
|
||||
libinput_device_config_scroll_set_method() for documentation on how to
|
||||
switch methods and libinput_device_config_scroll_get_methods() for
|
||||
documentation on how to query a device for available scroll methods.
|
||||
|
||||
Scroll movements provide vertical and horizontal directions, each
|
||||
scroll event contains both directions where applicable, see
|
||||
libinput_event_pointer_get_axis_value(). libinput does not provide separate
|
||||
toggles to enable or disable horizontal scrolling. Instead, horizontal
|
||||
scrolling is always enabled. This is intentional, libinput does not have
|
||||
enough context to know when horizontal scrolling is appropriate for a given
|
||||
widget. The task of filtering horizontal movements is up to the caller.
|
||||
|
||||
@section twofinger_scrolling Two-finger scrolling
|
||||
|
||||
|
|
@ -16,7 +29,6 @@ For scrolling to trigger, a built-in distance threshold has to be met but once
|
|||
engaged any movement will scroll. In other words, to start scrolling a
|
||||
sufficiently large movement is required, once scrolling tiny amounts of
|
||||
movements will translate into tiny scroll movements.
|
||||
|
||||
Scrolling in both directions at once is possible by meeting the required
|
||||
distance thresholds to enable each direction separately.
|
||||
|
||||
|
|
@ -28,23 +40,27 @@ scroll).
|
|||
|
||||
@image html edge-scrolling.svg "Vertical and horizontal edge scrolling"
|
||||
|
||||
Due to the layout of the edges, diagonal scrolling is not possible.
|
||||
Due to the layout of the edges, diagonal scrolling is not possible. The
|
||||
behavior of edge scrolling using both edges at the same time is undefined.
|
||||
|
||||
Edge scrolling conflicts with @ref clickpad_softbuttons and is
|
||||
not usually available on clickpads.
|
||||
not usually available on clickpads. See
|
||||
http://who-t.blogspot.com.au/2015/03/why-libinput-doesnt-support-edge.html
|
||||
for details.
|
||||
|
||||
@section button_scrolling On-Button scrolling
|
||||
|
||||
Scrolling when a button is held down is available on selected devices. The
|
||||
motion of a device is converted into scrolling motion.
|
||||
|
||||
For example, Lenovo devices provide a
|
||||
On-button scrolling converts the motion of a device into scroll events while
|
||||
a designated button is held down. For example, Lenovo devices provide a
|
||||
<a href="http://en.wikipedia.org/wiki/Pointing_stick">pointing stick</a> that emulates
|
||||
scroll events when the trackstick's middle mouse button is held down.
|
||||
|
||||
@image html button-scrolling.svg "Button scrolling"
|
||||
|
||||
Note that libinput's @ref t440_support enables the use of the middle
|
||||
The button may be changed with
|
||||
libinput_device_config_scroll_set_button() but must be on the same device as
|
||||
the motion events. Cross-device scrolling is not supported but
|
||||
for one exception: libinput's @ref t440_support enables the use of the middle
|
||||
button for button scrolling (even when the touchpad is disabled).
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -2,14 +2,66 @@
|
|||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
width="393.62857"
|
||||
height="268.62857"
|
||||
id="svg2">
|
||||
id="svg2"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="palm-detection.svg">
|
||||
<metadata
|
||||
id="metadata3479">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1136"
|
||||
id="namedview3477"
|
||||
showgrid="false"
|
||||
inkscape:zoom="3.5662625"
|
||||
inkscape:cx="199.35048"
|
||||
inkscape:cy="156.74673"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2" />
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="marker4663"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4407"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||
transform="scale(0.8) translate(12.5,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
|
|
@ -59,64 +111,111 @@
|
|||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
</defs>
|
||||
<g
|
||||
transform="translate(343.95712,-527.33359)"
|
||||
id="layer3"
|
||||
style="display:inline">
|
||||
<rect
|
||||
width="386.42856"
|
||||
height="261.42856"
|
||||
x="-340.35712"
|
||||
y="530.93359"
|
||||
id="rect2858-0"
|
||||
style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:7.20000076;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
width="65.281105"
|
||||
height="254.3844"
|
||||
x="-336.88608"
|
||||
y="534.46918"
|
||||
id="rect12924"
|
||||
style="color:#000000;fill:#ff0000;fill-opacity:0.32017547;fill-rule:nonzero;stroke:none;stroke-width:3.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
width="65.281105"
|
||||
height="254.3844"
|
||||
x="-22.72864"
|
||||
y="534.21661"
|
||||
id="rect13482"
|
||||
style="color:#000000;fill:#ff0000;fill-opacity:0.32017547;fill-rule:nonzero;stroke:none;stroke-width:3.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 38.928571,67.914286 c 0,0 3.508205,24.810617 9.642857,57.857144 6.134651,33.04652 23.277202,79.68584 89.642852,90.35714"
|
||||
transform="translate(-343.95712,527.33359)"
|
||||
id="path13492"
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:6, 1;stroke-dashoffset:0;marker-mid:none;marker-end:url(#Arrow1Lend-2)" />
|
||||
<text
|
||||
x="-310.74283"
|
||||
y="590.96222"
|
||||
id="text13874"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
||||
x="-310.74283"
|
||||
y="590.96222"
|
||||
id="tspan13876"
|
||||
style="font-size:18px;font-family:Arial;-inkscape-font-specification:Arial">A</tspan></text>
|
||||
<text
|
||||
x="7.8971062"
|
||||
y="626.08258"
|
||||
id="text13874-8"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
||||
x="7.8971062"
|
||||
y="626.08258"
|
||||
id="tspan13876-7"
|
||||
style="font-size:18px;font-family:Arial;-inkscape-font-specification:Arial">B</tspan></text>
|
||||
<path
|
||||
d="m 347.5,90.414286 c 0,0 -28.20972,-6.408104 -85,-6.071429 -22.06971,0.130838 -66.07143,4.285715 -66.07143,4.285715"
|
||||
transform="translate(-343.95712,527.33359)"
|
||||
id="path13903"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend-2)" />
|
||||
</g>
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:7.20000076;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="rect2858-0"
|
||||
y="3.6000037"
|
||||
x="3.6000032"
|
||||
height="261.42856"
|
||||
width="386.42856" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ff0000;fill-opacity:0.32017547;fill-rule:nonzero;stroke:none;stroke-width:3.5;marker:none;enable-background:accumulate"
|
||||
id="rect12924"
|
||||
y="7.1355872"
|
||||
x="7.0710421"
|
||||
height="254.3844"
|
||||
width="65.281105" />
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ff0000;fill-opacity:0.32017547;fill-rule:nonzero;stroke:none;stroke-width:3.5;marker:none;enable-background:accumulate"
|
||||
id="rect13482"
|
||||
y="6.8830237"
|
||||
x="321.22849"
|
||||
height="254.3844"
|
||||
width="65.281105" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:6, 1;stroke-dashoffset:0;stroke-opacity:1;marker-mid:none;marker-end:url(#Arrow1Lend-2)"
|
||||
id="path13492"
|
||||
d="m 38.928571,67.914286 c 0,0 3.508205,24.810617 9.642857,57.857144 6.134651,33.04652 23.277202,79.68584 89.642852,90.35714" />
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:0.3559322;fill-rule:evenodd;stroke:none;stroke-width:3.30527353px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="rect3490"
|
||||
width="65.272476"
|
||||
height="136.21509"
|
||||
x="7.0411549"
|
||||
y="7.0411549" />
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:100%;font-family:Utopia;-inkscape-font-specification:Utopia;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"
|
||||
id="text13874"
|
||||
y="63.628628"
|
||||
x="33.214291"><tspan
|
||||
style="font-size:18px;font-family:Arial;-inkscape-font-specification:Arial"
|
||||
id="tspan13876"
|
||||
y="63.628628"
|
||||
x="33.214291">A</tspan></text>
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:0.3559322;fill-rule:evenodd;stroke:none;stroke-width:3.30527353px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="rect3490-2"
|
||||
width="65.272476"
|
||||
height="136.21509"
|
||||
x="321.23563"
|
||||
y="6.7607527" />
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:100%;font-family:Utopia;-inkscape-font-specification:Utopia;text-align:start;writing-mode:lr-tb;text-anchor:start;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"
|
||||
id="text13874-8"
|
||||
y="98.748993"
|
||||
x="351.85422"><tspan
|
||||
style="font-size:18px;font-family:Arial;-inkscape-font-specification:Arial"
|
||||
id="tspan13876-7"
|
||||
y="98.748993"
|
||||
x="351.85422">B</tspan></text>
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend-2)"
|
||||
id="path13903"
|
||||
d="m 347.5,90.414286 c 0,0 -28.20972,-6.408104 -85,-6.071429 -22.06971,0.130838 -66.07143,4.285715 -66.07143,4.285715" />
|
||||
<g
|
||||
transform="translate(343.95712,-527.33359)"
|
||||
id="layer1"
|
||||
style="display:inline" />
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:100%;font-family:Utopia;-inkscape-font-specification:Utopia;text-align:start;writing-mode:lr-tb;text-anchor:start;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"
|
||||
id="text13874-8-1"
|
||||
y="46.009491"
|
||||
x="342.27759"><tspan
|
||||
style="font-size:18px;font-family:Arial;-inkscape-font-specification:Arial"
|
||||
id="tspan13876-7-9"
|
||||
y="46.009491"
|
||||
x="342.27759">C</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:100%;font-family:Utopia;-inkscape-font-specification:Utopia;text-align:start;writing-mode:lr-tb;text-anchor:start;display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"
|
||||
id="text13874-8-1-4"
|
||||
y="215.65927"
|
||||
x="37.970726"><tspan
|
||||
style="font-size:18px;font-family:Arial;-inkscape-font-specification:Arial"
|
||||
id="tspan13876-7-9-5"
|
||||
y="215.65927"
|
||||
x="37.970726">D</tspan></text>
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1"
|
||||
id="path4401"
|
||||
cx="-360.181"
|
||||
cy="24.53549"
|
||||
r="4.0658817"
|
||||
transform="scale(-1,1)" />
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1"
|
||||
id="path4401-9"
|
||||
cx="-36.452721"
|
||||
cy="194.8819"
|
||||
r="4.0658817"
|
||||
transform="scale(-1,1)" />
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 8.3 KiB |
|
|
@ -33,6 +33,10 @@ continue the dragging process, so that multiple touchpad-widths of distance
|
|||
can be covered easily. If two-fingers are supported by the hardware, a
|
||||
second finger can be used to drag while the first is held in-place.
|
||||
|
||||
An alternative method to end a drag process is to tap immediately after
|
||||
lifting the finger. The full sequence is thus: tap, finger down, drag,
|
||||
finger up, tap.
|
||||
|
||||
@section tap_constraints Constraints while tapping
|
||||
|
||||
A couple of constraints apply to the contact to be converted into a press, the most common ones are:
|
||||
|
|
|
|||
92
doc/test-suite.dox
Normal file
92
doc/test-suite.dox
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
@page test-suite libinput test suite
|
||||
|
||||
The libinput test suite is based on
|
||||
[Check](http://check.sourceforge.net/doc/check_html/) and runs automatically
|
||||
during `make check`. Check itself is wrapped into a libinput-specific test
|
||||
suite called *litest*. Tests are found in `$srcdir/test/`, the test binaries are
|
||||
prefixed with `test-` and can be run individually.
|
||||
|
||||
@section test-config X.Org config to avoid interference
|
||||
|
||||
uinput devices created by the test suite are usually recognised by X as
|
||||
input devices. All events sent through these devices will generate X events
|
||||
and interfere with your desktop.
|
||||
|
||||
Copy the file `$srcdir/test/50-litest.conf` into your `/etc/X11/xorg.conf.d`
|
||||
and restart X. This will ignore any litest devices and thus not interfere
|
||||
with your desktop.
|
||||
|
||||
@section test-root Permissions required to run tests
|
||||
|
||||
Most tests require the creation of uinput devices and access to the
|
||||
resulting `/dev/input/eventX` nodes. Some tests require temporary udev rules.
|
||||
<b>This usually requires the tests to be run as root</b>.
|
||||
|
||||
@section test-filtering Selective running of tests
|
||||
|
||||
litest's tests are grouped by test groups and devices. A test group is e.g.
|
||||
"touchpad:tap" and incorporates all tapping-related tests for touchpads.
|
||||
Each test function is (usually) run with one or more specific devices.
|
||||
The `--list` commandline argument shows the list of suites and tests.
|
||||
@code
|
||||
$ ./test/test-device --list
|
||||
device:wheel:
|
||||
wheel only
|
||||
blackwidow
|
||||
device:invalid devices:
|
||||
no device
|
||||
device:group:
|
||||
no device
|
||||
logitech trackball
|
||||
MS surface cover
|
||||
mouse_roccat
|
||||
wheel only
|
||||
blackwidow
|
||||
...
|
||||
@endcode
|
||||
|
||||
In the above example, the "device:wheel" suite is run for the "wheel only" and
|
||||
the "blackwidow" device. Both devices are automatically instantiated through
|
||||
uinput by litest. The "no device" entry signals that litest does not
|
||||
instantiate a uinput device for a specific test (though the test itself may
|
||||
instantiate one).
|
||||
|
||||
The `--filter-test` argument enables selective running of tests through
|
||||
basic shell-style function name matching. For example:
|
||||
|
||||
@code
|
||||
$ ./test/test-touchpad --filter-test="*1fg_tap*"
|
||||
@endcode
|
||||
|
||||
The `--filter-device` argument enables selective running of tests through
|
||||
basic shell-style device name matching. The device names matched are the
|
||||
litest-specific shortnames, see the output of `--list`. For example:
|
||||
|
||||
@code
|
||||
$ ./test/test-touchpad --filter-device="synaptics*"
|
||||
@endcode
|
||||
|
||||
The `--filter-group` argument enables selective running of test groups
|
||||
through basic shell-style test group matching. The test groups matched are
|
||||
litest-specific test groups, see the output of `--list`. For example:
|
||||
|
||||
@code
|
||||
$ ./test/test-touchpad --filter-group="touchpad:*hover*"
|
||||
@endcode
|
||||
|
||||
The `--filter-device` and `--filter-group` arguments can be combined with
|
||||
`--list` to show which groups and devices will be affected.
|
||||
|
||||
@section test-verbosity Controlling test output
|
||||
|
||||
Each test supports the `--verbose` commandline option to enable debugging
|
||||
output, see libinput_log_set_priority() for details. The `LITEST_VERBOSE`
|
||||
environment variable, if set, also enables verbose mode.
|
||||
|
||||
@code
|
||||
$ ./test/test-device --verbose
|
||||
$ LITEST_VERBOSE=1 make check
|
||||
@endcode
|
||||
|
||||
*/
|
||||
File diff suppressed because it is too large
Load diff
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 116 KiB |
|
|
@ -162,6 +162,7 @@ struct input_keymap_entry {
|
|||
#define INPUT_PROP_SEMI_MT 0x03 /* touch rectangle only */
|
||||
#define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */
|
||||
#define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */
|
||||
#define INPUT_PROP_ACCELEROMETER 0x06 /* has accelerometer */
|
||||
|
||||
#define INPUT_PROP_MAX 0x1f
|
||||
#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
|
||||
|
|
@ -459,7 +460,10 @@ struct input_keymap_entry {
|
|||
#define KEY_VIDEO_NEXT 241 /* drive next video source */
|
||||
#define KEY_VIDEO_PREV 242 /* drive previous video source */
|
||||
#define KEY_BRIGHTNESS_CYCLE 243 /* brightness up, after max is min */
|
||||
#define KEY_BRIGHTNESS_ZERO 244 /* brightness off, use ambient */
|
||||
#define KEY_BRIGHTNESS_AUTO 244 /* Set Auto Brightness: manual
|
||||
brightness control is off,
|
||||
rely on ambient */
|
||||
#define KEY_BRIGHTNESS_ZERO KEY_BRIGHTNESS_AUTO
|
||||
#define KEY_DISPLAY_OFF 245 /* display device to off state */
|
||||
|
||||
#define KEY_WWAN 246 /* Wireless WAN (LTE, UMTS, GSM, etc.) */
|
||||
|
|
@ -629,6 +633,7 @@ struct input_keymap_entry {
|
|||
#define KEY_ADDRESSBOOK 0x1ad /* AL Contacts/Address Book */
|
||||
#define KEY_MESSENGER 0x1ae /* AL Instant Messaging */
|
||||
#define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */
|
||||
#define KEY_BRIGHTNESS_TOGGLE KEY_DISPLAYTOGGLE
|
||||
#define KEY_SPELLCHECK 0x1b0 /* AL Spell Check */
|
||||
#define KEY_LOGOFF 0x1b1 /* AL Logoff */
|
||||
|
||||
|
|
@ -720,6 +725,24 @@ struct input_keymap_entry {
|
|||
|
||||
#define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */
|
||||
|
||||
#define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */
|
||||
#define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */
|
||||
#define KEY_JOURNAL 0x242 /* AL Log/Journal/Timecard */
|
||||
#define KEY_CONTROLPANEL 0x243 /* AL Control Panel */
|
||||
#define KEY_APPSELECT 0x244 /* AL Select Task/Application */
|
||||
#define KEY_SCREENSAVER 0x245 /* AL Screen Saver */
|
||||
#define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */
|
||||
|
||||
#define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */
|
||||
#define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */
|
||||
|
||||
#define KEY_KBDINPUTASSIST_PREV 0x260
|
||||
#define KEY_KBDINPUTASSIST_NEXT 0x261
|
||||
#define KEY_KBDINPUTASSIST_PREVGROUP 0x262
|
||||
#define KEY_KBDINPUTASSIST_NEXTGROUP 0x263
|
||||
#define KEY_KBDINPUTASSIST_ACCEPT 0x264
|
||||
#define KEY_KBDINPUTASSIST_CANCEL 0x265
|
||||
|
||||
#define BTN_TRIGGER_HAPPY 0x2c0
|
||||
#define BTN_TRIGGER_HAPPY1 0x2c0
|
||||
#define BTN_TRIGGER_HAPPY2 0x2c1
|
||||
|
|
@ -945,7 +968,8 @@ struct input_keymap_entry {
|
|||
*/
|
||||
#define MT_TOOL_FINGER 0
|
||||
#define MT_TOOL_PEN 1
|
||||
#define MT_TOOL_MAX 1
|
||||
#define MT_TOOL_PALM 2
|
||||
#define MT_TOOL_MAX 2
|
||||
|
||||
/*
|
||||
* Values describing the status of a force-feedback effect
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
lib_LTLIBRARIES = libinput.la
|
||||
noinst_LTLIBRARIES = libinput-util.la
|
||||
noinst_LTLIBRARIES = libinput-util.la \
|
||||
libfilter.la
|
||||
|
||||
include_HEADERS = \
|
||||
libinput.h
|
||||
|
|
@ -10,14 +11,15 @@ libinput_la_SOURCES = \
|
|||
libinput-private.h \
|
||||
evdev.c \
|
||||
evdev.h \
|
||||
evdev-tablet.c \
|
||||
evdev-tablet.h \
|
||||
evdev-middle-button.c \
|
||||
evdev-mt-touchpad.c \
|
||||
evdev-mt-touchpad.h \
|
||||
evdev-mt-touchpad-tap.c \
|
||||
evdev-mt-touchpad-buttons.c \
|
||||
evdev-mt-touchpad-edge-scroll.c \
|
||||
evdev-mt-touchpad-gestures.c \
|
||||
evdev-tablet.c \
|
||||
evdev-tablet.h \
|
||||
filter.c \
|
||||
filter.h \
|
||||
filter-private.h \
|
||||
|
|
@ -52,6 +54,13 @@ libinput_util_la_CFLAGS = -I$(top_srcdir)/include \
|
|||
$(LIBUDEV_CFLAGS) \
|
||||
$(GCC_CFLAGS)
|
||||
|
||||
libfilter_la_SOURCES = \
|
||||
filter.c \
|
||||
filter.h \
|
||||
filter-private.h
|
||||
libfilter_la_LIBADD =
|
||||
libfilter_la_CFLAGS =
|
||||
|
||||
libinput_la_LDFLAGS = -version-info $(LIBINPUT_LT_VERSION) -shared \
|
||||
-Wl,--version-script=$(srcdir)/libinput.sym
|
||||
|
||||
|
|
|
|||
716
src/evdev-middle-button.c
Normal file
716
src/evdev-middle-button.c
Normal file
|
|
@ -0,0 +1,716 @@
|
|||
/*
|
||||
* Copyright © 2014 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "evdev.h"
|
||||
|
||||
#define MIDDLEBUTTON_TIMEOUT 50
|
||||
|
||||
/*****************************************
|
||||
* BEFORE YOU EDIT THIS FILE, look at the state diagram in
|
||||
* doc/middle-button-emulation-state-machine.svg, or online at
|
||||
* https://drive.google.com/file/d/0B1NwWmji69nodUJncXRMc1FvY1k/view?usp=sharing
|
||||
* (it's a http://draw.io diagram)
|
||||
*
|
||||
* Any changes in this file must be represented in the diagram.
|
||||
*
|
||||
* Note in regards to the state machine: it only handles left, right and
|
||||
* emulated middle button clicks, all other button events are passed
|
||||
* through. When in the PASSTHROUGH state, all events are passed through
|
||||
* as-is.
|
||||
*/
|
||||
|
||||
#define CASE_RETURN_STRING(a) case a: return #a;
|
||||
|
||||
static inline const char*
|
||||
middlebutton_state_to_str(enum evdev_middlebutton_state state)
|
||||
{
|
||||
switch (state) {
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_IDLE);
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_LEFT_DOWN);
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_RIGHT_DOWN);
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_MIDDLE);
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_LEFT_UP_PENDING);
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_RIGHT_UP_PENDING);
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_PASSTHROUGH);
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_IGNORE_LR);
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_IGNORE_L);
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_IGNORE_R);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline const char*
|
||||
middlebutton_event_to_str(enum evdev_middlebutton_event event)
|
||||
{
|
||||
switch (event) {
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_EVENT_L_DOWN);
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_EVENT_R_DOWN);
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_EVENT_OTHER);
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_EVENT_L_UP);
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_EVENT_R_UP);
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_EVENT_TIMEOUT);
|
||||
CASE_RETURN_STRING(MIDDLEBUTTON_EVENT_ALL_UP);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
middlebutton_state_error(struct evdev_device *device,
|
||||
enum evdev_middlebutton_event event)
|
||||
{
|
||||
log_bug_libinput(device->base.seat->libinput,
|
||||
"Invalid event %s in middle btn state %s\n",
|
||||
middlebutton_event_to_str(event),
|
||||
middlebutton_state_to_str(device->middlebutton.state));
|
||||
}
|
||||
|
||||
static void
|
||||
middlebutton_timer_set(struct evdev_device *device, uint64_t now)
|
||||
{
|
||||
libinput_timer_set(&device->middlebutton.timer,
|
||||
now + MIDDLEBUTTON_TIMEOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
middlebutton_timer_cancel(struct evdev_device *device)
|
||||
{
|
||||
libinput_timer_cancel(&device->middlebutton.timer);
|
||||
}
|
||||
|
||||
static inline void
|
||||
middlebutton_set_state(struct evdev_device *device,
|
||||
enum evdev_middlebutton_state state,
|
||||
uint64_t now)
|
||||
{
|
||||
switch (state) {
|
||||
case MIDDLEBUTTON_LEFT_DOWN:
|
||||
case MIDDLEBUTTON_RIGHT_DOWN:
|
||||
middlebutton_timer_set(device, now);
|
||||
device->middlebutton.first_event_time = now;
|
||||
break;
|
||||
case MIDDLEBUTTON_IDLE:
|
||||
case MIDDLEBUTTON_MIDDLE:
|
||||
case MIDDLEBUTTON_LEFT_UP_PENDING:
|
||||
case MIDDLEBUTTON_RIGHT_UP_PENDING:
|
||||
case MIDDLEBUTTON_PASSTHROUGH:
|
||||
case MIDDLEBUTTON_IGNORE_LR:
|
||||
case MIDDLEBUTTON_IGNORE_L:
|
||||
case MIDDLEBUTTON_IGNORE_R:
|
||||
middlebutton_timer_cancel(device);
|
||||
break;
|
||||
}
|
||||
|
||||
device->middlebutton.state = state;
|
||||
}
|
||||
|
||||
static void
|
||||
middlebutton_post_event(struct evdev_device *device,
|
||||
uint64_t now,
|
||||
int button,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
evdev_pointer_notify_button(device,
|
||||
now,
|
||||
button,
|
||||
state);
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_middlebutton_idle_handle_event(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum evdev_middlebutton_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case MIDDLEBUTTON_EVENT_L_DOWN:
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_LEFT_DOWN, time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_R_DOWN:
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_RIGHT_DOWN, time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_OTHER:
|
||||
return 0;
|
||||
case MIDDLEBUTTON_EVENT_R_UP:
|
||||
case MIDDLEBUTTON_EVENT_L_UP:
|
||||
case MIDDLEBUTTON_EVENT_TIMEOUT:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_ALL_UP:
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_middlebutton_ldown_handle_event(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum evdev_middlebutton_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case MIDDLEBUTTON_EVENT_L_DOWN:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_R_DOWN:
|
||||
middlebutton_post_event(device, time,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_MIDDLE, time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_OTHER:
|
||||
middlebutton_post_event(device, time,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
middlebutton_set_state(device,
|
||||
MIDDLEBUTTON_PASSTHROUGH,
|
||||
time);
|
||||
return 0;
|
||||
case MIDDLEBUTTON_EVENT_R_UP:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_L_UP:
|
||||
middlebutton_post_event(device,
|
||||
device->middlebutton.first_event_time,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
middlebutton_post_event(device, time,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_IDLE, time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_TIMEOUT:
|
||||
middlebutton_post_event(device,
|
||||
device->middlebutton.first_event_time,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
middlebutton_set_state(device,
|
||||
MIDDLEBUTTON_PASSTHROUGH,
|
||||
time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_ALL_UP:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_middlebutton_rdown_handle_event(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum evdev_middlebutton_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case MIDDLEBUTTON_EVENT_L_DOWN:
|
||||
middlebutton_post_event(device, time,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_MIDDLE, time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_R_DOWN:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_OTHER:
|
||||
middlebutton_post_event(device,
|
||||
device->middlebutton.first_event_time,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
middlebutton_set_state(device,
|
||||
MIDDLEBUTTON_PASSTHROUGH,
|
||||
time);
|
||||
return 0;
|
||||
case MIDDLEBUTTON_EVENT_R_UP:
|
||||
middlebutton_post_event(device,
|
||||
device->middlebutton.first_event_time,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
middlebutton_post_event(device, time,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_IDLE, time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_L_UP:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_TIMEOUT:
|
||||
middlebutton_post_event(device,
|
||||
device->middlebutton.first_event_time,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
middlebutton_set_state(device,
|
||||
MIDDLEBUTTON_PASSTHROUGH,
|
||||
time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_ALL_UP:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_middlebutton_middle_handle_event(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum evdev_middlebutton_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case MIDDLEBUTTON_EVENT_L_DOWN:
|
||||
case MIDDLEBUTTON_EVENT_R_DOWN:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_OTHER:
|
||||
middlebutton_post_event(device, time,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_IGNORE_LR, time);
|
||||
return 0;
|
||||
case MIDDLEBUTTON_EVENT_R_UP:
|
||||
middlebutton_post_event(device, time,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
middlebutton_set_state(device,
|
||||
MIDDLEBUTTON_LEFT_UP_PENDING,
|
||||
time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_L_UP:
|
||||
middlebutton_post_event(device, time,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
middlebutton_set_state(device,
|
||||
MIDDLEBUTTON_RIGHT_UP_PENDING,
|
||||
time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_TIMEOUT:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_ALL_UP:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_middlebutton_lup_pending_handle_event(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum evdev_middlebutton_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case MIDDLEBUTTON_EVENT_L_DOWN:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_R_DOWN:
|
||||
middlebutton_post_event(device, time,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_MIDDLE, time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_OTHER:
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_IGNORE_L, time);
|
||||
return 0;
|
||||
case MIDDLEBUTTON_EVENT_R_UP:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_L_UP:
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_IDLE, time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_TIMEOUT:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_ALL_UP:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_middlebutton_rup_pending_handle_event(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum evdev_middlebutton_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case MIDDLEBUTTON_EVENT_L_DOWN:
|
||||
middlebutton_post_event(device, time,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_MIDDLE, time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_R_DOWN:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_OTHER:
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_IGNORE_R, time);
|
||||
return 0;
|
||||
case MIDDLEBUTTON_EVENT_R_UP:
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_IDLE, time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_L_UP:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_TIMEOUT:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_ALL_UP:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_middlebutton_passthrough_handle_event(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum evdev_middlebutton_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case MIDDLEBUTTON_EVENT_L_DOWN:
|
||||
case MIDDLEBUTTON_EVENT_R_DOWN:
|
||||
case MIDDLEBUTTON_EVENT_OTHER:
|
||||
case MIDDLEBUTTON_EVENT_R_UP:
|
||||
case MIDDLEBUTTON_EVENT_L_UP:
|
||||
return 0;
|
||||
case MIDDLEBUTTON_EVENT_TIMEOUT:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_ALL_UP:
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_IDLE, time);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_middlebutton_ignore_lr_handle_event(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum evdev_middlebutton_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case MIDDLEBUTTON_EVENT_L_DOWN:
|
||||
case MIDDLEBUTTON_EVENT_R_DOWN:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_OTHER:
|
||||
return 0;
|
||||
case MIDDLEBUTTON_EVENT_R_UP:
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_IGNORE_L, time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_L_UP:
|
||||
middlebutton_set_state(device, MIDDLEBUTTON_IGNORE_R, time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_TIMEOUT:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_ALL_UP:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_middlebutton_ignore_l_handle_event(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum evdev_middlebutton_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case MIDDLEBUTTON_EVENT_L_DOWN:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_R_DOWN:
|
||||
return 0;
|
||||
case MIDDLEBUTTON_EVENT_OTHER:
|
||||
case MIDDLEBUTTON_EVENT_R_UP:
|
||||
return 0;
|
||||
case MIDDLEBUTTON_EVENT_L_UP:
|
||||
middlebutton_set_state(device,
|
||||
MIDDLEBUTTON_PASSTHROUGH,
|
||||
time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_TIMEOUT:
|
||||
case MIDDLEBUTTON_EVENT_ALL_UP:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
static int
|
||||
evdev_middlebutton_ignore_r_handle_event(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum evdev_middlebutton_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case MIDDLEBUTTON_EVENT_L_DOWN:
|
||||
return 0;
|
||||
case MIDDLEBUTTON_EVENT_R_DOWN:
|
||||
middlebutton_state_error(device, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_OTHER:
|
||||
return 0;
|
||||
case MIDDLEBUTTON_EVENT_R_UP:
|
||||
middlebutton_set_state(device,
|
||||
MIDDLEBUTTON_PASSTHROUGH,
|
||||
time);
|
||||
break;
|
||||
case MIDDLEBUTTON_EVENT_L_UP:
|
||||
return 0;
|
||||
case MIDDLEBUTTON_EVENT_TIMEOUT:
|
||||
case MIDDLEBUTTON_EVENT_ALL_UP:
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_middlebutton_handle_event(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum evdev_middlebutton_event event)
|
||||
{
|
||||
int rc;
|
||||
enum evdev_middlebutton_state current;
|
||||
|
||||
current = device->middlebutton.state;
|
||||
|
||||
switch (current) {
|
||||
case MIDDLEBUTTON_IDLE:
|
||||
rc = evdev_middlebutton_idle_handle_event(device, time, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_LEFT_DOWN:
|
||||
rc = evdev_middlebutton_ldown_handle_event(device, time, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_RIGHT_DOWN:
|
||||
rc = evdev_middlebutton_rdown_handle_event(device, time, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_MIDDLE:
|
||||
rc = evdev_middlebutton_middle_handle_event(device, time, event);
|
||||
break;
|
||||
case MIDDLEBUTTON_LEFT_UP_PENDING:
|
||||
rc = evdev_middlebutton_lup_pending_handle_event(device,
|
||||
time,
|
||||
event);
|
||||
break;
|
||||
case MIDDLEBUTTON_RIGHT_UP_PENDING:
|
||||
rc = evdev_middlebutton_rup_pending_handle_event(device,
|
||||
time,
|
||||
event);
|
||||
break;
|
||||
case MIDDLEBUTTON_PASSTHROUGH:
|
||||
rc = evdev_middlebutton_passthrough_handle_event(device,
|
||||
time,
|
||||
event);
|
||||
break;
|
||||
case MIDDLEBUTTON_IGNORE_LR:
|
||||
rc = evdev_middlebutton_ignore_lr_handle_event(device,
|
||||
time,
|
||||
event);
|
||||
break;
|
||||
case MIDDLEBUTTON_IGNORE_L:
|
||||
rc = evdev_middlebutton_ignore_l_handle_event(device,
|
||||
time,
|
||||
event);
|
||||
break;
|
||||
case MIDDLEBUTTON_IGNORE_R:
|
||||
rc = evdev_middlebutton_ignore_r_handle_event(device,
|
||||
time,
|
||||
event);
|
||||
break;
|
||||
}
|
||||
|
||||
log_debug(device->base.seat->libinput,
|
||||
"middlebuttonstate: %s → %s → %s, rc %d\n",
|
||||
middlebutton_state_to_str(current),
|
||||
middlebutton_event_to_str(event),
|
||||
middlebutton_state_to_str(device->middlebutton.state),
|
||||
rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline void
|
||||
evdev_middlebutton_apply_config(struct evdev_device *device)
|
||||
{
|
||||
if (device->middlebutton.want_enabled ==
|
||||
device->middlebutton.enabled)
|
||||
return;
|
||||
|
||||
if (device->middlebutton.button_mask != 0)
|
||||
return;
|
||||
|
||||
device->middlebutton.enabled = device->middlebutton.want_enabled;
|
||||
}
|
||||
|
||||
bool
|
||||
evdev_middlebutton_filter_button(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
int button,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
enum evdev_middlebutton_event event;
|
||||
bool is_press = state == LIBINPUT_BUTTON_STATE_PRESSED;
|
||||
int rc;
|
||||
unsigned int bit = (button - BTN_LEFT);
|
||||
uint32_t old_mask = 0;
|
||||
|
||||
if (!device->middlebutton.enabled)
|
||||
return false;
|
||||
|
||||
switch (button) {
|
||||
case BTN_LEFT:
|
||||
if (is_press)
|
||||
event = MIDDLEBUTTON_EVENT_L_DOWN;
|
||||
else
|
||||
event = MIDDLEBUTTON_EVENT_L_UP;
|
||||
break;
|
||||
case BTN_RIGHT:
|
||||
if (is_press)
|
||||
event = MIDDLEBUTTON_EVENT_R_DOWN;
|
||||
else
|
||||
event = MIDDLEBUTTON_EVENT_R_UP;
|
||||
break;
|
||||
|
||||
/* BTN_MIDDLE counts as "other" and resets middle button
|
||||
* emulation */
|
||||
case BTN_MIDDLE:
|
||||
default:
|
||||
event = MIDDLEBUTTON_EVENT_OTHER;
|
||||
break;
|
||||
}
|
||||
|
||||
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",
|
||||
libevdev_event_code_get_name(EV_KEY,
|
||||
button));
|
||||
return true;
|
||||
}
|
||||
|
||||
rc = evdev_middlebutton_handle_event(device, time, event);
|
||||
|
||||
old_mask = device->middlebutton.button_mask;
|
||||
if (is_press)
|
||||
device->middlebutton.button_mask |= 1 << bit;
|
||||
else
|
||||
device->middlebutton.button_mask &= ~(1 << bit);
|
||||
|
||||
if (old_mask != device->middlebutton.button_mask &&
|
||||
device->middlebutton.button_mask == 0) {
|
||||
evdev_middlebutton_handle_event(device,
|
||||
time,
|
||||
MIDDLEBUTTON_EVENT_ALL_UP);
|
||||
evdev_middlebutton_apply_config(device);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_middlebutton_handle_timeout(uint64_t now, void *data)
|
||||
{
|
||||
struct evdev_device *device = (struct evdev_device*)data;
|
||||
|
||||
evdev_middlebutton_handle_event(device,
|
||||
libinput_now(device->base.seat->libinput),
|
||||
MIDDLEBUTTON_EVENT_TIMEOUT);
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_middlebutton_is_available(struct libinput_device *device)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static enum libinput_config_status
|
||||
evdev_middlebutton_set(struct libinput_device *device,
|
||||
enum libinput_config_middle_emulation_state enable)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
|
||||
switch (enable) {
|
||||
case LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED:
|
||||
evdev->middlebutton.want_enabled = true;
|
||||
break;
|
||||
case LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED:
|
||||
evdev->middlebutton.want_enabled = false;
|
||||
break;
|
||||
default:
|
||||
return LIBINPUT_CONFIG_STATUS_INVALID;
|
||||
}
|
||||
|
||||
evdev_middlebutton_apply_config(evdev);
|
||||
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static enum libinput_config_middle_emulation_state
|
||||
evdev_middlebutton_get(struct libinput_device *device)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
|
||||
return evdev->middlebutton.enabled ?
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED :
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
|
||||
}
|
||||
|
||||
static enum libinput_config_middle_emulation_state
|
||||
evdev_middlebutton_get_default(struct libinput_device *device)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
|
||||
return evdev->middlebutton.enabled_default ?
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED :
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
|
||||
}
|
||||
|
||||
void
|
||||
evdev_init_middlebutton(struct evdev_device *device,
|
||||
bool enable,
|
||||
bool want_config)
|
||||
{
|
||||
libinput_timer_init(&device->middlebutton.timer,
|
||||
device->base.seat->libinput,
|
||||
evdev_middlebutton_handle_timeout,
|
||||
device);
|
||||
device->middlebutton.enabled_default = enable;
|
||||
device->middlebutton.want_enabled = enable;
|
||||
device->middlebutton.enabled = enable;
|
||||
|
||||
if (!want_config)
|
||||
return;
|
||||
|
||||
device->middlebutton.config.available = evdev_middlebutton_is_available;
|
||||
device->middlebutton.config.set = evdev_middlebutton_set;
|
||||
device->middlebutton.config.get = evdev_middlebutton_get;
|
||||
device->middlebutton.config.get_default = evdev_middlebutton_get_default;
|
||||
device->base.config.middle_emulation = &device->middlebutton.config;
|
||||
}
|
||||
|
|
@ -144,12 +144,15 @@ tp_button_set_leave_timer(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
* as described in the state machine diagram.
|
||||
*/
|
||||
static void
|
||||
tp_button_set_state(struct tp_dispatch *tp, struct tp_touch *t,
|
||||
enum button_state new_state, enum button_event event)
|
||||
tp_button_set_state(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum button_state new_state,
|
||||
enum button_event event)
|
||||
{
|
||||
libinput_timer_cancel(&t->button.timer);
|
||||
|
||||
t->button.state = new_state;
|
||||
|
||||
switch (t->button.state) {
|
||||
case BUTTON_STATE_NONE:
|
||||
t->button.curr = 0;
|
||||
|
|
@ -235,7 +238,9 @@ tp_button_bottom_handle_event(struct tp_dispatch *tp,
|
|||
case BUTTON_EVENT_IN_BOTTOM_R:
|
||||
case BUTTON_EVENT_IN_BOTTOM_L:
|
||||
if (event != t->button.curr)
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM,
|
||||
tp_button_set_state(tp,
|
||||
t,
|
||||
BUTTON_STATE_BOTTOM,
|
||||
event);
|
||||
break;
|
||||
case BUTTON_EVENT_IN_TOP_R:
|
||||
|
|
@ -256,8 +261,8 @@ tp_button_bottom_handle_event(struct tp_dispatch *tp,
|
|||
|
||||
static void
|
||||
tp_button_top_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum button_event event)
|
||||
struct tp_touch *t,
|
||||
enum button_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case BUTTON_EVENT_IN_BOTTOM_R:
|
||||
|
|
@ -268,7 +273,9 @@ tp_button_top_handle_event(struct tp_dispatch *tp,
|
|||
case BUTTON_EVENT_IN_TOP_M:
|
||||
case BUTTON_EVENT_IN_TOP_L:
|
||||
if (event != t->button.curr)
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_TOP_NEW,
|
||||
tp_button_set_state(tp,
|
||||
t,
|
||||
BUTTON_STATE_TOP_NEW,
|
||||
event);
|
||||
break;
|
||||
case BUTTON_EVENT_IN_AREA:
|
||||
|
|
@ -286,8 +293,8 @@ tp_button_top_handle_event(struct tp_dispatch *tp,
|
|||
|
||||
static void
|
||||
tp_button_top_new_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum button_event event)
|
||||
struct tp_touch *t,
|
||||
enum button_event event)
|
||||
{
|
||||
switch(event) {
|
||||
case BUTTON_EVENT_IN_BOTTOM_R:
|
||||
|
|
@ -298,7 +305,9 @@ tp_button_top_new_handle_event(struct tp_dispatch *tp,
|
|||
case BUTTON_EVENT_IN_TOP_M:
|
||||
case BUTTON_EVENT_IN_TOP_L:
|
||||
if (event != t->button.curr)
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_TOP_NEW,
|
||||
tp_button_set_state(tp,
|
||||
t,
|
||||
BUTTON_STATE_TOP_NEW,
|
||||
event);
|
||||
break;
|
||||
case BUTTON_EVENT_IN_AREA:
|
||||
|
|
@ -320,18 +329,22 @@ tp_button_top_new_handle_event(struct tp_dispatch *tp,
|
|||
|
||||
static void
|
||||
tp_button_top_to_ignore_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum button_event event)
|
||||
struct tp_touch *t,
|
||||
enum button_event event)
|
||||
{
|
||||
switch(event) {
|
||||
case BUTTON_EVENT_IN_TOP_R:
|
||||
case BUTTON_EVENT_IN_TOP_M:
|
||||
case BUTTON_EVENT_IN_TOP_L:
|
||||
if (event == t->button.curr)
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_TOP,
|
||||
tp_button_set_state(tp,
|
||||
t,
|
||||
BUTTON_STATE_TOP,
|
||||
event);
|
||||
else
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_TOP_NEW,
|
||||
tp_button_set_state(tp,
|
||||
t,
|
||||
BUTTON_STATE_TOP_NEW,
|
||||
event);
|
||||
break;
|
||||
case BUTTON_EVENT_IN_BOTTOM_R:
|
||||
|
|
@ -352,8 +365,8 @@ tp_button_top_to_ignore_handle_event(struct tp_dispatch *tp,
|
|||
|
||||
static void
|
||||
tp_button_ignore_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum button_event event)
|
||||
struct tp_touch *t,
|
||||
enum button_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case BUTTON_EVENT_IN_BOTTOM_R:
|
||||
|
|
@ -426,18 +439,22 @@ tp_button_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
if (t->state == TOUCH_END) {
|
||||
tp_button_handle_event(tp, t, BUTTON_EVENT_UP, time);
|
||||
} else if (t->dirty) {
|
||||
enum button_event event;
|
||||
|
||||
if (is_inside_bottom_right_area(tp, t))
|
||||
tp_button_handle_event(tp, t, BUTTON_EVENT_IN_BOTTOM_R, time);
|
||||
event = BUTTON_EVENT_IN_BOTTOM_R;
|
||||
else if (is_inside_bottom_left_area(tp, t))
|
||||
tp_button_handle_event(tp, t, BUTTON_EVENT_IN_BOTTOM_L, time);
|
||||
event = BUTTON_EVENT_IN_BOTTOM_L;
|
||||
else if (is_inside_top_right_area(tp, t))
|
||||
tp_button_handle_event(tp, t, BUTTON_EVENT_IN_TOP_R, time);
|
||||
event = BUTTON_EVENT_IN_TOP_R;
|
||||
else if (is_inside_top_middle_area(tp, t))
|
||||
tp_button_handle_event(tp, t, BUTTON_EVENT_IN_TOP_M, time);
|
||||
event = BUTTON_EVENT_IN_TOP_M;
|
||||
else if (is_inside_top_left_area(tp, t))
|
||||
tp_button_handle_event(tp, t, BUTTON_EVENT_IN_TOP_L, time);
|
||||
event = BUTTON_EVENT_IN_TOP_L;
|
||||
else
|
||||
tp_button_handle_event(tp, t, BUTTON_EVENT_IN_AREA, time);
|
||||
event = BUTTON_EVENT_IN_AREA;
|
||||
|
||||
tp_button_handle_event(tp, t, event, time);
|
||||
}
|
||||
if (tp->queued & TOUCHPAD_EVENT_BUTTON_RELEASE)
|
||||
tp_button_handle_event(tp, t, BUTTON_EVENT_RELEASE, time);
|
||||
|
|
@ -629,12 +646,25 @@ tp_button_config_click_get_method(struct libinput_device *device)
|
|||
static enum libinput_config_click_method
|
||||
tp_click_get_default_method(struct tp_dispatch *tp)
|
||||
{
|
||||
struct evdev_device *device = tp->device;
|
||||
|
||||
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;
|
||||
else
|
||||
return LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
|
||||
|
||||
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:
|
||||
return LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
|
||||
}
|
||||
|
||||
static enum libinput_config_click_method
|
||||
|
|
@ -694,6 +724,10 @@ tp_init_buttons(struct tp_dispatch *tp,
|
|||
|
||||
tp_init_top_softbuttons(tp, device, 1.0);
|
||||
|
||||
if (!tp->buttons.is_clickpad &&
|
||||
!libevdev_has_event_code(device->evdev, EV_KEY, BTN_MIDDLE))
|
||||
evdev_init_middlebutton(tp->device, true, false);
|
||||
|
||||
tp_for_each_touch(tp, t) {
|
||||
t->button.state = BUTTON_STATE_NONE;
|
||||
libinput_timer_init(&t->button.timer,
|
||||
|
|
@ -734,10 +768,10 @@ tp_post_physical_buttons(struct tp_dispatch *tp, uint64_t time)
|
|||
state = LIBINPUT_BUTTON_STATE_RELEASED;
|
||||
|
||||
b = evdev_to_left_handed(tp->device, button);
|
||||
evdev_pointer_notify_button(tp->device,
|
||||
time,
|
||||
b,
|
||||
state);
|
||||
evdev_pointer_notify_physical_button(tp->device,
|
||||
time,
|
||||
b,
|
||||
state);
|
||||
}
|
||||
|
||||
button++;
|
||||
|
|
@ -765,8 +799,10 @@ tp_notify_clickpadbutton(struct tp_dispatch *tp,
|
|||
event.type = EV_KEY;
|
||||
event.code = button;
|
||||
event.value = (state == LIBINPUT_BUTTON_STATE_PRESSED) ? 1 : 0;
|
||||
dispatch->interface->process(dispatch, tp->buttons.trackpoint,
|
||||
&event, time);
|
||||
dispatch->interface->process(dispatch,
|
||||
tp->buttons.trackpoint,
|
||||
&event,
|
||||
time);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -779,8 +815,9 @@ tp_notify_clickpadbutton(struct tp_dispatch *tp,
|
|||
* by the softbutton code with one based on the number of fingers.
|
||||
*/
|
||||
if (tp->buttons.click_method == LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER &&
|
||||
state == LIBINPUT_BUTTON_STATE_PRESSED) {
|
||||
state == LIBINPUT_BUTTON_STATE_PRESSED) {
|
||||
switch (tp->nfingers_down) {
|
||||
case 0:
|
||||
case 1: button = BTN_LEFT; break;
|
||||
case 2: button = BTN_RIGHT; break;
|
||||
case 3: button = BTN_MIDDLE; break;
|
||||
|
|
@ -814,46 +851,48 @@ tp_post_clickpadbutton_buttons(struct tp_dispatch *tp, uint64_t time)
|
|||
|
||||
if (current) {
|
||||
struct tp_touch *t;
|
||||
uint32_t area = 0;
|
||||
|
||||
tp_for_each_touch(tp, t) {
|
||||
switch (t->button.curr) {
|
||||
case BUTTON_EVENT_IN_AREA:
|
||||
button |= AREA;
|
||||
area |= AREA;
|
||||
break;
|
||||
case BUTTON_EVENT_IN_TOP_L:
|
||||
is_top = 1;
|
||||
/* fallthrough */
|
||||
case BUTTON_EVENT_IN_BOTTOM_L:
|
||||
button |= LEFT;
|
||||
area |= LEFT;
|
||||
break;
|
||||
case BUTTON_EVENT_IN_TOP_M:
|
||||
is_top = 1;
|
||||
button |= MIDDLE;
|
||||
area |= MIDDLE;
|
||||
break;
|
||||
case BUTTON_EVENT_IN_TOP_R:
|
||||
is_top = 1;
|
||||
/* fallthrough */
|
||||
case BUTTON_EVENT_IN_BOTTOM_R:
|
||||
button |= RIGHT;
|
||||
area |= RIGHT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (button == 0) {
|
||||
if (area == 0 &&
|
||||
tp->buttons.click_method != LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) {
|
||||
/* No touches, wait for a touch before processing */
|
||||
tp->buttons.click_pending = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((button & MIDDLE) || ((button & LEFT) && (button & RIGHT)))
|
||||
if ((area & MIDDLE) || ((area & LEFT) && (area & RIGHT)))
|
||||
button = evdev_to_left_handed(tp->device, BTN_MIDDLE);
|
||||
else if (button & RIGHT)
|
||||
else if (area & RIGHT)
|
||||
button = evdev_to_left_handed(tp->device, BTN_RIGHT);
|
||||
else if (button & LEFT)
|
||||
else if (area & LEFT)
|
||||
button = evdev_to_left_handed(tp->device, BTN_LEFT);
|
||||
else /* main area is always BTN_LEFT */
|
||||
else /* main or no area (for clickfinger) is always BTN_LEFT */
|
||||
button = BTN_LEFT;
|
||||
|
||||
tp->buttons.active = button;
|
||||
|
|
@ -870,8 +909,11 @@ tp_post_clickpadbutton_buttons(struct tp_dispatch *tp, uint64_t time)
|
|||
tp->buttons.click_pending = false;
|
||||
|
||||
if (button)
|
||||
return tp_notify_clickpadbutton(tp, time, button, is_top, state);
|
||||
|
||||
return tp_notify_clickpadbutton(tp,
|
||||
time,
|
||||
button,
|
||||
is_top,
|
||||
state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -893,5 +935,6 @@ tp_button_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
bool
|
||||
tp_button_is_inside_softbutton_area(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
return is_inside_top_button_area(tp, t) || is_inside_bottom_button_area(tp, t);
|
||||
return is_inside_top_button_area(tp, t) ||
|
||||
is_inside_bottom_button_area(tp, t);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "evdev-mt-touchpad.h"
|
||||
|
||||
#define CASE_RETURN_STRING(a) case a: return #a
|
||||
|
||||
#define DEFAULT_SCROLL_LOCK_TIMEOUT 300 /* ms */
|
||||
/* Use a reasonably large threshold until locked into scrolling mode, to
|
||||
avoid accidentally locking in scrolling mode when trying to use the entire
|
||||
|
|
@ -44,6 +46,32 @@ enum scroll_event {
|
|||
SCROLL_EVENT_POSTED,
|
||||
};
|
||||
|
||||
static inline const char*
|
||||
edge_state_to_str(enum tp_edge_scroll_touch_state state)
|
||||
{
|
||||
|
||||
switch (state) {
|
||||
CASE_RETURN_STRING(EDGE_SCROLL_TOUCH_STATE_NONE);
|
||||
CASE_RETURN_STRING(EDGE_SCROLL_TOUCH_STATE_EDGE_NEW);
|
||||
CASE_RETURN_STRING(EDGE_SCROLL_TOUCH_STATE_EDGE);
|
||||
CASE_RETURN_STRING(EDGE_SCROLL_TOUCH_STATE_AREA);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline const char*
|
||||
edge_event_to_str(enum scroll_event event)
|
||||
{
|
||||
switch (event) {
|
||||
CASE_RETURN_STRING(SCROLL_EVENT_TOUCH);
|
||||
CASE_RETURN_STRING(SCROLL_EVENT_MOTION);
|
||||
CASE_RETURN_STRING(SCROLL_EVENT_RELEASE);
|
||||
CASE_RETURN_STRING(SCROLL_EVENT_TIMEOUT);
|
||||
CASE_RETURN_STRING(SCROLL_EVENT_POSTED);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
tp_touch_get_edge(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
|
|
@ -204,7 +232,10 @@ tp_edge_scroll_handle_event(struct tp_dispatch *tp,
|
|||
struct tp_touch *t,
|
||||
enum scroll_event event)
|
||||
{
|
||||
switch (t->scroll.edge_state) {
|
||||
struct libinput *libinput = tp->device->base.seat->libinput;
|
||||
enum tp_edge_scroll_touch_state current = t->scroll.edge_state;
|
||||
|
||||
switch (current) {
|
||||
case EDGE_SCROLL_TOUCH_STATE_NONE:
|
||||
tp_edge_scroll_handle_none(tp, t, event);
|
||||
break;
|
||||
|
|
@ -218,6 +249,12 @@ tp_edge_scroll_handle_event(struct tp_dispatch *tp,
|
|||
tp_edge_scroll_handle_area(tp, t, event);
|
||||
break;
|
||||
}
|
||||
|
||||
log_debug(libinput,
|
||||
"edge state: %s → %s → %s\n",
|
||||
edge_state_to_str(current),
|
||||
edge_event_to_str(event),
|
||||
edge_state_to_str(t->scroll.edge_state));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -313,7 +350,6 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
struct tp_touch *t;
|
||||
enum libinput_pointer_axis axis;
|
||||
double *delta;
|
||||
double initial_dx, initial_dy, *initial_delta;
|
||||
struct normalized_coords normalized;
|
||||
const struct normalized_coords zero = { 0.0, 0.0 };
|
||||
const struct discrete_coords zero_discrete = { 0.0, 0.0 };
|
||||
|
|
@ -340,20 +376,17 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
case EDGE_RIGHT:
|
||||
axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
|
||||
delta = &normalized.y;
|
||||
initial_delta = &initial_dy;
|
||||
break;
|
||||
case EDGE_BOTTOM:
|
||||
axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
|
||||
delta = &normalized.x;
|
||||
initial_delta = &initial_dx;
|
||||
break;
|
||||
default: /* EDGE_RIGHT | EDGE_BOTTOM */
|
||||
continue; /* Don't know direction yet, skip */
|
||||
}
|
||||
|
||||
normalized = tp_get_delta(t);
|
||||
tp_filter_motion(tp, &normalized.x, &normalized.y,
|
||||
NULL, NULL, time);
|
||||
normalized = tp_filter_motion(tp, &normalized, time);
|
||||
|
||||
switch (t->scroll.edge_state) {
|
||||
case EDGE_SCROLL_TOUCH_STATE_NONE:
|
||||
|
|
@ -363,16 +396,11 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
t->scroll.edge_state);
|
||||
break;
|
||||
case EDGE_SCROLL_TOUCH_STATE_EDGE_NEW:
|
||||
initial_dx = t->point.x - t->scroll.initial.x;
|
||||
initial_dy = t->point.y - t->scroll.initial.y;
|
||||
tp_normalize_delta(tp,
|
||||
initial_dx,
|
||||
initial_dy,
|
||||
&normalized);
|
||||
if (fabs(*initial_delta) < DEFAULT_SCROLL_THRESHOLD) {
|
||||
normalized.x = 0.0;
|
||||
normalized.y = 0.0;
|
||||
}
|
||||
normalized = tp_normalize_delta(tp,
|
||||
device_delta(t->point,
|
||||
t->scroll.initial));
|
||||
if (fabs(*delta) < DEFAULT_SCROLL_THRESHOLD)
|
||||
normalized = zero;
|
||||
break;
|
||||
case EDGE_SCROLL_TOUCH_STATE_EDGE:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ tp_get_touches_delta(struct tp_dispatch *tp, bool average)
|
|||
struct normalized_coords normalized;
|
||||
struct normalized_coords delta = {0.0, 0.0};
|
||||
|
||||
for (i = 0; i < tp->real_touches; i++) {
|
||||
for (i = 0; i < tp->num_slots; i++) {
|
||||
t = &tp->touches[i];
|
||||
|
||||
if (tp_touch_active(tp, t) && t->dirty) {
|
||||
|
|
@ -93,14 +93,13 @@ tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time)
|
|||
|
||||
/* When a clickpad is clicked, combine motion of all active touches */
|
||||
if (tp->buttons.is_clickpad && tp->buttons.state)
|
||||
delta = tp_get_combined_touches_delta(tp);
|
||||
unaccel = tp_get_combined_touches_delta(tp);
|
||||
else
|
||||
delta = tp_get_average_touches_delta(tp);
|
||||
unaccel = tp_get_average_touches_delta(tp);
|
||||
|
||||
tp_filter_motion(tp, &delta.x, &delta.y, &unaccel.x, &unaccel.y, time);
|
||||
delta = tp_filter_motion(tp, &unaccel, time);
|
||||
|
||||
if (delta.x != 0.0 || delta.y != 0.0 ||
|
||||
unaccel.x != 0.0 || unaccel.y != 0.0) {
|
||||
if (!normalized_is_zero(delta) || !normalized_is_zero(unaccel)) {
|
||||
pointer_notify_motion(&tp->device->base, time,
|
||||
&delta, &unaccel);
|
||||
}
|
||||
|
|
@ -111,10 +110,23 @@ tp_gesture_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
|
|||
{
|
||||
struct normalized_coords delta;
|
||||
|
||||
delta = tp_get_average_touches_delta(tp);
|
||||
tp_filter_motion(tp, &delta.x, &delta.y, NULL, NULL, time);
|
||||
if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_2FG)
|
||||
return;
|
||||
|
||||
if (delta.x == 0.0 && delta.y == 0.0)
|
||||
/* On some semi-mt models slot 0 is more accurate, so for semi-mt
|
||||
* we only use slot 0. */
|
||||
if (tp->semi_mt) {
|
||||
if (!tp->touches[0].dirty)
|
||||
return;
|
||||
|
||||
delta = tp_get_delta(&tp->touches[0]);
|
||||
} else {
|
||||
delta = tp_get_average_touches_delta(tp);
|
||||
}
|
||||
|
||||
delta = tp_filter_motion(tp, &delta, time);
|
||||
|
||||
if (normalized_is_zero(delta))
|
||||
return;
|
||||
|
||||
tp_gesture_start(tp, time);
|
||||
|
|
@ -154,6 +166,9 @@ tp_gesture_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
void
|
||||
tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_2FG)
|
||||
return;
|
||||
|
||||
evdev_stop_scroll(tp->device,
|
||||
time,
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
|
||||
|
|
|
|||
|
|
@ -34,9 +34,10 @@
|
|||
|
||||
#include "evdev-mt-touchpad.h"
|
||||
|
||||
#define CASE_RETURN_STRING(a) case a: return #a;
|
||||
#define CASE_RETURN_STRING(a) case a: return #a
|
||||
|
||||
#define DEFAULT_TAP_TIMEOUT_PERIOD 180
|
||||
#define DEFAULT_DRAG_TIMEOUT_PERIOD 500
|
||||
#define DEFAULT_TAP_MOVE_THRESHOLD TP_MM_TO_DPI_NORMALIZED(3)
|
||||
|
||||
enum tap_event {
|
||||
|
|
@ -59,8 +60,8 @@ enum tap_event {
|
|||
*/
|
||||
|
||||
static inline const char*
|
||||
tap_state_to_str(enum tp_tap_state state) {
|
||||
|
||||
tap_state_to_str(enum tp_tap_state state)
|
||||
{
|
||||
switch(state) {
|
||||
CASE_RETURN_STRING(TAP_STATE_IDLE);
|
||||
CASE_RETURN_STRING(TAP_STATE_HOLD);
|
||||
|
|
@ -73,15 +74,18 @@ tap_state_to_str(enum tp_tap_state state) {
|
|||
CASE_RETURN_STRING(TAP_STATE_DRAGGING);
|
||||
CASE_RETURN_STRING(TAP_STATE_DRAGGING_WAIT);
|
||||
CASE_RETURN_STRING(TAP_STATE_DRAGGING_OR_DOUBLETAP);
|
||||
CASE_RETURN_STRING(TAP_STATE_DRAGGING_OR_TAP);
|
||||
CASE_RETURN_STRING(TAP_STATE_DRAGGING_2);
|
||||
CASE_RETURN_STRING(TAP_STATE_MULTITAP);
|
||||
CASE_RETURN_STRING(TAP_STATE_MULTITAP_DOWN);
|
||||
CASE_RETURN_STRING(TAP_STATE_DEAD);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline const char*
|
||||
tap_event_to_str(enum tap_event event) {
|
||||
|
||||
tap_event_to_str(enum tap_event event)
|
||||
{
|
||||
switch(event) {
|
||||
CASE_RETURN_STRING(TAP_EVENT_TOUCH);
|
||||
CASE_RETURN_STRING(TAP_EVENT_MOTION);
|
||||
|
|
@ -126,6 +130,12 @@ tp_tap_set_timer(struct tp_dispatch *tp, uint64_t time)
|
|||
libinput_timer_set(&tp->tap.timer, time + DEFAULT_TAP_TIMEOUT_PERIOD);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_tap_set_drag_timer(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
libinput_timer_set(&tp->tap.timer, time + DEFAULT_DRAG_TIMEOUT_PERIOD);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_tap_clear_timer(struct tp_dispatch *tp)
|
||||
{
|
||||
|
|
@ -145,9 +155,10 @@ tp_tap_idle_handle_event(struct tp_dispatch *tp,
|
|||
tp_tap_set_timer(tp, time);
|
||||
break;
|
||||
case TAP_EVENT_RELEASE:
|
||||
break;
|
||||
case TAP_EVENT_MOTION:
|
||||
log_bug_libinput(libinput,
|
||||
"invalid event, no fingers are down\n");
|
||||
"invalid tap event, no fingers are down\n");
|
||||
break;
|
||||
case TAP_EVENT_TIMEOUT:
|
||||
break;
|
||||
|
|
@ -218,10 +229,11 @@ tp_tap_tapped_handle_event(struct tp_dispatch *tp,
|
|||
case TAP_EVENT_MOTION:
|
||||
case TAP_EVENT_RELEASE:
|
||||
log_bug_libinput(libinput,
|
||||
"invalid event when fingers are up\n");
|
||||
"invalid tap event when fingers are up\n");
|
||||
break;
|
||||
case TAP_EVENT_TOUCH:
|
||||
tp->tap.state = TAP_STATE_DRAGGING_OR_DOUBLETAP;
|
||||
tp_tap_set_timer(tp, time);
|
||||
break;
|
||||
case TAP_EVENT_TIMEOUT:
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
|
|
@ -351,11 +363,8 @@ tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp,
|
|||
tp->tap.state = TAP_STATE_DRAGGING_2;
|
||||
break;
|
||||
case TAP_EVENT_RELEASE:
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
tp->tap.state = TAP_STATE_MULTITAP;
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_clear_timer(tp);
|
||||
break;
|
||||
case TAP_EVENT_MOTION:
|
||||
case TAP_EVENT_TIMEOUT:
|
||||
|
|
@ -380,7 +389,7 @@ tp_tap_dragging_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_RELEASE:
|
||||
tp->tap.state = TAP_STATE_DRAGGING_WAIT;
|
||||
tp_tap_set_timer(tp, time);
|
||||
tp_tap_set_drag_timer(tp, time);
|
||||
break;
|
||||
case TAP_EVENT_MOTION:
|
||||
case TAP_EVENT_TIMEOUT:
|
||||
|
|
@ -401,8 +410,8 @@ tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp,
|
|||
|
||||
switch (event) {
|
||||
case TAP_EVENT_TOUCH:
|
||||
tp->tap.state = TAP_STATE_DRAGGING;
|
||||
tp_tap_clear_timer(tp);
|
||||
tp->tap.state = TAP_STATE_DRAGGING_OR_TAP;
|
||||
tp_tap_set_timer(tp, time);
|
||||
break;
|
||||
case TAP_EVENT_RELEASE:
|
||||
case TAP_EVENT_MOTION:
|
||||
|
|
@ -418,6 +427,32 @@ tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_tap_dragging_tap_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum tap_event event, uint64_t time)
|
||||
{
|
||||
|
||||
switch (event) {
|
||||
case TAP_EVENT_TOUCH:
|
||||
tp->tap.state = TAP_STATE_DRAGGING_2;
|
||||
tp_tap_clear_timer(tp);
|
||||
break;
|
||||
case TAP_EVENT_RELEASE:
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
case TAP_EVENT_MOTION:
|
||||
case TAP_EVENT_TIMEOUT:
|
||||
tp->tap.state = TAP_STATE_DRAGGING;
|
||||
break;
|
||||
case TAP_EVENT_BUTTON:
|
||||
tp->tap.state = TAP_STATE_DEAD;
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_tap_dragging2_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
|
|
@ -443,6 +478,78 @@ tp_tap_dragging2_handle_event(struct tp_dispatch *tp,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_tap_multitap_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum tap_event event, uint64_t time)
|
||||
{
|
||||
struct libinput *libinput = tp->device->base.seat->libinput;
|
||||
|
||||
switch (event) {
|
||||
case TAP_EVENT_RELEASE:
|
||||
log_bug_libinput(libinput,
|
||||
"invalid tap event, no fingers are down\n");
|
||||
break;
|
||||
case TAP_EVENT_TOUCH:
|
||||
tp->tap.state = TAP_STATE_MULTITAP_DOWN;
|
||||
tp->tap.multitap_last_time = time;
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_set_timer(tp, time);
|
||||
break;
|
||||
case TAP_EVENT_MOTION:
|
||||
log_bug_libinput(libinput,
|
||||
"invalid tap event, no fingers are down\n");
|
||||
break;
|
||||
case TAP_EVENT_TIMEOUT:
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
case TAP_EVENT_BUTTON:
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
tp_tap_clear_timer(tp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_tap_multitap_down_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum tap_event event,
|
||||
uint64_t time)
|
||||
{
|
||||
switch (event) {
|
||||
case TAP_EVENT_RELEASE:
|
||||
tp->tap.state = TAP_STATE_MULTITAP;
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
case TAP_EVENT_TOUCH:
|
||||
tp->tap.state = TAP_STATE_DRAGGING_2;
|
||||
tp_tap_notify(tp,
|
||||
tp->tap.multitap_last_time,
|
||||
1,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_clear_timer(tp);
|
||||
break;
|
||||
case TAP_EVENT_MOTION:
|
||||
case TAP_EVENT_TIMEOUT:
|
||||
tp->tap.state = TAP_STATE_DRAGGING;
|
||||
tp_tap_notify(tp,
|
||||
tp->tap.multitap_last_time,
|
||||
1,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_clear_timer(tp);
|
||||
break;
|
||||
case TAP_EVENT_BUTTON:
|
||||
tp->tap.state = TAP_STATE_DEAD;
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_clear_timer(tp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_tap_dead_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
|
|
@ -508,9 +615,18 @@ tp_tap_handle_event(struct tp_dispatch *tp,
|
|||
case TAP_STATE_DRAGGING_WAIT:
|
||||
tp_tap_dragging_wait_handle_event(tp, t, event, time);
|
||||
break;
|
||||
case TAP_STATE_DRAGGING_OR_TAP:
|
||||
tp_tap_dragging_tap_handle_event(tp, t, event, time);
|
||||
break;
|
||||
case TAP_STATE_DRAGGING_2:
|
||||
tp_tap_dragging2_handle_event(tp, t, event, time);
|
||||
break;
|
||||
case TAP_STATE_MULTITAP:
|
||||
tp_tap_multitap_handle_event(tp, t, event, time);
|
||||
break;
|
||||
case TAP_STATE_MULTITAP_DOWN:
|
||||
tp_tap_multitap_down_handle_event(tp, t, event, time);
|
||||
break;
|
||||
case TAP_STATE_DEAD:
|
||||
tp_tap_dead_handle_event(tp, t, event, time);
|
||||
break;
|
||||
|
|
@ -530,16 +646,11 @@ static bool
|
|||
tp_tap_exceeds_motion_threshold(struct tp_dispatch *tp,
|
||||
struct tp_touch *t)
|
||||
{
|
||||
int threshold = DEFAULT_TAP_MOVE_THRESHOLD;
|
||||
double dx, dy;
|
||||
struct normalized_coords normalized;
|
||||
struct normalized_coords norm =
|
||||
tp_normalize_delta(tp, device_delta(t->point,
|
||||
t->tap.initial));
|
||||
|
||||
dx = abs(t->tap.initial.x - t->point.x);
|
||||
dy = abs(t->tap.initial.y - t->point.y);
|
||||
tp_normalize_delta(tp, dx, dy, &normalized);
|
||||
|
||||
return normalized.x * normalized.x + normalized.y * normalized.y
|
||||
> threshold * threshold;
|
||||
return normalized_length(norm) > DEFAULT_TAP_MOVE_THRESHOLD;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -575,6 +686,14 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
t->tap.state = TAP_TOUCH_STATE_TOUCH;
|
||||
t->tap.initial = t->point;
|
||||
tp_tap_handle_event(tp, t, TAP_EVENT_TOUCH, time);
|
||||
|
||||
/* If we think this is a palm, pretend there's a
|
||||
* motion event which will prevent tap clicks
|
||||
* without requiring extra states in the FSM.
|
||||
*/
|
||||
if (tp_palm_tap_is_palm(tp, t))
|
||||
tp_tap_handle_event(tp, t, TAP_EVENT_MOTION, time);
|
||||
|
||||
} else if (t->state == TOUCH_END) {
|
||||
tp_tap_handle_event(tp, t, TAP_EVENT_RELEASE, time);
|
||||
t->tap.state = TAP_TOUCH_STATE_IDLE;
|
||||
|
|
@ -603,8 +722,10 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
case TAP_STATE_TOUCH:
|
||||
case TAP_STATE_TAPPED:
|
||||
case TAP_STATE_DRAGGING_OR_DOUBLETAP:
|
||||
case TAP_STATE_DRAGGING_OR_TAP:
|
||||
case TAP_STATE_TOUCH_2:
|
||||
case TAP_STATE_TOUCH_3:
|
||||
case TAP_STATE_MULTITAP_DOWN:
|
||||
filter_motion = 1;
|
||||
break;
|
||||
|
||||
|
|
@ -780,6 +901,7 @@ tp_tap_dragging(struct tp_dispatch *tp)
|
|||
case TAP_STATE_DRAGGING:
|
||||
case TAP_STATE_DRAGGING_2:
|
||||
case TAP_STATE_DRAGGING_WAIT:
|
||||
case TAP_STATE_DRAGGING_OR_TAP:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@
|
|||
#define DEFAULT_ACCEL_NUMERATOR 3000.0
|
||||
#define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
|
||||
#define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT 500 /* ms */
|
||||
#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1 200 /* ms */
|
||||
#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2 500 /* ms */
|
||||
#define FAKE_FINGER_OVERFLOW (1 << 7)
|
||||
|
||||
static inline int
|
||||
tp_hysteresis(int in, int center, int margin)
|
||||
|
|
@ -58,33 +61,16 @@ tp_motion_history_offset(struct tp_touch *t, int offset)
|
|||
return &t->history.samples[offset_index];
|
||||
}
|
||||
|
||||
void
|
||||
struct normalized_coords
|
||||
tp_filter_motion(struct tp_dispatch *tp,
|
||||
double *dx, double *dy,
|
||||
double *dx_unaccel, double *dy_unaccel,
|
||||
const struct normalized_coords *unaccelerated,
|
||||
uint64_t time)
|
||||
{
|
||||
struct normalized_coords unaccelerated;
|
||||
struct normalized_coords accelerated;
|
||||
if (normalized_is_zero(*unaccelerated))
|
||||
return *unaccelerated;
|
||||
|
||||
unaccelerated.x = *dx;
|
||||
unaccelerated.y = *dy;
|
||||
|
||||
if (unaccelerated.x != 0.0 || unaccelerated.y != 0.0)
|
||||
accelerated = filter_dispatch(tp->device->pointer.filter,
|
||||
&unaccelerated,
|
||||
tp,
|
||||
time);
|
||||
else
|
||||
accelerated = unaccelerated;
|
||||
|
||||
if (dx_unaccel)
|
||||
*dx_unaccel = unaccelerated.x;
|
||||
if (dy_unaccel)
|
||||
*dy_unaccel = unaccelerated.y;
|
||||
|
||||
*dx = accelerated.x;
|
||||
*dy = accelerated.y;
|
||||
return filter_dispatch(tp->device->pointer.filter,
|
||||
unaccelerated, tp, time);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -144,8 +130,10 @@ tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
|
|||
static inline unsigned int
|
||||
tp_fake_finger_count(struct tp_dispatch *tp)
|
||||
{
|
||||
/* don't count BTN_TOUCH */
|
||||
return ffs(tp->fake_touches >> 1);
|
||||
if (tp->fake_touches & FAKE_FINGER_OVERFLOW)
|
||||
return FAKE_FINGER_OVERFLOW;
|
||||
else /* don't count BTN_TOUCH */
|
||||
return ffs(tp->fake_touches >> 1);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
|
|
@ -163,6 +151,8 @@ tp_fake_finger_set(struct tp_dispatch *tp,
|
|||
|
||||
switch (code) {
|
||||
case BTN_TOUCH:
|
||||
if (!is_press)
|
||||
tp->fake_touches &= ~FAKE_FINGER_OVERFLOW;
|
||||
shift = 0;
|
||||
break;
|
||||
case BTN_TOOL_FINGER:
|
||||
|
|
@ -173,14 +163,24 @@ tp_fake_finger_set(struct tp_dispatch *tp,
|
|||
case BTN_TOOL_QUADTAP:
|
||||
shift = code - BTN_TOOL_DOUBLETAP + 2;
|
||||
break;
|
||||
/* when QUINTTAP is released we're either switching to 6 fingers
|
||||
(flag stays in place until BTN_TOUCH is released) or
|
||||
one of DOUBLE/TRIPLE/QUADTAP (will clear the flag on press) */
|
||||
case BTN_TOOL_QUINTTAP:
|
||||
if (is_press)
|
||||
tp->fake_touches |= FAKE_FINGER_OVERFLOW;
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_press)
|
||||
if (is_press) {
|
||||
tp->fake_touches &= ~FAKE_FINGER_OVERFLOW;
|
||||
tp->fake_touches |= 1 << shift;
|
||||
else
|
||||
|
||||
} else {
|
||||
tp->fake_touches &= ~(0x1 << shift);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -233,7 +233,7 @@ tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
}
|
||||
|
||||
t->dirty = true;
|
||||
t->palm.is_palm = false;
|
||||
t->palm.state = PALM_NONE;
|
||||
t->state = TOUCH_END;
|
||||
t->pinned.is_pinned = false;
|
||||
t->millis = time;
|
||||
|
|
@ -261,23 +261,22 @@ tp_estimate_delta(int x0, int x1, int x2, int x3)
|
|||
struct normalized_coords
|
||||
tp_get_delta(struct tp_touch *t)
|
||||
{
|
||||
double dx, dy; /* in device coords */
|
||||
struct normalized_coords normalized = { 0.0, 0.0 };
|
||||
struct device_float_coords delta;
|
||||
const struct normalized_coords zero = { 0.0, 0.0 };
|
||||
|
||||
if (t->history.count < TOUCHPAD_MIN_SAMPLES)
|
||||
return normalized;
|
||||
return zero;
|
||||
|
||||
dx = tp_estimate_delta(tp_motion_history_offset(t, 0)->x,
|
||||
tp_motion_history_offset(t, 1)->x,
|
||||
tp_motion_history_offset(t, 2)->x,
|
||||
tp_motion_history_offset(t, 3)->x);
|
||||
dy = tp_estimate_delta(tp_motion_history_offset(t, 0)->y,
|
||||
tp_motion_history_offset(t, 1)->y,
|
||||
tp_motion_history_offset(t, 2)->y,
|
||||
tp_motion_history_offset(t, 3)->y);
|
||||
tp_normalize_delta(t->tp, dx, dy, &normalized);
|
||||
delta.x = tp_estimate_delta(tp_motion_history_offset(t, 0)->x,
|
||||
tp_motion_history_offset(t, 1)->x,
|
||||
tp_motion_history_offset(t, 2)->x,
|
||||
tp_motion_history_offset(t, 3)->x);
|
||||
delta.y = tp_estimate_delta(tp_motion_history_offset(t, 0)->y,
|
||||
tp_motion_history_offset(t, 1)->y,
|
||||
tp_motion_history_offset(t, 2)->y,
|
||||
tp_motion_history_offset(t, 3)->y);
|
||||
|
||||
return normalized;
|
||||
return tp_normalize_delta(t->tp, delta);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -303,6 +302,9 @@ tp_process_absolute(struct tp_dispatch *tp,
|
|||
case ABS_MT_SLOT:
|
||||
tp->slot = e->value;
|
||||
break;
|
||||
case ABS_MT_DISTANCE:
|
||||
t->distance = e->value;
|
||||
break;
|
||||
case ABS_MT_TRACKING_ID:
|
||||
if (e->value != -1)
|
||||
tp_new_touch(tp, t, time);
|
||||
|
|
@ -335,19 +337,18 @@ tp_process_absolute_st(struct tp_dispatch *tp,
|
|||
}
|
||||
|
||||
static void
|
||||
tp_process_fake_touch(struct tp_dispatch *tp,
|
||||
const struct input_event *e,
|
||||
uint64_t time)
|
||||
tp_process_fake_touches(struct tp_dispatch *tp,
|
||||
uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
unsigned int nfake_touches;
|
||||
unsigned int i, start;
|
||||
|
||||
tp_fake_finger_set(tp, e->code, e->value != 0);
|
||||
|
||||
nfake_touches = tp_fake_finger_count(tp);
|
||||
if (nfake_touches == FAKE_FINGER_OVERFLOW)
|
||||
return;
|
||||
|
||||
start = tp->has_mt ? tp->real_touches : 0;
|
||||
start = tp->has_mt ? tp->num_slots : 0;
|
||||
for (i = start; i < tp->ntouches; i++) {
|
||||
t = tp_get_touch(tp, i);
|
||||
if (i < nfake_touches)
|
||||
|
|
@ -408,7 +409,8 @@ tp_process_key(struct tp_dispatch *tp,
|
|||
case BTN_TOOL_DOUBLETAP:
|
||||
case BTN_TOOL_TRIPLETAP:
|
||||
case BTN_TOOL_QUADTAP:
|
||||
tp_process_fake_touch(tp, e, time);
|
||||
case BTN_TOOL_QUINTTAP:
|
||||
tp_fake_finger_set(tp, e->code, !!e->value);
|
||||
break;
|
||||
case BTN_0:
|
||||
case BTN_1:
|
||||
|
|
@ -455,29 +457,58 @@ int
|
|||
tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
|
||||
!t->palm.is_palm &&
|
||||
t->palm.state == PALM_NONE &&
|
||||
!t->pinned.is_pinned &&
|
||||
tp_button_touch_active(tp, t) &&
|
||||
tp_edge_scroll_touch_active(tp, t);
|
||||
}
|
||||
|
||||
bool
|
||||
tp_palm_tap_is_palm(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
if (t->state != TOUCH_BEGIN)
|
||||
return false;
|
||||
|
||||
if (t->point.x > tp->palm.left_edge &&
|
||||
t->point.x < tp->palm.right_edge)
|
||||
return false;
|
||||
|
||||
/* We're inside the left/right palm edge and in the northern half of
|
||||
* the touchpad - this tap is a palm */
|
||||
if (t->point.y < tp->palm.vert_center)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
||||
{
|
||||
const int PALM_TIMEOUT = 200; /* ms */
|
||||
const int DIRECTIONS = NE|E|SE|SW|W|NW;
|
||||
struct device_float_coords delta;
|
||||
int dirs;
|
||||
|
||||
if (tp->sendevents.keyboard_active &&
|
||||
t->state == TOUCH_BEGIN) {
|
||||
t->palm.state = PALM_TYPING;
|
||||
t->palm.time = time;
|
||||
t->palm.first = t->point;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If labelled a touch as palm, we unlabel as palm when
|
||||
we move out of the palm edge zone within the timeout, provided
|
||||
the direction is within 45 degrees of the horizontal.
|
||||
*/
|
||||
if (t->palm.is_palm) {
|
||||
if (t->palm.state == PALM_EDGE) {
|
||||
if (time < t->palm.time + PALM_TIMEOUT &&
|
||||
(t->point.x > tp->palm.left_edge && t->point.x < tp->palm.right_edge)) {
|
||||
int dirs = vector_get_direction(t->point.x - t->palm.first.x,
|
||||
t->point.y - t->palm.first.y);
|
||||
delta = device_delta(t->point, t->palm.first);
|
||||
dirs = normalized_get_direction(
|
||||
tp_normalize_delta(tp, delta));
|
||||
if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS)) {
|
||||
t->palm.is_palm = false;
|
||||
t->palm.state = PALM_NONE;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
@ -496,13 +527,35 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
tp_button_is_inside_softbutton_area(tp, t))
|
||||
return;
|
||||
|
||||
t->palm.is_palm = true;
|
||||
t->palm.state = PALM_EDGE;
|
||||
t->palm.time = time;
|
||||
t->palm.first = t->point;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
|
||||
tp_unhover_abs_distance(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < tp->ntouches; i++) {
|
||||
t = tp_get_touch(tp, i);
|
||||
|
||||
if (t->state == TOUCH_HOVERING) {
|
||||
if (t->distance == 0) {
|
||||
/* avoid jumps when landing a finger */
|
||||
tp_motion_history_reset(t);
|
||||
tp_begin_touch(tp, t, time);
|
||||
}
|
||||
} else {
|
||||
if (t->distance > 0)
|
||||
tp_end_touch(tp, t, time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_unhover_fake_touches(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
unsigned int nfake_touches;
|
||||
|
|
@ -512,6 +565,9 @@ tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
|
|||
return;
|
||||
|
||||
nfake_touches = tp_fake_finger_count(tp);
|
||||
if (nfake_touches == FAKE_FINGER_OVERFLOW)
|
||||
return;
|
||||
|
||||
if (tp->nfingers_down == nfake_touches &&
|
||||
((tp->nfingers_down == 0 && !tp_fake_finger_is_touching(tp)) ||
|
||||
(tp->nfingers_down > 0 && tp_fake_finger_is_touching(tp))))
|
||||
|
|
@ -544,7 +600,8 @@ tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
|
|||
for (i = tp->ntouches - 1; i >= 0; i--) {
|
||||
t = tp_get_touch(tp, i);
|
||||
|
||||
if (t->state == TOUCH_HOVERING)
|
||||
if (t->state == TOUCH_HOVERING ||
|
||||
t->state == TOUCH_NONE)
|
||||
continue;
|
||||
|
||||
tp_end_touch(tp, t, time);
|
||||
|
|
@ -556,6 +613,16 @@ tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
if (tp->reports_distance)
|
||||
tp_unhover_abs_distance(tp, time);
|
||||
else
|
||||
tp_unhover_fake_touches(tp, time);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
tp_process_state(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
|
|
@ -563,6 +630,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
|
|||
struct tp_touch *first = tp_get_touch(tp, 0);
|
||||
unsigned int i;
|
||||
|
||||
tp_process_fake_touches(tp, time);
|
||||
tp_unhover_touches(tp, time);
|
||||
|
||||
for (i = 0; i < tp->ntouches; i++) {
|
||||
|
|
@ -572,7 +640,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
|
|||
if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down)
|
||||
tp_motion_history_reset(t);
|
||||
|
||||
if (i >= tp->real_touches && t->state != TOUCH_NONE) {
|
||||
if (i >= tp->num_slots && t->state != TOUCH_NONE) {
|
||||
t->point = first->point;
|
||||
if (!t->dirty)
|
||||
t->dirty = first->dirty;
|
||||
|
|
@ -647,7 +715,9 @@ tp_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
filter_motion |= tp_tap_handle_state(tp, time);
|
||||
filter_motion |= tp_post_button_events(tp, time);
|
||||
|
||||
if (filter_motion || tp->sendevents.trackpoint_active) {
|
||||
if (filter_motion ||
|
||||
tp->sendevents.trackpoint_active ||
|
||||
tp->sendevents.keyboard_active) {
|
||||
tp_edge_scroll_stop_events(tp, time);
|
||||
tp_gesture_stop(tp, time);
|
||||
return;
|
||||
|
|
@ -669,10 +739,10 @@ tp_handle_state(struct tp_dispatch *tp,
|
|||
}
|
||||
|
||||
static void
|
||||
tp_process(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
struct input_event *e,
|
||||
uint64_t time)
|
||||
tp_interface_process(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
struct input_event *e,
|
||||
uint64_t time)
|
||||
{
|
||||
struct tp_dispatch *tp =
|
||||
(struct tp_dispatch *)dispatch;
|
||||
|
|
@ -697,14 +767,19 @@ static void
|
|||
tp_remove_sendevents(struct tp_dispatch *tp)
|
||||
{
|
||||
libinput_timer_cancel(&tp->sendevents.trackpoint_timer);
|
||||
libinput_timer_cancel(&tp->sendevents.keyboard_timer);
|
||||
|
||||
if (tp->buttons.trackpoint)
|
||||
libinput_device_remove_event_listener(
|
||||
&tp->sendevents.trackpoint_listener);
|
||||
|
||||
if (tp->sendevents.keyboard)
|
||||
libinput_device_remove_event_listener(
|
||||
&tp->sendevents.keyboard_listener);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_remove(struct evdev_dispatch *dispatch)
|
||||
tp_interface_remove(struct evdev_dispatch *dispatch)
|
||||
{
|
||||
struct tp_dispatch *tp =
|
||||
(struct tp_dispatch*)dispatch;
|
||||
|
|
@ -717,7 +792,7 @@ tp_remove(struct evdev_dispatch *dispatch)
|
|||
}
|
||||
|
||||
static void
|
||||
tp_destroy(struct evdev_dispatch *dispatch)
|
||||
tp_interface_destroy(struct evdev_dispatch *dispatch)
|
||||
{
|
||||
struct tp_dispatch *tp =
|
||||
(struct tp_dispatch*)dispatch;
|
||||
|
|
@ -726,6 +801,12 @@ tp_destroy(struct evdev_dispatch *dispatch)
|
|||
free(tp);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_release_fake_touches(struct tp_dispatch *tp)
|
||||
{
|
||||
tp->fake_touches = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_clear_state(struct tp_dispatch *tp)
|
||||
{
|
||||
|
|
@ -749,6 +830,7 @@ tp_clear_state(struct tp_dispatch *tp)
|
|||
tp_for_each_touch(tp, t) {
|
||||
tp_end_sequence(tp, t, now);
|
||||
}
|
||||
tp_release_fake_touches(tp);
|
||||
|
||||
tp_handle_state(tp, now);
|
||||
}
|
||||
|
|
@ -771,6 +853,15 @@ tp_suspend(struct tp_dispatch *tp, struct evdev_device *device)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_interface_suspend(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
struct tp_dispatch *tp = (struct tp_dispatch *)dispatch;
|
||||
|
||||
tp_clear_state(tp);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_resume(struct tp_dispatch *tp, struct evdev_device *device)
|
||||
{
|
||||
|
|
@ -816,13 +907,76 @@ tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data)
|
|||
}
|
||||
|
||||
static void
|
||||
tp_device_added(struct evdev_device *device,
|
||||
struct evdev_device *added_device)
|
||||
tp_keyboard_timeout(uint64_t now, void *data)
|
||||
{
|
||||
struct tp_dispatch *tp = data;
|
||||
|
||||
tp_tap_resume(tp, now);
|
||||
tp->sendevents.keyboard_active = false;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_keyboard_event(uint64_t time, struct libinput_event *event, void *data)
|
||||
{
|
||||
struct tp_dispatch *tp = data;
|
||||
struct libinput_event_keyboard *kbdev;
|
||||
unsigned int timeout;
|
||||
|
||||
if (event->type != LIBINPUT_EVENT_KEYBOARD_KEY)
|
||||
return;
|
||||
|
||||
kbdev = libinput_event_get_keyboard_event(event);
|
||||
|
||||
/* Only trigger the timer on key down. */
|
||||
if (libinput_event_keyboard_get_key_state(kbdev) !=
|
||||
LIBINPUT_KEY_STATE_PRESSED)
|
||||
return;
|
||||
|
||||
/* modifier keys don't trigger disable-while-typing so things like
|
||||
* ctrl+zoom or ctrl+click are possible */
|
||||
switch (libinput_event_keyboard_get_key(kbdev)) {
|
||||
case KEY_LEFTCTRL:
|
||||
case KEY_RIGHTCTRL:
|
||||
case KEY_LEFTALT:
|
||||
case KEY_RIGHTALT:
|
||||
case KEY_LEFTSHIFT:
|
||||
case KEY_RIGHTSHIFT:
|
||||
case KEY_FN:
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tp->sendevents.keyboard_active) {
|
||||
tp_edge_scroll_stop_events(tp, time);
|
||||
tp_gesture_stop(tp, time);
|
||||
tp_tap_suspend(tp, time);
|
||||
tp->sendevents.keyboard_active = true;
|
||||
timeout = DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1;
|
||||
} else {
|
||||
timeout = DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2;
|
||||
}
|
||||
|
||||
libinput_timer_set(&tp->sendevents.keyboard_timer,
|
||||
time + timeout);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_interface_device_added(struct evdev_device *device,
|
||||
struct evdev_device *added_device)
|
||||
{
|
||||
struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
|
||||
unsigned int bus_tp = libevdev_get_id_bustype(device->evdev),
|
||||
bus_trp = libevdev_get_id_bustype(added_device->evdev),
|
||||
bus_kbd = libevdev_get_id_bustype(added_device->evdev);
|
||||
bool tp_is_internal, trp_is_internal, kbd_is_internal;
|
||||
|
||||
tp_is_internal = bus_tp != BUS_USB && bus_tp != BUS_BLUETOOTH;
|
||||
trp_is_internal = bus_trp != BUS_USB && bus_trp != BUS_BLUETOOTH;
|
||||
|
||||
if (tp->buttons.trackpoint == NULL &&
|
||||
(added_device->tags & EVDEV_TAG_TRACKPOINT)) {
|
||||
(added_device->tags & EVDEV_TAG_TRACKPOINT) &&
|
||||
tp_is_internal && trp_is_internal) {
|
||||
/* Don't send any pending releases to the new trackpoint */
|
||||
tp->buttons.active_is_topbutton = false;
|
||||
tp->buttons.trackpoint = added_device;
|
||||
|
|
@ -831,6 +985,18 @@ tp_device_added(struct evdev_device *device,
|
|||
tp_trackpoint_event, tp);
|
||||
}
|
||||
|
||||
/* FIXME: detect external keyboard better */
|
||||
kbd_is_internal = bus_tp != BUS_BLUETOOTH &&
|
||||
bus_kbd == bus_tp;
|
||||
if (tp_is_internal && kbd_is_internal &&
|
||||
tp->sendevents.keyboard == NULL) {
|
||||
libinput_device_add_event_listener(&added_device->base,
|
||||
&tp->sendevents.keyboard_listener,
|
||||
tp_keyboard_event, tp);
|
||||
tp->sendevents.keyboard = added_device;
|
||||
tp->sendevents.keyboard_active = false;
|
||||
}
|
||||
|
||||
if (tp->sendevents.current_mode !=
|
||||
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
|
||||
return;
|
||||
|
|
@ -840,8 +1006,8 @@ tp_device_added(struct evdev_device *device,
|
|||
}
|
||||
|
||||
static void
|
||||
tp_device_removed(struct evdev_device *device,
|
||||
struct evdev_device *removed_device)
|
||||
tp_interface_device_removed(struct evdev_device *device,
|
||||
struct evdev_device *removed_device)
|
||||
{
|
||||
struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
|
||||
struct libinput_device *dev;
|
||||
|
|
@ -857,6 +1023,12 @@ tp_device_removed(struct evdev_device *device,
|
|||
tp->buttons.trackpoint = NULL;
|
||||
}
|
||||
|
||||
if (removed_device == tp->sendevents.keyboard) {
|
||||
libinput_device_remove_event_listener(
|
||||
&tp->sendevents.keyboard_listener);
|
||||
tp->sendevents.keyboard = NULL;
|
||||
}
|
||||
|
||||
if (tp->sendevents.current_mode !=
|
||||
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
|
||||
return;
|
||||
|
|
@ -873,8 +1045,8 @@ tp_device_removed(struct evdev_device *device,
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tag_device(struct evdev_device *device,
|
||||
struct udev_device *udev_device)
|
||||
tp_interface_tag_device(struct evdev_device *device,
|
||||
struct udev_device *udev_device)
|
||||
{
|
||||
int bustype;
|
||||
|
||||
|
|
@ -896,15 +1068,16 @@ tp_tag_device(struct evdev_device *device,
|
|||
}
|
||||
|
||||
static struct evdev_dispatch_interface tp_interface = {
|
||||
tp_process,
|
||||
tp_remove,
|
||||
tp_destroy,
|
||||
tp_device_added,
|
||||
tp_device_removed,
|
||||
tp_device_removed, /* device_suspended, treat as remove */
|
||||
tp_device_added, /* device_resumed, treat as add */
|
||||
tp_tag_device,
|
||||
NULL, /* post_added */
|
||||
tp_interface_process,
|
||||
tp_interface_suspend,
|
||||
tp_interface_remove,
|
||||
tp_interface_destroy,
|
||||
tp_interface_device_added,
|
||||
tp_interface_device_removed,
|
||||
tp_interface_device_removed, /* device_suspended, treat as remove */
|
||||
tp_interface_device_added, /* device_resumed, treat as add */
|
||||
tp_interface_tag_device,
|
||||
NULL, /* post_added */
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -915,6 +1088,28 @@ tp_init_touch(struct tp_dispatch *tp,
|
|||
t->has_ended = true;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_sync_touch(struct tp_dispatch *tp,
|
||||
struct evdev_device *device,
|
||||
struct tp_touch *t,
|
||||
int slot)
|
||||
{
|
||||
struct libevdev *evdev = device->evdev;
|
||||
|
||||
if (!libevdev_fetch_slot_value(evdev,
|
||||
slot,
|
||||
ABS_MT_POSITION_X,
|
||||
&t->point.x))
|
||||
t->point.x = libevdev_get_event_value(evdev, EV_ABS, ABS_X);
|
||||
if (!libevdev_fetch_slot_value(evdev,
|
||||
slot,
|
||||
ABS_MT_POSITION_Y,
|
||||
&t->point.y))
|
||||
t->point.y = libevdev_get_event_value(evdev, EV_ABS, ABS_Y);
|
||||
|
||||
libevdev_fetch_slot_value(evdev, slot, ABS_MT_DISTANCE, &t->distance);
|
||||
}
|
||||
|
||||
static int
|
||||
tp_init_slots(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
|
|
@ -934,11 +1129,11 @@ tp_init_slots(struct tp_dispatch *tp,
|
|||
|
||||
absinfo = libevdev_get_abs_info(device->evdev, ABS_MT_SLOT);
|
||||
if (absinfo) {
|
||||
tp->real_touches = absinfo->maximum + 1;
|
||||
tp->num_slots = absinfo->maximum + 1;
|
||||
tp->slot = absinfo->value;
|
||||
tp->has_mt = true;
|
||||
} else {
|
||||
tp->real_touches = 1;
|
||||
tp->num_slots = 1;
|
||||
tp->slot = 0;
|
||||
tp->has_mt = false;
|
||||
}
|
||||
|
|
@ -954,7 +1149,7 @@ tp_init_slots(struct tp_dispatch *tp,
|
|||
}
|
||||
}
|
||||
|
||||
tp->ntouches = max(tp->real_touches, n_btn_tool_touches);
|
||||
tp->ntouches = max(tp->num_slots, n_btn_tool_touches);
|
||||
tp->touches = calloc(tp->ntouches, sizeof(struct tp_touch));
|
||||
if (!tp->touches)
|
||||
return -1;
|
||||
|
|
@ -962,6 +1157,12 @@ tp_init_slots(struct tp_dispatch *tp,
|
|||
for (i = 0; i < tp->ntouches; i++)
|
||||
tp_init_touch(tp, &tp->touches[i]);
|
||||
|
||||
/* Always sync the first touch so we get ABS_X/Y synced on
|
||||
* single-touch touchpads */
|
||||
tp_sync_touch(tp, device, &tp->touches[0], 0);
|
||||
for (i = 1; i < tp->num_slots; i++)
|
||||
tp_sync_touch(tp, device, &tp->touches[i], i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -969,6 +1170,7 @@ static int
|
|||
tp_init_accel(struct tp_dispatch *tp, double diagonal)
|
||||
{
|
||||
int res_x, res_y;
|
||||
accel_profile_func_t profile;
|
||||
|
||||
res_x = tp->device->abs.absinfo_x->resolution;
|
||||
res_y = tp->device->abs.absinfo_y->resolution;
|
||||
|
|
@ -992,9 +1194,16 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal)
|
|||
tp->accel.y_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
|
||||
}
|
||||
|
||||
if (evdev_device_init_pointer_acceleration(
|
||||
tp->device,
|
||||
touchpad_accel_profile_linear) == -1)
|
||||
switch (tp->device->model) {
|
||||
case EVDEV_MODEL_LENOVO_X230:
|
||||
profile = touchpad_lenovo_x230_accel_profile;
|
||||
break;
|
||||
default:
|
||||
profile = touchpad_accel_profile_linear;
|
||||
break;
|
||||
}
|
||||
|
||||
if (evdev_device_init_pointer_acceleration(tp->device, profile) == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
|
@ -1087,13 +1296,16 @@ static int
|
|||
tp_init_palmdetect(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
int width;
|
||||
int width, height;
|
||||
|
||||
tp->palm.right_edge = INT_MAX;
|
||||
tp->palm.left_edge = INT_MIN;
|
||||
tp->palm.vert_center = INT_MIN;
|
||||
|
||||
width = abs(device->abs.absinfo_x->maximum -
|
||||
device->abs.absinfo_x->minimum);
|
||||
height = abs(device->abs.absinfo_y->maximum -
|
||||
device->abs.absinfo_y->minimum);
|
||||
|
||||
/* Apple touchpads are always big enough to warrant palm detection */
|
||||
if (evdev_device_get_id_vendor(device) != VENDOR_ID_APPLE) {
|
||||
|
|
@ -1101,15 +1313,16 @@ tp_init_palmdetect(struct tp_dispatch *tp,
|
|||
if (device->abs.absinfo_x->resolution == 1)
|
||||
return 0;
|
||||
|
||||
/* Enable palm detection on touchpads >= 80 mm. Anything smaller
|
||||
/* 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 < 80)
|
||||
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;
|
||||
tp->palm.left_edge = device->abs.absinfo_x->minimum + width * 0.05;
|
||||
tp->palm.vert_center = device->abs.absinfo_y->minimum + height/2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1121,6 +1334,10 @@ tp_init_sendevents(struct tp_dispatch *tp,
|
|||
libinput_timer_init(&tp->sendevents.trackpoint_timer,
|
||||
tp->device->base.seat->libinput,
|
||||
tp_trackpoint_timeout, tp);
|
||||
|
||||
libinput_timer_init(&tp->sendevents.keyboard_timer,
|
||||
tp->device->base.seat->libinput,
|
||||
tp_keyboard_timeout, tp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1143,6 +1360,10 @@ tp_init(struct tp_dispatch *tp,
|
|||
device->abs.absinfo_y->minimum);
|
||||
diagonal = sqrt(width*width + height*height);
|
||||
|
||||
tp->reports_distance = libevdev_has_event_code(device->evdev,
|
||||
EV_ABS,
|
||||
ABS_MT_DISTANCE);
|
||||
|
||||
tp->hysteresis_margin.x =
|
||||
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
|
||||
tp->hysteresis_margin.y =
|
||||
|
|
@ -1313,7 +1534,7 @@ evdev_mt_touchpad_create(struct evdev_device *device)
|
|||
tp->model = tp_get_model(device);
|
||||
|
||||
if (tp_init(tp, device) != 0) {
|
||||
tp_destroy(&tp->base);
|
||||
tp_interface_destroy(&tp->base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,12 @@ enum touch_state {
|
|||
TOUCH_END
|
||||
};
|
||||
|
||||
enum touch_palm_state {
|
||||
PALM_NONE = 0,
|
||||
PALM_EDGE,
|
||||
PALM_TYPING,
|
||||
};
|
||||
|
||||
enum button_event {
|
||||
BUTTON_EVENT_IN_BOTTOM_R = 30,
|
||||
BUTTON_EVENT_IN_BOTTOM_L,
|
||||
|
|
@ -94,9 +100,12 @@ enum tp_tap_state {
|
|||
TAP_STATE_TOUCH_3,
|
||||
TAP_STATE_TOUCH_3_HOLD,
|
||||
TAP_STATE_DRAGGING_OR_DOUBLETAP,
|
||||
TAP_STATE_DRAGGING_OR_TAP,
|
||||
TAP_STATE_DRAGGING,
|
||||
TAP_STATE_DRAGGING_WAIT,
|
||||
TAP_STATE_DRAGGING_2,
|
||||
TAP_STATE_MULTITAP,
|
||||
TAP_STATE_MULTITAP_DOWN,
|
||||
TAP_STATE_DEAD, /**< finger count exceeded */
|
||||
};
|
||||
|
||||
|
|
@ -127,6 +136,7 @@ struct tp_touch {
|
|||
bool dirty;
|
||||
struct device_coords point;
|
||||
uint64_t millis;
|
||||
int distance; /* distance == 0 means touch */
|
||||
|
||||
struct {
|
||||
struct device_coords samples[TOUCHPAD_HISTORY_LENGTH];
|
||||
|
|
@ -167,7 +177,7 @@ struct tp_touch {
|
|||
} scroll;
|
||||
|
||||
struct {
|
||||
bool is_palm;
|
||||
enum touch_palm_state state;
|
||||
struct device_coords first; /* first coordinates if is_palm == true */
|
||||
uint32_t time; /* first timestamp if is_palm == true */
|
||||
} palm;
|
||||
|
|
@ -181,9 +191,10 @@ struct tp_dispatch {
|
|||
unsigned int slot; /* current slot */
|
||||
bool has_mt;
|
||||
bool semi_mt;
|
||||
bool reports_distance; /* does the device support true hovering */
|
||||
enum touchpad_model model;
|
||||
|
||||
unsigned int real_touches; /* number of slots */
|
||||
unsigned int num_slots; /* number of slots */
|
||||
unsigned int ntouches; /* no slots inc. fakes */
|
||||
struct tp_touch *touches; /* len == ntouches */
|
||||
/* bit 0: BTN_TOUCH
|
||||
|
|
@ -255,41 +266,50 @@ struct tp_dispatch {
|
|||
struct libinput_timer timer;
|
||||
enum tp_tap_state state;
|
||||
uint32_t buttons_pressed;
|
||||
uint64_t multitap_last_time;
|
||||
} tap;
|
||||
|
||||
struct {
|
||||
int32_t right_edge; /* in device coordinates */
|
||||
int32_t left_edge; /* in device coordinates */
|
||||
int32_t vert_center; /* in device coordinates */
|
||||
} palm;
|
||||
|
||||
struct {
|
||||
struct libinput_device_config_send_events config;
|
||||
enum libinput_config_send_events_mode current_mode;
|
||||
|
||||
bool trackpoint_active;
|
||||
struct libinput_event_listener trackpoint_listener;
|
||||
struct libinput_timer trackpoint_timer;
|
||||
|
||||
bool keyboard_active;
|
||||
struct libinput_event_listener keyboard_listener;
|
||||
struct libinput_timer keyboard_timer;
|
||||
struct evdev_device *keyboard;
|
||||
} sendevents;
|
||||
};
|
||||
|
||||
#define tp_for_each_touch(_tp, _t) \
|
||||
for (unsigned int _i = 0; _i < (_tp)->ntouches && (_t = &(_tp)->touches[_i]); _i++)
|
||||
|
||||
static inline void
|
||||
tp_normalize_delta(struct tp_dispatch *tp,
|
||||
double dx, double dy,
|
||||
struct normalized_coords *normalized)
|
||||
static inline struct normalized_coords
|
||||
tp_normalize_delta(struct tp_dispatch *tp, struct device_float_coords delta)
|
||||
{
|
||||
normalized->x = dx * tp->accel.x_scale_coeff;
|
||||
normalized->y = dy * tp->accel.y_scale_coeff;
|
||||
struct normalized_coords normalized;
|
||||
|
||||
normalized.x = delta.x * tp->accel.x_scale_coeff;
|
||||
normalized.y = delta.y * tp->accel.y_scale_coeff;
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
struct normalized_coords
|
||||
tp_get_delta(struct tp_touch *t);
|
||||
|
||||
void
|
||||
struct normalized_coords
|
||||
tp_filter_motion(struct tp_dispatch *tp,
|
||||
double *dx, double *dy,
|
||||
double *dx_unaccel, double *dy_unaccel,
|
||||
const struct normalized_coords *unaccelerated,
|
||||
uint64_t time);
|
||||
|
||||
int
|
||||
|
|
@ -385,4 +405,7 @@ tp_gesture_post_events(struct tp_dispatch *tp, uint64_t time);
|
|||
void
|
||||
tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time);
|
||||
|
||||
bool
|
||||
tp_palm_tap_is_palm(struct tp_dispatch *tp, struct tp_touch *t);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1022,6 +1022,7 @@ tablet_check_initial_proximity(struct evdev_device *device,
|
|||
|
||||
static struct evdev_dispatch_interface tablet_interface = {
|
||||
tablet_process,
|
||||
NULL, /* suspend */
|
||||
NULL, /* remove */
|
||||
tablet_destroy,
|
||||
NULL, /* device_added */
|
||||
|
|
|
|||
402
src/evdev.c
402
src/evdev.c
|
|
@ -137,6 +137,21 @@ evdev_keyboard_notify_key(struct evdev_device *device,
|
|||
keyboard_notify_key(&device->base, time, key, state);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_pointer_notify_physical_button(struct evdev_device *device,
|
||||
uint32_t time,
|
||||
int button,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
if (evdev_middlebutton_filter_button(device,
|
||||
time,
|
||||
button,
|
||||
state))
|
||||
return;
|
||||
|
||||
evdev_pointer_notify_button(device, time, button, state);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_pointer_notify_button(struct evdev_device *device,
|
||||
uint32_t time,
|
||||
|
|
@ -151,13 +166,13 @@ evdev_pointer_notify_button(struct evdev_device *device,
|
|||
(state == LIBINPUT_BUTTON_STATE_RELEASED && down_count == 0)) {
|
||||
pointer_notify_button(&device->base, time, button, state);
|
||||
|
||||
if (state == LIBINPUT_BUTTON_STATE_RELEASED &&
|
||||
device->left_handed.change_to_enabled)
|
||||
device->left_handed.change_to_enabled(device);
|
||||
if (state == LIBINPUT_BUTTON_STATE_RELEASED) {
|
||||
if (device->left_handed.change_to_enabled)
|
||||
device->left_handed.change_to_enabled(device);
|
||||
|
||||
if (state == LIBINPUT_BUTTON_STATE_RELEASED &&
|
||||
device->scroll.change_scroll_method)
|
||||
device->scroll.change_scroll_method(device);
|
||||
if (device->scroll.change_scroll_method)
|
||||
device->scroll.change_scroll_method(device);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -230,8 +245,8 @@ normalize_delta(struct evdev_device *device,
|
|||
const struct device_coords *delta,
|
||||
struct normalized_coords *normalized)
|
||||
{
|
||||
normalized->x = delta->x * (double)device->dpi / DEFAULT_MOUSE_DPI;
|
||||
normalized->y = delta->y * (double)device->dpi / DEFAULT_MOUSE_DPI;
|
||||
normalized->x = delta->x * DEFAULT_MOUSE_DPI / (double)device->dpi;
|
||||
normalized->y = delta->y * DEFAULT_MOUSE_DPI / (double)device->dpi;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -266,12 +281,13 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
|||
}
|
||||
|
||||
/* Apply pointer acceleration. */
|
||||
accel = filter_dispatch(device->pointer.filter, &unaccel, device, time);
|
||||
accel = filter_dispatch(device->pointer.filter,
|
||||
&unaccel,
|
||||
device,
|
||||
time);
|
||||
|
||||
if (accel.x == 0.0 && accel.y == 0.0 &&
|
||||
unaccel.x == 0.0 && unaccel.y == 0.0) {
|
||||
if (normalized_is_zero(accel) && normalized_is_zero(unaccel))
|
||||
break;
|
||||
}
|
||||
|
||||
pointer_notify_motion(base, time, &accel, &unaccel);
|
||||
break;
|
||||
|
|
@ -432,10 +448,10 @@ evdev_button_scroll_button(struct evdev_device *device,
|
|||
} else {
|
||||
/* If the button is released quickly enough emit the
|
||||
* button press/release events. */
|
||||
evdev_pointer_notify_button(device, time,
|
||||
evdev_pointer_notify_physical_button(device, time,
|
||||
device->scroll.button,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
evdev_pointer_notify_button(device, time,
|
||||
evdev_pointer_notify_physical_button(device, time,
|
||||
device->scroll.button,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
|
|
@ -507,7 +523,7 @@ evdev_process_key(struct evdev_device *device,
|
|||
evdev_button_scroll_button(device, time, e->value);
|
||||
break;
|
||||
}
|
||||
evdev_pointer_notify_button(
|
||||
evdev_pointer_notify_physical_button(
|
||||
device,
|
||||
time,
|
||||
evdev_to_left_handed(device, e->code),
|
||||
|
|
@ -744,6 +760,65 @@ fallback_process(struct evdev_dispatch *dispatch,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
release_pressed_keys(struct evdev_device *device)
|
||||
{
|
||||
struct libinput *libinput = device->base.seat->libinput;
|
||||
uint64_t time;
|
||||
int code;
|
||||
|
||||
if ((time = libinput_now(libinput)) == 0)
|
||||
return;
|
||||
|
||||
for (code = 0; code < KEY_CNT; code++) {
|
||||
int count = get_key_down_count(device, code);
|
||||
|
||||
if (count == 0)
|
||||
continue;
|
||||
|
||||
if (count > 1) {
|
||||
log_bug_libinput(libinput,
|
||||
"Key %d is down %d times.\n",
|
||||
code,
|
||||
count);
|
||||
}
|
||||
|
||||
switch (get_key_type(code)) {
|
||||
case EVDEV_KEY_TYPE_NONE:
|
||||
break;
|
||||
case EVDEV_KEY_TYPE_KEY:
|
||||
evdev_keyboard_notify_key(
|
||||
device,
|
||||
time,
|
||||
code,
|
||||
LIBINPUT_KEY_STATE_RELEASED);
|
||||
break;
|
||||
case EVDEV_KEY_TYPE_BUTTON:
|
||||
evdev_pointer_notify_physical_button(
|
||||
device,
|
||||
time,
|
||||
evdev_to_left_handed(device, code),
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
}
|
||||
|
||||
count = get_key_down_count(device, code);
|
||||
if (count != 0) {
|
||||
log_bug_libinput(libinput,
|
||||
"Releasing key %d failed.\n",
|
||||
code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_suspend(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
release_pressed_keys(device);
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_destroy(struct evdev_dispatch *dispatch)
|
||||
{
|
||||
|
|
@ -801,6 +876,7 @@ evdev_calibration_get_default_matrix(struct libinput_device *libinput_device,
|
|||
|
||||
struct evdev_dispatch_interface fallback_interface = {
|
||||
fallback_process,
|
||||
fallback_suspend,
|
||||
NULL, /* remove */
|
||||
fallback_destroy,
|
||||
NULL, /* device_added */
|
||||
|
|
@ -971,8 +1047,15 @@ evdev_scroll_get_default_method(struct libinput_device *device)
|
|||
|
||||
if (libevdev_has_property(evdev->evdev, INPUT_PROP_POINTING_STICK))
|
||||
return LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
|
||||
else
|
||||
return LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
|
||||
|
||||
/* Mice without a scroll wheel but with middle button have on-button
|
||||
* scrolling by default */
|
||||
if (!libevdev_has_event_code(evdev->evdev, EV_REL, REL_WHEEL) &&
|
||||
!libevdev_has_event_code(evdev->evdev, EV_REL, REL_HWHEEL) &&
|
||||
libevdev_has_event_code(evdev->evdev, EV_KEY, BTN_MIDDLE))
|
||||
return LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
|
||||
|
||||
return LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
|
||||
}
|
||||
|
||||
static enum libinput_config_status
|
||||
|
|
@ -1004,8 +1087,15 @@ evdev_scroll_get_default_button(struct libinput_device *device)
|
|||
|
||||
if (libevdev_has_property(evdev->evdev, INPUT_PROP_POINTING_STICK))
|
||||
return BTN_MIDDLE;
|
||||
else
|
||||
return 0;
|
||||
|
||||
/* A device that defaults to button scrolling defaults
|
||||
to BTN_MIDDLE */
|
||||
if (evdev_scroll_get_default_method(device) ==
|
||||
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN &&
|
||||
libevdev_has_event_code(evdev->evdev, EV_KEY, BTN_MIDDLE))
|
||||
return BTN_MIDDLE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -1131,6 +1221,24 @@ fallback_dispatch_create(struct libinput_device *device)
|
|||
evdev_init_calibration(evdev_device, dispatch);
|
||||
evdev_init_sendevents(evdev_device, dispatch);
|
||||
|
||||
/* BTN_MIDDLE is set on mice even when it's not present. So
|
||||
* we can only use the absense of BTN_MIDDLE to mean something, i.e.
|
||||
* we enable it by default on anything that only has L&R.
|
||||
* If we have L&R and no middle, we don't expose it as config
|
||||
* option */
|
||||
if (libevdev_has_event_code(evdev_device->evdev, EV_KEY, BTN_LEFT) &&
|
||||
libevdev_has_event_code(evdev_device->evdev, EV_KEY, BTN_RIGHT)) {
|
||||
bool has_middle = libevdev_has_event_code(evdev_device->evdev,
|
||||
EV_KEY,
|
||||
BTN_MIDDLE);
|
||||
bool want_config = has_middle;
|
||||
bool enable_by_default = !has_middle;
|
||||
|
||||
evdev_init_middlebutton(evdev_device,
|
||||
enable_by_default,
|
||||
want_config);
|
||||
}
|
||||
|
||||
return dispatch;
|
||||
}
|
||||
|
||||
|
|
@ -1140,6 +1248,19 @@ evdev_process_event(struct evdev_device *device, struct input_event *e)
|
|||
struct evdev_dispatch *dispatch = device->dispatch;
|
||||
uint64_t time = e->time.tv_sec * 1000ULL + e->time.tv_usec / 1000;
|
||||
|
||||
#if 0
|
||||
if (libevdev_event_is_code(e, EV_SYN, SYN_REPORT))
|
||||
log_debug(device->base.seat->libinput,
|
||||
"-------------- EV_SYN ------------\n");
|
||||
else
|
||||
log_debug(device->base.seat->libinput,
|
||||
"%-7s %-16s %-20s %4d\n",
|
||||
evdev_device_get_sysname(device),
|
||||
libevdev_event_type_get_name(e->type),
|
||||
libevdev_event_code_get_name(e->type, e->code),
|
||||
e->value);
|
||||
#endif
|
||||
|
||||
dispatch->interface->process(dispatch, device, e, time);
|
||||
}
|
||||
|
||||
|
|
@ -1322,6 +1443,31 @@ evdev_read_wheel_click_prop(struct evdev_device *device)
|
|||
|
||||
return angle;
|
||||
}
|
||||
|
||||
static inline int
|
||||
evdev_get_trackpoint_dpi(struct evdev_device *device)
|
||||
{
|
||||
struct libinput *libinput = device->base.seat->libinput;
|
||||
const char *trackpoint_accel;
|
||||
double accel = DEFAULT_TRACKPOINT_ACCEL;
|
||||
|
||||
trackpoint_accel = udev_device_get_property_value(
|
||||
device->udev_device, "POINTINGSTICK_CONST_ACCEL");
|
||||
if (trackpoint_accel) {
|
||||
accel = parse_trackpoint_accel_property(trackpoint_accel);
|
||||
if (accel == 0.0) {
|
||||
log_error(libinput, "Trackpoint accel property for "
|
||||
"'%s' is present but invalid, "
|
||||
"using %.2f instead\n",
|
||||
device->devname,
|
||||
DEFAULT_TRACKPOINT_ACCEL);
|
||||
accel = DEFAULT_TRACKPOINT_ACCEL;
|
||||
}
|
||||
}
|
||||
|
||||
return DEFAULT_MOUSE_DPI / accel;
|
||||
}
|
||||
|
||||
static inline int
|
||||
evdev_read_dpi_prop(struct evdev_device *device)
|
||||
{
|
||||
|
|
@ -1329,6 +1475,14 @@ evdev_read_dpi_prop(struct evdev_device *device)
|
|||
const char *mouse_dpi;
|
||||
int dpi = DEFAULT_MOUSE_DPI;
|
||||
|
||||
/*
|
||||
* Trackpoints do not have dpi, instead hwdb may contain a
|
||||
* POINTINGSTICK_CONST_ACCEL value to compensate for sensitivity
|
||||
* differences between models, we translate this to a fake dpi.
|
||||
*/
|
||||
if (libevdev_has_property(device->evdev, INPUT_PROP_POINTING_STICK))
|
||||
return evdev_get_trackpoint_dpi(device);
|
||||
|
||||
mouse_dpi = udev_device_get_property_value(device->udev_device,
|
||||
"MOUSE_DPI");
|
||||
if (mouse_dpi) {
|
||||
|
|
@ -1346,6 +1500,33 @@ evdev_read_dpi_prop(struct evdev_device *device)
|
|||
return dpi;
|
||||
}
|
||||
|
||||
static inline enum evdev_device_model
|
||||
evdev_read_model(struct evdev_device *device)
|
||||
{
|
||||
const struct model_map {
|
||||
const char *property;
|
||||
enum evdev_device_model model;
|
||||
} model_map[] = {
|
||||
{ "LIBINPUT_MODEL_LENOVO_X230", EVDEV_MODEL_LENOVO_X230 },
|
||||
{ "LIBINPUT_MODEL_CHROMEBOOK", EVDEV_MODEL_CHROMEBOOK },
|
||||
{ "LIBINPUT_MODEL_SYSTEM76_BONOBO", EVDEV_MODEL_SYSTEM76_BONOBO },
|
||||
{ "LIBINPUT_MODEL_SYSTEM76_GALAGO", EVDEV_MODEL_SYSTEM76_GALAGO },
|
||||
{ "LIBINPUT_MODEL_SYSTEM76_KUDU", EVDEV_MODEL_SYSTEM76_KUDU },
|
||||
{ "LIBINPUT_MODEL_CLEVO_W740SU", EVDEV_MODEL_CLEVO_W740SU },
|
||||
{ NULL, EVDEV_MODEL_DEFAULT },
|
||||
};
|
||||
const struct model_map *m = model_map;
|
||||
|
||||
while (m->property) {
|
||||
if (!!udev_device_get_property_value(device->udev_device,
|
||||
m->property))
|
||||
break;
|
||||
m++;
|
||||
}
|
||||
|
||||
return m->model;
|
||||
}
|
||||
|
||||
/* Return 1 if the given resolutions have been set, or 0 otherwise */
|
||||
inline int
|
||||
evdev_fix_abs_resolution(struct evdev_device *device,
|
||||
|
|
@ -1380,13 +1561,6 @@ evdev_fix_abs_resolution(struct evdev_device *device,
|
|||
absx = libevdev_get_abs_info(evdev, xcode);
|
||||
absy = libevdev_get_abs_info(evdev, ycode);
|
||||
|
||||
if ((absx->resolution == 0 && absy->resolution != 0) ||
|
||||
(absx->resolution != 0 && absy->resolution == 0)) {
|
||||
log_bug_kernel(libinput,
|
||||
"Kernel has only x or y resolution, not both.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (absx->resolution == 0 || absx->resolution == EVDEV_FAKE_RESOLUTION) {
|
||||
fixed = *absx;
|
||||
fixed.resolution = xresolution;
|
||||
|
|
@ -1434,6 +1608,18 @@ evdev_device_get_udev_tags(struct evdev_device *device,
|
|||
return tags;
|
||||
}
|
||||
|
||||
/* Fake MT devices have the ABS_MT_SLOT bit set because of
|
||||
the limited ABS_* range - they aren't MT devices, they
|
||||
just have too many ABS_ axes */
|
||||
static inline bool
|
||||
evdev_is_fake_mt_device(struct evdev_device *device)
|
||||
{
|
||||
struct libevdev *evdev = device->evdev;
|
||||
|
||||
return libevdev_has_event_code(evdev, EV_ABS, ABS_MT_SLOT) &&
|
||||
libevdev_get_num_slots(evdev) == -1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
evdev_fix_android_mt(struct evdev_device *device)
|
||||
{
|
||||
|
|
@ -1444,12 +1630,13 @@ evdev_fix_android_mt(struct evdev_device *device)
|
|||
return;
|
||||
|
||||
if (!libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) ||
|
||||
!libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y))
|
||||
!libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y) ||
|
||||
evdev_is_fake_mt_device(device))
|
||||
return;
|
||||
|
||||
libevdev_set_abs_info(evdev, ABS_X,
|
||||
libevdev_enable_event_code(evdev, EV_ABS, ABS_X,
|
||||
libevdev_get_abs_info(evdev, ABS_MT_POSITION_X));
|
||||
libevdev_set_abs_info(evdev, ABS_Y,
|
||||
libevdev_enable_event_code(evdev, EV_ABS, ABS_Y,
|
||||
libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y));
|
||||
}
|
||||
|
||||
|
|
@ -1464,11 +1651,27 @@ evdev_check_min_max(struct evdev_device *device, unsigned int code)
|
|||
|
||||
absinfo = libevdev_get_abs_info(evdev, code);
|
||||
if (absinfo->minimum == absinfo->maximum) {
|
||||
log_bug_kernel(device->base.seat->libinput,
|
||||
"Device '%s' has min == max on %s\n",
|
||||
device->devname,
|
||||
libevdev_event_code_get_name(EV_ABS, code));
|
||||
return -1;
|
||||
/* Some devices have a sort-of legitimate min/max of 0 for
|
||||
* ABS_MISC and above (e.g. Roccat Kone XTD). Don't ignore
|
||||
* them, simply disable the axes so we won't get events,
|
||||
* we don't know what to do with them anyway.
|
||||
*/
|
||||
if (absinfo->minimum == 0 &&
|
||||
code >= ABS_MISC && code < ABS_MT_SLOT) {
|
||||
log_info(device->base.seat->libinput,
|
||||
"Disabling EV_ABS %#x on device '%s' (min == max == 0)\n",
|
||||
code,
|
||||
device->devname);
|
||||
libevdev_disable_event_code(device->evdev,
|
||||
EV_ABS,
|
||||
code);
|
||||
} else {
|
||||
log_bug_kernel(device->base.seat->libinput,
|
||||
"Device '%s' has min == max on %s\n",
|
||||
device->devname,
|
||||
libevdev_event_code_get_name(EV_ABS, code));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1477,17 +1680,46 @@ evdev_check_min_max(struct evdev_device *device, unsigned int code)
|
|||
static int
|
||||
evdev_reject_device(struct evdev_device *device)
|
||||
{
|
||||
struct libinput *libinput = device->base.seat->libinput;
|
||||
struct libevdev *evdev = device->evdev;
|
||||
unsigned int code;
|
||||
const struct input_absinfo *absx, *absy;
|
||||
|
||||
if (libevdev_has_event_code(evdev, EV_ABS, ABS_X) ^
|
||||
libevdev_has_event_code(evdev, EV_ABS, ABS_Y))
|
||||
return -1;
|
||||
|
||||
if (libevdev_has_event_code(evdev, EV_REL, REL_X) ^
|
||||
libevdev_has_event_code(evdev, EV_REL, REL_Y))
|
||||
return -1;
|
||||
|
||||
if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) ^
|
||||
libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y))
|
||||
return -1;
|
||||
|
||||
if (libevdev_has_event_code(evdev, EV_ABS, ABS_X)) {
|
||||
absx = libevdev_get_abs_info(evdev, ABS_X);
|
||||
absy = libevdev_get_abs_info(evdev, ABS_Y);
|
||||
if ((absx->resolution == 0 && absy->resolution != 0) ||
|
||||
(absx->resolution != 0 && absy->resolution == 0)) {
|
||||
log_bug_kernel(libinput,
|
||||
"Kernel has only x or y resolution, not both.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!evdev_is_fake_mt_device(device) &&
|
||||
libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X)) {
|
||||
absx = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X);
|
||||
absy = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y);
|
||||
if ((absx->resolution == 0 && absy->resolution != 0) ||
|
||||
(absx->resolution != 0 && absy->resolution == 0)) {
|
||||
log_bug_kernel(libinput,
|
||||
"Kernel has only x or y MT resolution, not both.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (code = 0; code < ABS_CNT; code++) {
|
||||
switch (code) {
|
||||
case ABS_MISC:
|
||||
|
|
@ -1550,8 +1782,16 @@ evdev_configure_mt_device(struct evdev_device *device)
|
|||
|
||||
for (slot = 0; slot < num_slots; ++slot) {
|
||||
slots[slot].seat_slot = -1;
|
||||
slots[slot].point.x = 0;
|
||||
slots[slot].point.y = 0;
|
||||
|
||||
if (evdev_need_mtdev(device))
|
||||
continue;
|
||||
|
||||
slots[slot].point.x = libevdev_get_slot_value(evdev,
|
||||
slot,
|
||||
ABS_MT_POSITION_X);
|
||||
slots[slot].point.y = libevdev_get_slot_value(evdev,
|
||||
slot,
|
||||
ABS_MT_POSITION_Y);
|
||||
}
|
||||
device->mt.slots = slots;
|
||||
device->mt.slots_len = num_slots;
|
||||
|
|
@ -1615,10 +1855,10 @@ evdev_configure_device(struct evdev_device *device)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (libevdev_has_event_code(evdev, EV_ABS, ABS_X) ||
|
||||
libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X)) {
|
||||
if (!evdev_is_fake_mt_device(device))
|
||||
evdev_fix_android_mt(device);
|
||||
|
||||
if (libevdev_has_event_code(evdev, EV_ABS, ABS_X)) {
|
||||
if (evdev_fix_abs_resolution(device,
|
||||
ABS_X,
|
||||
ABS_Y,
|
||||
|
|
@ -1627,12 +1867,10 @@ evdev_configure_device(struct evdev_device *device)
|
|||
device->abs.fake_resolution = 1;
|
||||
device->abs.absinfo_x = libevdev_get_abs_info(evdev, ABS_X);
|
||||
device->abs.absinfo_y = libevdev_get_abs_info(evdev, ABS_Y);
|
||||
device->abs.point.x = device->abs.absinfo_x->value;
|
||||
device->abs.point.y = device->abs.absinfo_y->value;
|
||||
|
||||
/* Fake MT devices have the ABS_MT_SLOT bit set because of
|
||||
the limited ABS_* range - they aren't MT devices, they
|
||||
just have too many ABS_ axes */
|
||||
if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_SLOT) &&
|
||||
libevdev_get_num_slots(evdev) == -1) {
|
||||
if (evdev_is_fake_mt_device(device)) {
|
||||
udev_tags &= ~EVDEV_UDEV_TAG_TOUCHSCREEN;
|
||||
} else if (evdev_configure_mt_device(device) == -1) {
|
||||
return -1;
|
||||
|
|
@ -1663,8 +1901,8 @@ evdev_configure_device(struct evdev_device *device)
|
|||
}
|
||||
|
||||
if (udev_tags & EVDEV_UDEV_TAG_MOUSE) {
|
||||
if (!libevdev_has_event_code(evdev, EV_ABS, ABS_X) &&
|
||||
!libevdev_has_event_code(evdev, EV_ABS, ABS_Y) &&
|
||||
if (libevdev_has_event_code(evdev, EV_REL, REL_X) &&
|
||||
libevdev_has_event_code(evdev, EV_REL, REL_Y) &&
|
||||
evdev_device_init_pointer_acceleration(
|
||||
device,
|
||||
pointer_accel_profile_linear) == -1)
|
||||
|
|
@ -1689,6 +1927,13 @@ evdev_configure_device(struct evdev_device *device)
|
|||
log_info(libinput,
|
||||
"input device '%s', %s is a keyboard\n",
|
||||
device->devname, devnode);
|
||||
|
||||
/* want natural-scroll config option */
|
||||
if (libevdev_has_event_code(evdev, EV_REL, REL_WHEEL) ||
|
||||
libevdev_has_event_code(evdev, EV_REL, REL_HWHEEL)) {
|
||||
device->scroll.natural_scrolling_enabled = true;
|
||||
device->seat_caps |= EVDEV_DEVICE_POINTER;
|
||||
}
|
||||
}
|
||||
|
||||
if (udev_tags & EVDEV_UDEV_TAG_TOUCHSCREEN) {
|
||||
|
|
@ -1804,7 +2049,8 @@ evdev_device_create(struct libinput_seat *seat,
|
|||
/* Use non-blocking mode so that we can loop on read on
|
||||
* evdev_device_data() until all events on the fd are
|
||||
* read. mtdev_get() also expects this. */
|
||||
fd = open_restricted(libinput, devnode, O_RDWR | O_NONBLOCK);
|
||||
fd = open_restricted(libinput, devnode,
|
||||
O_RDWR | O_NONBLOCK | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
log_info(libinput,
|
||||
"opening input device '%s' failed (%s).\n",
|
||||
|
|
@ -1844,6 +2090,7 @@ evdev_device_create(struct libinput_seat *seat,
|
|||
device->scroll.wheel_click_angle =
|
||||
evdev_read_wheel_click_prop(device);
|
||||
device->dpi = evdev_read_dpi_prop(device);
|
||||
device->model = evdev_read_model(device);
|
||||
/* at most 5 SYN_DROPPED log-messages per 30s */
|
||||
ratelimit_init(&device->syn_drop_limit, 30ULL * 1000, 5);
|
||||
|
||||
|
|
@ -2044,6 +2291,15 @@ evdev_device_has_button(struct evdev_device *device, uint32_t code)
|
|||
return libevdev_has_event_code(device->evdev, EV_KEY, code);
|
||||
}
|
||||
|
||||
int
|
||||
evdev_device_has_key(struct evdev_device *device, uint32_t code)
|
||||
{
|
||||
if (!(device->seat_caps & EVDEV_DEVICE_KEYBOARD))
|
||||
return -1;
|
||||
|
||||
return libevdev_has_event_code(device->evdev, EV_KEY, code);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
evdev_is_scrolling(const struct evdev_device *device,
|
||||
enum libinput_pointer_axis axis)
|
||||
|
|
@ -2121,7 +2377,7 @@ evdev_post_scroll(struct evdev_device *device,
|
|||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
|
||||
event.x = 0.0;
|
||||
|
||||
if (event.x != 0.0 || event.y != 0.0) {
|
||||
if (!normalized_is_zero(event)) {
|
||||
const struct discrete_coords zero_discrete = { 0.0, 0.0 };
|
||||
evdev_notify_axis(device,
|
||||
time,
|
||||
|
|
@ -2154,49 +2410,6 @@ evdev_stop_scroll(struct evdev_device *device,
|
|||
device->scroll.direction = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
release_pressed_keys(struct evdev_device *device)
|
||||
{
|
||||
struct libinput *libinput = device->base.seat->libinput;
|
||||
uint64_t time;
|
||||
int code;
|
||||
|
||||
if ((time = libinput_now(libinput)) == 0)
|
||||
return;
|
||||
|
||||
for (code = 0; code < KEY_CNT; code++) {
|
||||
int count = get_key_down_count(device, code);
|
||||
|
||||
if (count > 1) {
|
||||
log_bug_libinput(libinput,
|
||||
"Key %d is down %d times.\n",
|
||||
code,
|
||||
count);
|
||||
}
|
||||
|
||||
while (get_key_down_count(device, code) > 0) {
|
||||
switch (get_key_type(code)) {
|
||||
case EVDEV_KEY_TYPE_NONE:
|
||||
break;
|
||||
case EVDEV_KEY_TYPE_KEY:
|
||||
evdev_keyboard_notify_key(
|
||||
device,
|
||||
time,
|
||||
code,
|
||||
LIBINPUT_KEY_STATE_RELEASED);
|
||||
break;
|
||||
case EVDEV_KEY_TYPE_BUTTON:
|
||||
evdev_pointer_notify_button(
|
||||
device,
|
||||
time,
|
||||
evdev_to_left_handed(device, code),
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
evdev_notify_suspended_device(struct evdev_device *device)
|
||||
{
|
||||
|
|
@ -2242,14 +2455,16 @@ evdev_device_suspend(struct evdev_device *device)
|
|||
{
|
||||
evdev_notify_suspended_device(device);
|
||||
|
||||
if (device->dispatch->interface->suspend)
|
||||
device->dispatch->interface->suspend(device->dispatch,
|
||||
device);
|
||||
|
||||
if (device->source) {
|
||||
libinput_remove_source(device->base.seat->libinput,
|
||||
device->source);
|
||||
device->source = NULL;
|
||||
}
|
||||
|
||||
release_pressed_keys(device);
|
||||
|
||||
if (device->mtdev) {
|
||||
mtdev_close_delete(device->mtdev);
|
||||
device->mtdev = NULL;
|
||||
|
|
@ -2279,7 +2494,8 @@ evdev_device_resume(struct evdev_device *device)
|
|||
return -ENODEV;
|
||||
|
||||
devnode = udev_device_get_devnode(device->udev_device);
|
||||
fd = open_restricted(libinput, devnode, O_RDWR | O_NONBLOCK);
|
||||
fd = open_restricted(libinput, devnode,
|
||||
O_RDWR | O_NONBLOCK | O_CLOEXEC);
|
||||
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
|
|
|||
77
src/evdev.h
77
src/evdev.h
|
|
@ -36,6 +36,13 @@
|
|||
|
||||
/* The HW DPI rate we normalize to before calculating pointer acceleration */
|
||||
#define DEFAULT_MOUSE_DPI 1000
|
||||
|
||||
/*
|
||||
* The constant (linear) acceleration factor we use to normalize trackpoint
|
||||
* deltas before calculating pointer acceleration.
|
||||
*/
|
||||
#define DEFAULT_TRACKPOINT_ACCEL 1.0
|
||||
|
||||
/* The fake resolution value for abs devices without resolution */
|
||||
#define EVDEV_FAKE_RESOLUTION 1
|
||||
|
||||
|
|
@ -64,6 +71,39 @@ enum evdev_device_tags {
|
|||
EVDEV_TAG_TOUCHPAD_TRACKPOINT = (1 << 3),
|
||||
};
|
||||
|
||||
enum evdev_middlebutton_state {
|
||||
MIDDLEBUTTON_IDLE,
|
||||
MIDDLEBUTTON_LEFT_DOWN,
|
||||
MIDDLEBUTTON_RIGHT_DOWN,
|
||||
MIDDLEBUTTON_MIDDLE,
|
||||
MIDDLEBUTTON_LEFT_UP_PENDING,
|
||||
MIDDLEBUTTON_RIGHT_UP_PENDING,
|
||||
MIDDLEBUTTON_IGNORE_LR,
|
||||
MIDDLEBUTTON_IGNORE_L,
|
||||
MIDDLEBUTTON_IGNORE_R,
|
||||
MIDDLEBUTTON_PASSTHROUGH,
|
||||
};
|
||||
|
||||
enum evdev_middlebutton_event {
|
||||
MIDDLEBUTTON_EVENT_L_DOWN,
|
||||
MIDDLEBUTTON_EVENT_R_DOWN,
|
||||
MIDDLEBUTTON_EVENT_OTHER,
|
||||
MIDDLEBUTTON_EVENT_L_UP,
|
||||
MIDDLEBUTTON_EVENT_R_UP,
|
||||
MIDDLEBUTTON_EVENT_TIMEOUT,
|
||||
MIDDLEBUTTON_EVENT_ALL_UP,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
struct mt_slot {
|
||||
int32_t seat_slot;
|
||||
struct device_coords point;
|
||||
|
|
@ -159,8 +199,22 @@ struct evdev_device {
|
|||
void (*change_to_enabled)(struct evdev_device *device);
|
||||
} left_handed;
|
||||
|
||||
struct {
|
||||
struct libinput_device_config_middle_emulation config;
|
||||
/* middle-button emulation enabled */
|
||||
bool enabled;
|
||||
bool enabled_default;
|
||||
bool want_enabled;
|
||||
enum evdev_middlebutton_state state;
|
||||
struct libinput_timer timer;
|
||||
uint32_t button_mask;
|
||||
uint64_t first_event_time;
|
||||
} middlebutton;
|
||||
|
||||
int dpi; /* HW resolution */
|
||||
struct ratelimit syn_drop_limit; /* ratelimit for SYN_DROPPED logging */
|
||||
|
||||
enum evdev_device_model model;
|
||||
};
|
||||
|
||||
#define EVDEV_UNHANDLED_DEVICE ((struct evdev_device *) 1)
|
||||
|
|
@ -174,6 +228,10 @@ struct evdev_dispatch_interface {
|
|||
struct input_event *event,
|
||||
uint64_t time);
|
||||
|
||||
/* Device is being suspended */
|
||||
void (*suspend)(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device);
|
||||
|
||||
/* Device is being removed (may be NULL) */
|
||||
void (*remove)(struct evdev_dispatch *dispatch);
|
||||
|
||||
|
|
@ -283,6 +341,9 @@ evdev_device_get_size(struct evdev_device *device,
|
|||
int
|
||||
evdev_device_has_button(struct evdev_device *device, uint32_t code);
|
||||
|
||||
int
|
||||
evdev_device_has_key(struct evdev_device *device, uint32_t code);
|
||||
|
||||
double
|
||||
evdev_device_transform_x(struct evdev_device *device,
|
||||
double x,
|
||||
|
|
@ -315,6 +376,11 @@ evdev_pointer_notify_button(struct evdev_device *device,
|
|||
uint32_t time,
|
||||
int button,
|
||||
enum libinput_button_state state);
|
||||
void
|
||||
evdev_pointer_notify_physical_button(struct evdev_device *device,
|
||||
uint32_t time,
|
||||
int button,
|
||||
enum libinput_button_state state);
|
||||
|
||||
void
|
||||
evdev_init_natural_scroll(struct evdev_device *device);
|
||||
|
|
@ -336,6 +402,17 @@ evdev_device_remove(struct evdev_device *device);
|
|||
void
|
||||
evdev_device_destroy(struct evdev_device *device);
|
||||
|
||||
bool
|
||||
evdev_middlebutton_filter_button(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
int button,
|
||||
enum libinput_button_state state);
|
||||
|
||||
void
|
||||
evdev_init_middlebutton(struct evdev_device *device,
|
||||
bool enabled,
|
||||
bool want_config);
|
||||
|
||||
static inline double
|
||||
evdev_convert_to_mm(const struct input_absinfo *absinfo, double v)
|
||||
{
|
||||
|
|
|
|||
52
src/filter.c
52
src/filter.c
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2006-2009 Simon Thum
|
||||
* Copyright © 2012 Jonas Ådahl
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
|
|
@ -122,7 +123,7 @@ feed_trackers(struct pointer_accelerator *accel,
|
|||
trackers[current].delta.x = 0.0;
|
||||
trackers[current].delta.y = 0.0;
|
||||
trackers[current].time = time;
|
||||
trackers[current].dir = vector_get_direction(delta->x, delta->y);
|
||||
trackers[current].dir = normalized_get_direction(*delta);
|
||||
}
|
||||
|
||||
static struct pointer_tracker *
|
||||
|
|
@ -137,11 +138,9 @@ tracker_by_offset(struct pointer_accelerator *accel, unsigned int offset)
|
|||
static double
|
||||
calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time)
|
||||
{
|
||||
double distance;
|
||||
double tdelta = time - tracker->time + 1;
|
||||
|
||||
distance = hypot(tracker->delta.x, tracker->delta.y);
|
||||
return distance / tdelta; /* units/ms */
|
||||
return normalized_length(tracker->delta) / tdelta; /* units/ms */
|
||||
}
|
||||
|
||||
static double
|
||||
|
|
@ -260,13 +259,15 @@ accelerator_set_speed(struct motion_filter *filter,
|
|||
assert(speed >= -1.0 && speed <= 1.0);
|
||||
|
||||
/* delay when accel kicks in */
|
||||
accel_filter->threshold = DEFAULT_THRESHOLD - speed/6.0;
|
||||
accel_filter->threshold = DEFAULT_THRESHOLD - speed / 4.0;
|
||||
if (accel_filter->threshold < 0.2)
|
||||
accel_filter->threshold = 0.2;
|
||||
|
||||
/* adjust max accel factor */
|
||||
accel_filter->accel = DEFAULT_ACCELERATION + speed;
|
||||
accel_filter->accel = DEFAULT_ACCELERATION + speed * 1.5;
|
||||
|
||||
/* higher speed -> faster to reach max */
|
||||
accel_filter->incline = DEFAULT_INCLINE + speed/2.0;
|
||||
accel_filter->incline = DEFAULT_INCLINE + speed * 0.75;
|
||||
|
||||
filter->speed = speed;
|
||||
return true;
|
||||
|
|
@ -345,3 +346,40 @@ touchpad_accel_profile_linear(struct motion_filter *filter,
|
|||
|
||||
return speed_out * TP_MAGIC_SLOWDOWN;
|
||||
}
|
||||
|
||||
double
|
||||
touchpad_lenovo_x230_accel_profile(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in,
|
||||
uint64_t time)
|
||||
{
|
||||
/* Keep the magic factor from touchpad_accel_profile_linear. */
|
||||
const double TP_MAGIC_SLOWDOWN = 0.4;
|
||||
|
||||
/* Those touchpads presents an actual lower resolution that what is
|
||||
* advertised. We see some jumps from the cursor due to the big steps
|
||||
* in X and Y when we are receiving data.
|
||||
* Apply a factor to minimize those jumps at low speed, and try
|
||||
* keeping the same feeling as regular touchpads at high speed.
|
||||
* It still feels slower but it is usable at least */
|
||||
const double TP_MAGIC_LOW_RES_FACTOR = 4.0;
|
||||
double speed_out;
|
||||
struct pointer_accelerator *accel_filter =
|
||||
(struct pointer_accelerator *)filter;
|
||||
|
||||
double s1, s2;
|
||||
const double max_accel = accel_filter->accel *
|
||||
TP_MAGIC_LOW_RES_FACTOR; /* unitless factor */
|
||||
const double threshold = accel_filter->threshold /
|
||||
TP_MAGIC_LOW_RES_FACTOR; /* units/ms */
|
||||
const double incline = accel_filter->incline * TP_MAGIC_LOW_RES_FACTOR;
|
||||
|
||||
speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR;
|
||||
|
||||
s1 = min(1, speed_in * 5);
|
||||
s2 = 1 + (speed_in - threshold) * incline;
|
||||
|
||||
speed_out = min(max_accel, s2 > 1 ? s2 : s1);
|
||||
|
||||
return speed_out * TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,4 +67,9 @@ touchpad_accel_profile_linear(struct motion_filter *filter,
|
|||
void *data,
|
||||
double speed_in,
|
||||
uint64_t time);
|
||||
double
|
||||
touchpad_lenovo_x230_accel_profile(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in,
|
||||
uint64_t time);
|
||||
#endif /* FILTER_H */
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#define LIBINPUT_PRIVATE_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "linux/input.h"
|
||||
|
||||
|
|
@ -39,6 +40,14 @@ struct device_coords {
|
|||
int x, y;
|
||||
};
|
||||
|
||||
/*
|
||||
* A coordinate pair in device coordinates, capable of holding non discrete
|
||||
* values, this is necessary e.g. when device coordinates get averaged.
|
||||
*/
|
||||
struct device_float_coords {
|
||||
double x, y;
|
||||
};
|
||||
|
||||
/* A dpi-normalized coordinate pair */
|
||||
struct normalized_coords {
|
||||
double x, y;
|
||||
|
|
@ -173,6 +182,17 @@ struct libinput_device_config_click_method {
|
|||
enum libinput_config_click_method (*get_default_method)(struct libinput_device *device);
|
||||
};
|
||||
|
||||
struct libinput_device_config_middle_emulation {
|
||||
int (*available)(struct libinput_device *device);
|
||||
enum libinput_config_status (*set)(
|
||||
struct libinput_device *device,
|
||||
enum libinput_config_middle_emulation_state);
|
||||
enum libinput_config_middle_emulation_state (*get)(
|
||||
struct libinput_device *device);
|
||||
enum libinput_config_middle_emulation_state (*get_default)(
|
||||
struct libinput_device *device);
|
||||
};
|
||||
|
||||
struct libinput_device_config {
|
||||
struct libinput_device_config_tap *tap;
|
||||
struct libinput_device_config_calibration *calibration;
|
||||
|
|
@ -182,6 +202,7 @@ struct libinput_device_config {
|
|||
struct libinput_device_config_left_handed *left_handed;
|
||||
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_group {
|
||||
|
|
@ -393,4 +414,85 @@ libinput_now(struct libinput *libinput)
|
|||
|
||||
return ts.tv_sec * 1000ULL + ts.tv_nsec / 1000000;
|
||||
}
|
||||
|
||||
static inline struct device_float_coords
|
||||
device_delta(struct device_coords a, struct device_coords b)
|
||||
{
|
||||
struct device_float_coords delta;
|
||||
|
||||
delta.x = a.x - b.x;
|
||||
delta.y = a.y - b.y;
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
static inline double
|
||||
normalized_length(struct normalized_coords norm)
|
||||
{
|
||||
return hypot(norm.x, norm.y);
|
||||
}
|
||||
|
||||
static inline int
|
||||
normalized_is_zero(struct normalized_coords norm)
|
||||
{
|
||||
return norm.x == 0.0 && norm.y == 0.0;
|
||||
}
|
||||
|
||||
enum directions {
|
||||
N = 1 << 0,
|
||||
NE = 1 << 1,
|
||||
E = 1 << 2,
|
||||
SE = 1 << 3,
|
||||
S = 1 << 4,
|
||||
SW = 1 << 5,
|
||||
W = 1 << 6,
|
||||
NW = 1 << 7,
|
||||
UNDEFINED_DIRECTION = 0xff
|
||||
};
|
||||
|
||||
static inline int
|
||||
normalized_get_direction(struct normalized_coords norm)
|
||||
{
|
||||
int dir = UNDEFINED_DIRECTION;
|
||||
int d1, d2;
|
||||
double r;
|
||||
|
||||
if (fabs(norm.x) < 2.0 && fabs(norm.y) < 2.0) {
|
||||
if (norm.x > 0.0 && norm.y > 0.0)
|
||||
dir = S | SE | E;
|
||||
else if (norm.x > 0.0 && norm.y < 0.0)
|
||||
dir = N | NE | E;
|
||||
else if (norm.x < 0.0 && norm.y > 0.0)
|
||||
dir = S | SW | W;
|
||||
else if (norm.x < 0.0 && norm.y < 0.0)
|
||||
dir = N | NW | W;
|
||||
else if (norm.x > 0.0)
|
||||
dir = NE | E | SE;
|
||||
else if (norm.x < 0.0)
|
||||
dir = NW | W | SW;
|
||||
else if (norm.y > 0.0)
|
||||
dir = SE | S | SW;
|
||||
else if (norm.y < 0.0)
|
||||
dir = NE | N | NW;
|
||||
} else {
|
||||
/* Calculate r within the interval [0 to 8)
|
||||
*
|
||||
* r = [0 .. 2π] where 0 is North
|
||||
* d_f = r / 2π ([0 .. 1))
|
||||
* d_8 = 8 * d_f
|
||||
*/
|
||||
r = atan2(norm.y, norm.x);
|
||||
r = fmod(r + 2.5*M_PI, 2*M_PI);
|
||||
r *= 4*M_1_PI;
|
||||
|
||||
/* Mark one or two close enough octants */
|
||||
d1 = (int)(r + 0.9) % 8;
|
||||
d2 = (int)(r + 0.1) % 8;
|
||||
|
||||
dir = (1 << d1) | (1 << d2);
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
#endif /* LIBINPUT_PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <locale.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -201,3 +202,33 @@ parse_mouse_wheel_click_angle_property(const char *prop)
|
|||
|
||||
return angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to parse the TRACKPOINT_CONST_ACCEL property from udev.
|
||||
* Property is of the form:
|
||||
* TRACKPOINT_CONST_ACCEL=<float>
|
||||
*
|
||||
* @param prop The value of the udev property (without the TRACKPOINT_CONST_ACCEL=)
|
||||
* @return The acceleration, or 0.0 on error.
|
||||
*/
|
||||
double
|
||||
parse_trackpoint_accel_property(const char *prop)
|
||||
{
|
||||
locale_t c_locale;
|
||||
double accel;
|
||||
char *endp;
|
||||
|
||||
/* Create a "C" locale to force strtod to use '.' as separator */
|
||||
c_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
|
||||
if (c_locale == (locale_t)0)
|
||||
return 0.0;
|
||||
|
||||
accel = strtod_l(prop, &endp, c_locale);
|
||||
|
||||
freelocale(c_locale);
|
||||
|
||||
if (*endp != '\0')
|
||||
return 0.0;
|
||||
|
||||
return accel;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,63 +122,6 @@ msleep(unsigned int ms)
|
|||
usleep(ms * 1000);
|
||||
}
|
||||
|
||||
enum directions {
|
||||
N = 1 << 0,
|
||||
NE = 1 << 1,
|
||||
E = 1 << 2,
|
||||
SE = 1 << 3,
|
||||
S = 1 << 4,
|
||||
SW = 1 << 5,
|
||||
W = 1 << 6,
|
||||
NW = 1 << 7,
|
||||
UNDEFINED_DIRECTION = 0xff
|
||||
};
|
||||
|
||||
static inline int
|
||||
vector_get_direction(double dx, double dy)
|
||||
{
|
||||
int dir = UNDEFINED_DIRECTION;
|
||||
int d1, d2;
|
||||
double r;
|
||||
|
||||
if (fabs(dx) < 2.0 && fabs(dy) < 2.0) {
|
||||
if (dx > 0.0 && dy > 0.0)
|
||||
dir = S | SE | E;
|
||||
else if (dx > 0.0 && dy < 0.0)
|
||||
dir = N | NE | E;
|
||||
else if (dx < 0.0 && dy > 0.0)
|
||||
dir = S | SW | W;
|
||||
else if (dx < 0.0 && dy < 0.0)
|
||||
dir = N | NW | W;
|
||||
else if (dx > 0.0)
|
||||
dir = NE | E | SE;
|
||||
else if (dx < 0.0)
|
||||
dir = NW | W | SW;
|
||||
else if (dy > 0.0)
|
||||
dir = SE | S | SW;
|
||||
else if (dy < 0.0)
|
||||
dir = NE | N | NW;
|
||||
} else {
|
||||
/* Calculate r within the interval [0 to 8)
|
||||
*
|
||||
* r = [0 .. 2π] where 0 is North
|
||||
* d_f = r / 2π ([0 .. 1))
|
||||
* d_8 = 8 * d_f
|
||||
*/
|
||||
r = atan2(dy, dx);
|
||||
r = fmod(r + 2.5*M_PI, 2*M_PI);
|
||||
r *= 4*M_1_PI;
|
||||
|
||||
/* Mark one or two close enough octants */
|
||||
d1 = (int)(r + 0.9) % 8;
|
||||
d2 = (int)(r + 0.1) % 8;
|
||||
|
||||
dir = (1 << d1) | (1 << d2);
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
static inline int
|
||||
long_bit_is_set(const unsigned long *array, int bit)
|
||||
{
|
||||
|
|
@ -323,5 +266,6 @@ enum ratelimit_state ratelimit_test(struct ratelimit *r);
|
|||
|
||||
int parse_mouse_dpi_property(const char *prop);
|
||||
int parse_mouse_wheel_click_angle_property(const char *prop);
|
||||
double parse_trackpoint_accel_property(const char *prop);
|
||||
|
||||
#endif /* LIBINPUT_UTIL_H */
|
||||
|
|
|
|||
129
src/libinput.c
129
src/libinput.c
|
|
@ -1326,6 +1326,35 @@ notify_removed_device(struct libinput_device *device)
|
|||
&removed_device_event->base);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
device_has_cap(struct libinput_device *device,
|
||||
enum libinput_device_capability cap)
|
||||
{
|
||||
const char *capability;
|
||||
|
||||
if (libinput_device_has_capability(device, cap))
|
||||
return true;
|
||||
|
||||
switch (cap) {
|
||||
case LIBINPUT_DEVICE_CAP_POINTER:
|
||||
capability = "CAP_POINTER";
|
||||
break;
|
||||
case LIBINPUT_DEVICE_CAP_KEYBOARD:
|
||||
capability = "CAP_KEYBOARD";
|
||||
break;
|
||||
case LIBINPUT_DEVICE_CAP_TOUCH:
|
||||
capability = "CAP_TOUCH";
|
||||
break;
|
||||
}
|
||||
|
||||
log_bug_libinput(device->seat->libinput,
|
||||
"Event for missing capability %s on device \"%s\"\n",
|
||||
capability,
|
||||
libinput_device_get_name(device));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
keyboard_notify_key(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
|
|
@ -1335,6 +1364,9 @@ keyboard_notify_key(struct libinput_device *device,
|
|||
struct libinput_event_keyboard *key_event;
|
||||
uint32_t seat_key_count;
|
||||
|
||||
if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_KEYBOARD))
|
||||
return;
|
||||
|
||||
key_event = zalloc(sizeof *key_event);
|
||||
if (!key_event)
|
||||
return;
|
||||
|
|
@ -1361,6 +1393,9 @@ pointer_notify_motion(struct libinput_device *device,
|
|||
{
|
||||
struct libinput_event_pointer *motion_event;
|
||||
|
||||
if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_POINTER))
|
||||
return;
|
||||
|
||||
motion_event = zalloc(sizeof *motion_event);
|
||||
if (!motion_event)
|
||||
return;
|
||||
|
|
@ -1383,6 +1418,9 @@ pointer_notify_motion_absolute(struct libinput_device *device,
|
|||
{
|
||||
struct libinput_event_pointer *motion_absolute_event;
|
||||
|
||||
if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_POINTER))
|
||||
return;
|
||||
|
||||
motion_absolute_event = zalloc(sizeof *motion_absolute_event);
|
||||
if (!motion_absolute_event)
|
||||
return;
|
||||
|
|
@ -1406,6 +1444,9 @@ pointer_notify_button(struct libinput_device *device,
|
|||
struct libinput_event_pointer *button_event;
|
||||
int32_t seat_button_count;
|
||||
|
||||
if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_POINTER))
|
||||
return;
|
||||
|
||||
button_event = zalloc(sizeof *button_event);
|
||||
if (!button_event)
|
||||
return;
|
||||
|
|
@ -1436,6 +1477,9 @@ pointer_notify_axis(struct libinput_device *device,
|
|||
{
|
||||
struct libinput_event_pointer *axis_event;
|
||||
|
||||
if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_POINTER))
|
||||
return;
|
||||
|
||||
axis_event = zalloc(sizeof *axis_event);
|
||||
if (!axis_event)
|
||||
return;
|
||||
|
|
@ -1462,6 +1506,9 @@ touch_notify_touch_down(struct libinput_device *device,
|
|||
{
|
||||
struct libinput_event_touch *touch_event;
|
||||
|
||||
if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_TOUCH))
|
||||
return;
|
||||
|
||||
touch_event = zalloc(sizeof *touch_event);
|
||||
if (!touch_event)
|
||||
return;
|
||||
|
|
@ -1487,6 +1534,9 @@ touch_notify_touch_motion(struct libinput_device *device,
|
|||
{
|
||||
struct libinput_event_touch *touch_event;
|
||||
|
||||
if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_TOUCH))
|
||||
return;
|
||||
|
||||
touch_event = zalloc(sizeof *touch_event);
|
||||
if (!touch_event)
|
||||
return;
|
||||
|
|
@ -1511,6 +1561,9 @@ touch_notify_touch_up(struct libinput_device *device,
|
|||
{
|
||||
struct libinput_event_touch *touch_event;
|
||||
|
||||
if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_TOUCH))
|
||||
return;
|
||||
|
||||
touch_event = zalloc(sizeof *touch_event);
|
||||
if (!touch_event)
|
||||
return;
|
||||
|
|
@ -1532,6 +1585,9 @@ touch_notify_frame(struct libinput_device *device,
|
|||
{
|
||||
struct libinput_event_touch *touch_event;
|
||||
|
||||
if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_TOUCH))
|
||||
return;
|
||||
|
||||
touch_event = zalloc(sizeof *touch_event);
|
||||
if (!touch_event)
|
||||
return;
|
||||
|
|
@ -1855,6 +1911,12 @@ libinput_device_pointer_has_button(struct libinput_device *device, uint32_t code
|
|||
return evdev_device_has_button((struct evdev_device *)device, code);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_keyboard_has_key(struct libinput_device *device, uint32_t code)
|
||||
{
|
||||
return evdev_device_has_key((struct evdev_device *)device, code);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_event *
|
||||
libinput_event_device_notify_get_base_event(struct libinput_event_device_notify *event)
|
||||
{
|
||||
|
|
@ -2010,11 +2072,12 @@ libinput_device_config_tap_set_enabled(struct libinput_device *device,
|
|||
enable != LIBINPUT_CONFIG_TAP_DISABLED)
|
||||
return LIBINPUT_CONFIG_STATUS_INVALID;
|
||||
|
||||
if (enable &&
|
||||
libinput_device_config_tap_get_finger_count(device) == 0)
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
if (libinput_device_config_tap_get_finger_count(device) == 0)
|
||||
return enable ? LIBINPUT_CONFIG_STATUS_UNSUPPORTED :
|
||||
LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
|
||||
return device->config.tap->set_enabled(device, enable);
|
||||
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_tap_state
|
||||
|
|
@ -2237,9 +2300,6 @@ LIBINPUT_EXPORT enum libinput_config_status
|
|||
libinput_device_config_click_set_method(struct libinput_device *device,
|
||||
enum libinput_config_click_method method)
|
||||
{
|
||||
if ((libinput_device_config_click_get_methods(device) & method) != method)
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
|
||||
/* Check method is a single valid method */
|
||||
switch (method) {
|
||||
case LIBINPUT_CONFIG_CLICK_METHOD_NONE:
|
||||
|
|
@ -2250,6 +2310,9 @@ libinput_device_config_click_set_method(struct libinput_device *device,
|
|||
return LIBINPUT_CONFIG_STATUS_INVALID;
|
||||
}
|
||||
|
||||
if ((libinput_device_config_click_get_methods(device) & method) != method)
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
|
||||
if (device->config.click_method)
|
||||
return device->config.click_method->set_method(device, method);
|
||||
else /* method must be _NONE to get here */
|
||||
|
|
@ -2274,6 +2337,60 @@ libinput_device_config_click_get_default_method(struct libinput_device *device)
|
|||
return LIBINPUT_CONFIG_CLICK_METHOD_NONE;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_config_middle_emulation_is_available(
|
||||
struct libinput_device *device)
|
||||
{
|
||||
if (device->config.middle_emulation)
|
||||
return device->config.middle_emulation->available(device);
|
||||
else
|
||||
return LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_status
|
||||
libinput_device_config_middle_emulation_set_enabled(
|
||||
struct libinput_device *device,
|
||||
enum libinput_config_middle_emulation_state enable)
|
||||
{
|
||||
int available =
|
||||
libinput_device_config_middle_emulation_is_available(device);
|
||||
|
||||
switch (enable) {
|
||||
case LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED:
|
||||
if (!available)
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
break;
|
||||
case LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED:
|
||||
if (!available)
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
break;
|
||||
default:
|
||||
return LIBINPUT_CONFIG_STATUS_INVALID;
|
||||
}
|
||||
|
||||
return device->config.middle_emulation->set(device, enable);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_middle_emulation_state
|
||||
libinput_device_config_middle_emulation_get_enabled(
|
||||
struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_middle_emulation_is_available(device))
|
||||
return LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
|
||||
|
||||
return device->config.middle_emulation->get(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_middle_emulation_state
|
||||
libinput_device_config_middle_emulation_get_default_enabled(
|
||||
struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_middle_emulation_is_available(device))
|
||||
return LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
|
||||
|
||||
return device->config.middle_emulation->get_default(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_device_config_scroll_get_methods(struct libinput_device *device)
|
||||
{
|
||||
|
|
|
|||
140
src/libinput.h
140
src/libinput.h
|
|
@ -2183,6 +2183,22 @@ libinput_device_get_size(struct libinput_device *device,
|
|||
int
|
||||
libinput_device_pointer_has_button(struct libinput_device *device, uint32_t code);
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
*
|
||||
* Check if a @ref LIBINPUT_DEVICE_CAP_KEYBOARD device has a key with the
|
||||
* given code (see linux/input.h).
|
||||
*
|
||||
* @param device A current input device
|
||||
* @param code Key code to check for, e.g. <i>KEY_ESC</i>
|
||||
*
|
||||
* @return 1 if the device supports this key code, 0 if it does not, -1
|
||||
* on error.
|
||||
*/
|
||||
int
|
||||
libinput_device_keyboard_has_key(struct libinput_device *device,
|
||||
uint32_t code);
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
*
|
||||
|
|
@ -2914,6 +2930,130 @@ libinput_device_config_click_get_method(struct libinput_device *device);
|
|||
enum libinput_config_click_method
|
||||
libinput_device_config_click_get_default_method(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*/
|
||||
enum libinput_config_middle_emulation_state {
|
||||
/**
|
||||
* Middle mouse button emulation is to be disabled, or
|
||||
* is currently disabled.
|
||||
*/
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED,
|
||||
/**
|
||||
* Middle mouse button emulation is to be enabled, or
|
||||
* is currently enabled.
|
||||
*/
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED,
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Check if middle mouse button emulation configuration is available on this
|
||||
* device. See libinput_device_config_middle_emulation_set_enabled() for
|
||||
* details.
|
||||
*
|
||||
* @note Some devices provide middle mouse button emulation but do not allow
|
||||
* enabling/disabling that emulation. These devices return zero in
|
||||
* libinput_device_config_middle_emulation_is_available().
|
||||
*
|
||||
* @param device The device to query
|
||||
*
|
||||
* @return Non-zero if middle mouse button emulation is available and can be
|
||||
* configured, zero otherwise.
|
||||
*
|
||||
* @see libinput_device_config_middle_emulation_set_enabled
|
||||
* @see libinput_device_config_middle_emulation_get_enabled
|
||||
* @see libinput_device_config_middle_emulation_get_default_enabled
|
||||
*/
|
||||
int
|
||||
libinput_device_config_middle_emulation_is_available(
|
||||
struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Enable or disable middle button emulation on this device. When enabled, a
|
||||
* simultaneous press of the left and right button generates a middle mouse
|
||||
* button event. Releasing the buttons generates a middle mouse button
|
||||
* release, the left and right button events are discarded otherwise.
|
||||
*
|
||||
* The middle button release event may be generated when either button is
|
||||
* released, or when both buttons have been released. The exact behavior is
|
||||
* device-dependent.
|
||||
*
|
||||
* The middle button emulation behavior when combined with other device
|
||||
* buttons, including a physical middle button is device-dependent.
|
||||
*
|
||||
* @note Some devices provide middle mouse button emulation but do not allow
|
||||
* enabling/disabling that emulation.
|
||||
*
|
||||
* @param device The device to configure
|
||||
* @param enable @ref LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED to
|
||||
* disable, @ref LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED To enable
|
||||
* middle button emulation.
|
||||
*
|
||||
* @return A config status code. Disabling middle button emulation on a
|
||||
* device that does not support middle button emulation always succeeds.
|
||||
*
|
||||
* @see libinput_device_config_middle_emulation_is_available
|
||||
* @see libinput_device_config_middle_emulation_get_enabled
|
||||
* @see libinput_device_config_middle_emulation_get_default_enabled
|
||||
*/
|
||||
enum libinput_config_status
|
||||
libinput_device_config_middle_emulation_set_enabled(
|
||||
struct libinput_device *device,
|
||||
enum libinput_config_middle_emulation_state enable);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Check if configurable middle button emulation is enabled on this device.
|
||||
* If the device does not have configurable middle button emulation, this
|
||||
* function returns @ref LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED.
|
||||
*
|
||||
* @note Some devices provide middle mouse button emulation but do not allow
|
||||
* enabling/disabling that emulation. These devices always return @ref
|
||||
* LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED.
|
||||
*
|
||||
* @param device The device to configure
|
||||
* @return @ref LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED if disabled
|
||||
* or not available/configurable, @ref
|
||||
* LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED If enabled.
|
||||
*
|
||||
* @see libinput_device_config_middle_emulation_is_available
|
||||
* @see libinput_device_config_middle_emulation_set_enabled
|
||||
* @see libinput_device_config_middle_emulation_get_default_enabled
|
||||
*/
|
||||
enum libinput_config_middle_emulation_state
|
||||
libinput_device_config_middle_emulation_get_enabled(
|
||||
struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Check if configurable middle button emulation is enabled by default on
|
||||
* this device. If the device does not have configurable middle button
|
||||
* emulation, this function returns @ref
|
||||
* LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED.
|
||||
*
|
||||
* @note Some devices provide middle mouse button emulation but do not allow
|
||||
* enabling/disabling that emulation. These devices always return @ref
|
||||
* LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED.
|
||||
*
|
||||
* @param device The device to configure
|
||||
* @return @ref LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED If disabled
|
||||
* or not available, @ref LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED if
|
||||
* enabled.
|
||||
*
|
||||
* @see libinput_device_config_middle_emulation_is_available
|
||||
* @see libinput_device_config_middle_emulation_set_enabled
|
||||
* @see libinput_device_config_middle_emulation_get_enabled
|
||||
*/
|
||||
enum libinput_config_middle_emulation_state
|
||||
libinput_device_config_middle_emulation_get_default_enabled(
|
||||
struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
|
|
|
|||
|
|
@ -129,6 +129,19 @@ local:
|
|||
*;
|
||||
};
|
||||
|
||||
LIBINPUT_0.14.0 {
|
||||
global:
|
||||
libinput_device_config_middle_emulation_get_default_enabled;
|
||||
libinput_device_config_middle_emulation_get_enabled;
|
||||
libinput_device_config_middle_emulation_is_available;
|
||||
libinput_device_config_middle_emulation_set_enabled;
|
||||
} LIBINPUT_0.12.0;
|
||||
|
||||
LIBINPUT_0.15.0 {
|
||||
global:
|
||||
libinput_device_keyboard_has_key;
|
||||
} LIBINPUT_0.14.0;
|
||||
|
||||
/* tablet APIs, they are not part of any stable API promise yet.
|
||||
* keep them separate */
|
||||
LIBINPUT_TABLET_SUPPORT {
|
||||
|
|
@ -154,4 +167,4 @@ LIBINPUT_TABLET_SUPPORT {
|
|||
libinput_tool_ref;
|
||||
libinput_tool_set_user_data;
|
||||
libinput_tool_unref;
|
||||
} LIBINPUT_0.12.0;
|
||||
} LIBINPUT_0.15.0;
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ udev_device_from_devnode(struct libinput *libinput,
|
|||
dev = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
|
||||
|
||||
count++;
|
||||
if (count > 10) {
|
||||
if (count > 50) {
|
||||
log_bug_libinput(libinput,
|
||||
"udev device never initialized (%s)\n",
|
||||
devnode);
|
||||
|
|
|
|||
12
src/timer.c
12
src/timer.c
|
|
@ -101,6 +101,15 @@ libinput_timer_handler(void *data)
|
|||
struct libinput *libinput = data;
|
||||
struct libinput_timer *timer, *tmp;
|
||||
uint64_t now;
|
||||
uint64_t discard;
|
||||
int r;
|
||||
|
||||
r = read(libinput->timer.fd, &discard, sizeof(discard));
|
||||
if (r == -1 && errno != EAGAIN)
|
||||
log_bug_libinput(libinput,
|
||||
"Error %d reading from timerfd (%s)",
|
||||
errno,
|
||||
strerror(errno));
|
||||
|
||||
now = libinput_now(libinput);
|
||||
if (now == 0)
|
||||
|
|
@ -119,7 +128,8 @@ libinput_timer_handler(void *data)
|
|||
int
|
||||
libinput_timer_subsys_init(struct libinput *libinput)
|
||||
{
|
||||
libinput->timer.fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
|
||||
libinput->timer.fd = timerfd_create(CLOCK_MONOTONIC,
|
||||
TFD_CLOEXEC | TFD_NONBLOCK);
|
||||
if (libinput->timer.fd < 0)
|
||||
return -1;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,10 +14,14 @@ liblitest_la_SOURCES = \
|
|||
litest.h \
|
||||
litest-int.h \
|
||||
litest-alps-semi-mt.c \
|
||||
litest-atmel-hover.c \
|
||||
litest-bcm5974.c \
|
||||
litest-generic-singletouch.c \
|
||||
litest-keyboard.c \
|
||||
litest-keyboard-razer-blackwidow.c \
|
||||
litest-logitech-trackball.c \
|
||||
litest-mouse.c \
|
||||
litest-mouse-roccat.c \
|
||||
litest-ms-surface-cover.c \
|
||||
litest-protocol-a-touch-screen.c \
|
||||
litest-qemu-usb-tablet.c \
|
||||
|
|
@ -33,23 +37,31 @@ liblitest_la_SOURCES = \
|
|||
litest-wacom-isdv4-tablet.c \
|
||||
litest-wacom-touch.c \
|
||||
litest-wacom-intuos-finger.c \
|
||||
litest-wheel-only.c \
|
||||
litest-xen-virtual-pointer.c \
|
||||
litest-vmware-virtual-usb-mouse.c \
|
||||
litest.c
|
||||
liblitest_la_LIBADD = $(top_builddir)/src/libinput-util.la
|
||||
liblitest_la_CFLAGS = $(AM_CFLAGS)
|
||||
if HAVE_LIBUNWIND
|
||||
liblitest_la_LIBADD += $(LIBUNWIND_LIBS) -ldl
|
||||
liblitest_la_CFLAGS += $(LIBUNWIND_CFLAGS)
|
||||
endif
|
||||
|
||||
run_tests = \
|
||||
test-udev \
|
||||
test-path \
|
||||
test-touchpad \
|
||||
test-tablet \
|
||||
test-device \
|
||||
test-pointer \
|
||||
test-touch \
|
||||
test-log \
|
||||
test-tablet \
|
||||
test-touchpad \
|
||||
test-trackpoint \
|
||||
test-udev \
|
||||
test-path \
|
||||
test-log \
|
||||
test-misc \
|
||||
test-keyboard \
|
||||
test-device
|
||||
test-litest-selftest
|
||||
|
||||
build_tests = \
|
||||
test-build-cxx \
|
||||
test-build-linker \
|
||||
|
|
@ -83,7 +95,6 @@ test_log_LDADD = $(TEST_LIBS)
|
|||
test_log_LDFLAGS = -no-install
|
||||
|
||||
test_tablet_SOURCES = tablet.c
|
||||
test_tablet_CFLAGS = $(AM_CPPFLAGS)
|
||||
test_tablet_LDADD = $(TEST_LIBS)
|
||||
test_tablet_LDFLAGS = -static
|
||||
|
||||
|
|
@ -107,6 +118,11 @@ test_device_SOURCES = device.c
|
|||
test_device_LDADD = $(TEST_LIBS)
|
||||
test_device_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
|
||||
test_litest_selftest_LDADD = $(TEST_LIBS)
|
||||
test_litest_selftest_LDFLAGS = -no-install
|
||||
|
||||
# build-test only
|
||||
test_build_pedantic_c99_SOURCES = build-pedantic.c
|
||||
test_build_pedantic_c99_CFLAGS = -std=c99 -pedantic -Werror
|
||||
|
|
@ -123,6 +139,8 @@ test_build_linker_LDADD = $(top_builddir)/src/libinput.la $(top_builddir)/src/li
|
|||
test_build_cxx_SOURCES = build-cxx.cc
|
||||
test_build_cxx_CXXFLAGS = -Wall -Wextra -Wno-unused-parameter $(AM_CXXFLAGS)
|
||||
|
||||
AM_TESTS_ENVIRONMENT= LITEST_VERBOSE=1; export LITEST_VERBOSE;
|
||||
|
||||
if HAVE_VALGRIND
|
||||
VALGRIND_FLAGS=--leak-check=full \
|
||||
--quiet \
|
||||
|
|
@ -130,7 +148,7 @@ VALGRIND_FLAGS=--leak-check=full \
|
|||
--suppressions=$(srcdir)/valgrind.suppressions
|
||||
|
||||
valgrind:
|
||||
$(MAKE) check-TESTS LOG_COMPILER="$(VALGRIND)" LOG_FLAGS="$(VALGRIND_FLAGS)" CK_FORK=no
|
||||
$(MAKE) check-TESTS LOG_COMPILER="$(VALGRIND)" LOG_FLAGS="$(VALGRIND_FLAGS)" CK_FORK=no USING_VALGRIND=yes
|
||||
|
||||
check: valgrind
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
/* This is a build-test only */
|
||||
|
||||
int
|
||||
main(void) {
|
||||
main(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
143
test/device.c
143
test/device.c
|
|
@ -313,6 +313,9 @@ START_TEST(device_reenable_syspath_changed)
|
|||
|
||||
litest_device = litest_add_device(li, LITEST_MOUSE);
|
||||
device2 = litest_device->libinput_device;
|
||||
/* Note: if the sysname isn't the same, some other device got added
|
||||
* or removed while this test was running. This is unlikely and
|
||||
* would result in a false positive, so let's fail the test here */
|
||||
ck_assert_str_eq(libinput_device_get_sysname(device1),
|
||||
libinput_device_get_sysname(device2));
|
||||
|
||||
|
|
@ -814,37 +817,39 @@ START_TEST(abs_mt_device_no_absx)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(abs_device_no_range)
|
||||
static void
|
||||
assert_device_ignored(struct libinput *li, struct input_absinfo *absinfo)
|
||||
{
|
||||
struct libevdev_uinput *uinput;
|
||||
struct libinput *li;
|
||||
struct libinput_device *device;
|
||||
int code;
|
||||
|
||||
uinput = litest_create_uinput_abs_device("test device", NULL,
|
||||
absinfo,
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
-1);
|
||||
device = libinput_path_add_device(li,
|
||||
libevdev_uinput_get_devnode(uinput));
|
||||
litest_assert_ptr_null(device);
|
||||
libevdev_uinput_destroy(uinput);
|
||||
}
|
||||
|
||||
START_TEST(abs_device_no_range)
|
||||
{
|
||||
struct libinput *li;
|
||||
int code = _i; /* looped test */
|
||||
/* set x/y so libinput doesn't just reject for missing axes */
|
||||
struct input_absinfo absinfo[] = {
|
||||
{ ABS_X, 0, 10, 0, 0, 0 },
|
||||
{ ABS_Y, 0, 10, 0, 0, 0 },
|
||||
{ -1, 0, 0, 0, 0, 0 },
|
||||
{ code, 0, 0, 0, 0, 0 },
|
||||
{ -1, -1, -1, -1, -1, -1 }
|
||||
};
|
||||
|
||||
li = litest_create_context();
|
||||
litest_disable_log_handler(li);
|
||||
|
||||
for (code = 0; code < ABS_MT_SLOT; code++) {
|
||||
if (code == ABS_MISC)
|
||||
continue;
|
||||
absinfo[2].value = code;
|
||||
uinput = litest_create_uinput_abs_device("test device", NULL,
|
||||
absinfo,
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
-1);
|
||||
device = libinput_path_add_device(li,
|
||||
libevdev_uinput_get_devnode(uinput));
|
||||
ck_assert(device == NULL);
|
||||
libevdev_uinput_destroy(uinput);
|
||||
}
|
||||
assert_device_ignored(li, absinfo);
|
||||
|
||||
litest_restore_log_handler(li);
|
||||
libinput_unref(li);
|
||||
|
|
@ -853,10 +858,8 @@ END_TEST
|
|||
|
||||
START_TEST(abs_mt_device_no_range)
|
||||
{
|
||||
struct libevdev_uinput *uinput;
|
||||
struct libinput *li;
|
||||
struct libinput_device *device;
|
||||
int code;
|
||||
int code = _i; /* looped test */
|
||||
/* set x/y so libinput doesn't just reject for missing axes */
|
||||
struct input_absinfo absinfo[] = {
|
||||
{ ABS_X, 0, 10, 0, 0, 0 },
|
||||
|
|
@ -865,37 +868,90 @@ START_TEST(abs_mt_device_no_range)
|
|||
{ ABS_MT_TRACKING_ID, 0, 255, 0, 0, 0 },
|
||||
{ ABS_MT_POSITION_X, 0, 10, 0, 0, 0 },
|
||||
{ ABS_MT_POSITION_Y, 0, 10, 0, 0, 0 },
|
||||
{ -1, 0, 0, 0, 0, 0 },
|
||||
{ code, 0, 0, 0, 0, 0 },
|
||||
{ -1, -1, -1, -1, -1, -1 }
|
||||
};
|
||||
|
||||
li = litest_create_context();
|
||||
litest_disable_log_handler(li);
|
||||
|
||||
for (code = ABS_MT_SLOT + 1; code < ABS_CNT; code++) {
|
||||
if (code == ABS_MT_TOOL_TYPE ||
|
||||
code == ABS_MT_TRACKING_ID) /* kernel overrides it */
|
||||
continue;
|
||||
|
||||
absinfo[6].value = code;
|
||||
uinput = litest_create_uinput_abs_device("test device", NULL,
|
||||
absinfo,
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
-1);
|
||||
device = libinput_path_add_device(li,
|
||||
libevdev_uinput_get_devnode(uinput));
|
||||
ck_assert(device == NULL);
|
||||
libevdev_uinput_destroy(uinput);
|
||||
}
|
||||
if (code != ABS_MT_TOOL_TYPE &&
|
||||
code != ABS_MT_TRACKING_ID) /* kernel overrides it */
|
||||
assert_device_ignored(li, absinfo);
|
||||
|
||||
litest_restore_log_handler(li);
|
||||
libinput_unref(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main (int argc, char **argv)
|
||||
START_TEST(abs_device_missing_res)
|
||||
{
|
||||
struct libinput *li;
|
||||
struct input_absinfo absinfo[] = {
|
||||
{ ABS_X, 0, 10, 0, 0, 10 },
|
||||
{ ABS_Y, 0, 10, 0, 0, 0 },
|
||||
{ -1, -1, -1, -1, -1, -1 }
|
||||
};
|
||||
|
||||
li = litest_create_context();
|
||||
litest_disable_log_handler(li);
|
||||
|
||||
assert_device_ignored(li, absinfo);
|
||||
|
||||
absinfo[0].resolution = 0;
|
||||
absinfo[1].resolution = 20;
|
||||
|
||||
assert_device_ignored(li, absinfo);
|
||||
|
||||
litest_restore_log_handler(li);
|
||||
libinput_unref(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(abs_mt_device_missing_res)
|
||||
{
|
||||
struct libinput *li;
|
||||
struct input_absinfo absinfo[] = {
|
||||
{ ABS_X, 0, 10, 0, 0, 10 },
|
||||
{ ABS_Y, 0, 10, 0, 0, 10 },
|
||||
{ ABS_MT_SLOT, 0, 2, 0, 0, 0 },
|
||||
{ ABS_MT_TRACKING_ID, 0, 255, 0, 0, 0 },
|
||||
{ ABS_MT_POSITION_X, 0, 10, 0, 0, 10 },
|
||||
{ ABS_MT_POSITION_Y, 0, 10, 0, 0, 0 },
|
||||
{ -1, -1, -1, -1, -1, -1 }
|
||||
};
|
||||
|
||||
li = litest_create_context();
|
||||
litest_disable_log_handler(li);
|
||||
assert_device_ignored(li, absinfo);
|
||||
|
||||
absinfo[4].resolution = 0;
|
||||
absinfo[5].resolution = 20;
|
||||
|
||||
assert_device_ignored(li, absinfo);
|
||||
|
||||
litest_restore_log_handler(li);
|
||||
libinput_unref(li);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_wheel_only)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
|
||||
ck_assert(libinput_device_has_capability(device,
|
||||
LIBINPUT_DEVICE_CAP_POINTER));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
litest_setup_tests(void)
|
||||
{
|
||||
struct range abs_range = { 0, ABS_MISC };
|
||||
struct range abs_mt_range = { ABS_MT_SLOT + 1, ABS_CNT };
|
||||
|
||||
litest_add("device:sendevents", device_sendevents_config, LITEST_ANY, LITEST_TOUCHPAD|LITEST_TABLET);
|
||||
litest_add("device:sendevents", device_sendevents_config_invalid, LITEST_ANY, LITEST_TABLET);
|
||||
litest_add("device:sendevents", device_sendevents_config_touchpad, LITEST_TOUCHPAD, LITEST_TABLET);
|
||||
|
|
@ -906,7 +962,6 @@ int main (int argc, char **argv)
|
|||
litest_add("device:sendevents", device_disable_events_pending, LITEST_RELATIVE, LITEST_TOUCHPAD|LITEST_TABLET);
|
||||
litest_add("device:sendevents", device_double_disable, LITEST_ANY, LITEST_TABLET);
|
||||
litest_add("device:sendevents", device_double_enable, LITEST_ANY, LITEST_TABLET);
|
||||
|
||||
litest_add_no_device("device:sendevents", device_reenable_syspath_changed);
|
||||
litest_add_no_device("device:sendevents", device_reenable_device_removed);
|
||||
litest_add_for_device("device:sendevents", device_disable_release_buttons, LITEST_MOUSE);
|
||||
|
|
@ -927,8 +982,10 @@ int main (int argc, char **argv)
|
|||
litest_add_no_device("device:invalid devices", abs_device_no_absy);
|
||||
litest_add_no_device("device:invalid devices", abs_mt_device_no_absx);
|
||||
litest_add_no_device("device:invalid devices", abs_mt_device_no_absy);
|
||||
litest_add_no_device("device:invalid devices", abs_device_no_range);
|
||||
litest_add_no_device("device:invalid devices", abs_mt_device_no_range);
|
||||
litest_add_ranged_no_device("device:invalid devices", abs_device_no_range, &abs_range);
|
||||
litest_add_ranged_no_device("device:invalid devices", abs_mt_device_no_range, &abs_mt_range);
|
||||
litest_add_no_device("device:invalid devices", abs_device_missing_res);
|
||||
litest_add_no_device("device:invalid devices", abs_mt_device_missing_res);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
litest_add("device:wheel", device_wheel_only, LITEST_WHEEL, LITEST_RELATIVE|LITEST_ABSOLUTE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,11 +61,9 @@ START_TEST(keyboard_seat_key_count)
|
|||
continue;
|
||||
}
|
||||
|
||||
kev = libinput_event_get_keyboard_event(ev);
|
||||
ck_assert_notnull(kev);
|
||||
ck_assert_int_eq(libinput_event_keyboard_get_key(kev), KEY_A);
|
||||
ck_assert_int_eq(libinput_event_keyboard_get_key_state(kev),
|
||||
LIBINPUT_KEY_STATE_PRESSED);
|
||||
kev = litest_is_keyboard_event(ev,
|
||||
KEY_A,
|
||||
LIBINPUT_KEY_STATE_PRESSED);
|
||||
|
||||
++expected_key_button_count;
|
||||
seat_key_count =
|
||||
|
|
@ -175,31 +173,6 @@ START_TEST(keyboard_ignore_no_pressed_release)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
static void
|
||||
test_key_event(struct litest_device *dev, unsigned int key, int state)
|
||||
{
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_keyboard *kevent;
|
||||
|
||||
litest_event(dev, EV_KEY, key, state);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert(event != NULL);
|
||||
ck_assert_int_eq(libinput_event_get_type(event), LIBINPUT_EVENT_KEYBOARD_KEY);
|
||||
|
||||
kevent = libinput_event_get_keyboard_event(event);
|
||||
ck_assert(kevent != NULL);
|
||||
ck_assert_int_eq(libinput_event_keyboard_get_key(kevent), key);
|
||||
ck_assert_int_eq(libinput_event_keyboard_get_key_state(kevent),
|
||||
state ? LIBINPUT_KEY_STATE_PRESSED :
|
||||
LIBINPUT_KEY_STATE_RELEASED);
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
START_TEST(keyboard_key_auto_release)
|
||||
{
|
||||
struct libinput *libinput;
|
||||
|
|
@ -244,7 +217,17 @@ START_TEST(keyboard_key_auto_release)
|
|||
|
||||
/* Send pressed events, without releasing */
|
||||
for (i = 0; i < ARRAY_LENGTH(keys); ++i) {
|
||||
test_key_event(dev, keys[i].code, 1);
|
||||
key = keys[i].code;
|
||||
litest_event(dev, EV_KEY, key, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
libinput_dispatch(libinput);
|
||||
|
||||
event = libinput_get_event(libinput);
|
||||
kevent = litest_is_keyboard_event(event,
|
||||
key,
|
||||
LIBINPUT_KEY_STATE_PRESSED);
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
litest_drain_events(libinput);
|
||||
|
|
@ -290,12 +273,49 @@ START_TEST(keyboard_key_auto_release)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
START_TEST(keyboard_has_key)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
unsigned int code;
|
||||
int evdev_has, libinput_has;
|
||||
|
||||
ck_assert(libinput_device_has_capability(
|
||||
device,
|
||||
LIBINPUT_DEVICE_CAP_KEYBOARD));
|
||||
|
||||
for (code = 0; code < KEY_CNT; code++) {
|
||||
evdev_has = libevdev_has_event_code(dev->evdev, EV_KEY, code);
|
||||
libinput_has = libinput_device_keyboard_has_key(device, code);
|
||||
ck_assert_int_eq(evdev_has, libinput_has);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(keyboard_keys_bad_device)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
unsigned int code;
|
||||
int has_key;
|
||||
|
||||
if (libinput_device_has_capability(device,
|
||||
LIBINPUT_DEVICE_CAP_KEYBOARD))
|
||||
return;
|
||||
|
||||
for (code = 0; code < KEY_CNT; code++) {
|
||||
has_key = libinput_device_keyboard_has_key(device, code);
|
||||
ck_assert_int_eq(has_key, -1);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
litest_setup_tests(void)
|
||||
{
|
||||
litest_add_no_device("keyboard:seat key count", keyboard_seat_key_count);
|
||||
litest_add_no_device("keyboard:key counting", keyboard_ignore_no_pressed_release);
|
||||
litest_add_no_device("keyboard:key counting", keyboard_key_auto_release);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
litest_add("keyboard:keys", keyboard_has_key, LITEST_KEYS, LITEST_ANY);
|
||||
litest_add("keyboard:keys", keyboard_keys_bad_device, LITEST_ANY, LITEST_ANY);
|
||||
}
|
||||
|
|
|
|||
149
test/litest-atmel-hover.c
Normal file
149
test/litest-atmel-hover.c
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright © 2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "libinput-util.h"
|
||||
|
||||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
||||
static void
|
||||
atmel_hover_create(struct litest_device *d);
|
||||
|
||||
static void
|
||||
litest_atmel_hover_setup(void)
|
||||
{
|
||||
struct litest_device *d = litest_create_device(LITEST_ATMEL_HOVER);
|
||||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static struct input_event down[] = {
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_DISTANCE, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static struct input_event move[] = {
|
||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_DISTANCE, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static struct input_event up[] = {
|
||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
|
||||
{ .type = EV_ABS, .code = ABS_MT_DISTANCE, .value = 1 },
|
||||
{ .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = 0 },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static struct litest_device_interface interface = {
|
||||
.touch_down_events = down,
|
||||
.touch_move_events = move,
|
||||
.touch_up_events = up,
|
||||
};
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x18,
|
||||
.vendor = 0x0,
|
||||
.product = 0x0,
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_TOOL_FINGER,
|
||||
EV_KEY, BTN_TOUCH,
|
||||
EV_KEY, BTN_TOOL_DOUBLETAP,
|
||||
EV_KEY, BTN_TOOL_TRIPLETAP,
|
||||
EV_KEY, BTN_TOOL_QUADTAP,
|
||||
EV_KEY, BTN_TOOL_QUINTTAP,
|
||||
INPUT_PROP_MAX, INPUT_PROP_POINTER,
|
||||
INPUT_PROP_MAX, INPUT_PROP_BUTTONPAD,
|
||||
-1, -1,
|
||||
};
|
||||
|
||||
static struct input_absinfo absinfo[] = {
|
||||
{ ABS_X, 0, 960, 0, 0, 10 },
|
||||
{ ABS_Y, 0, 540, 0, 0, 10 },
|
||||
{ ABS_PRESSURE, 0, 255, 0, 0, 0 },
|
||||
{ ABS_MT_SLOT, 0, 9, 0, 0, 0 },
|
||||
{ ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0, 0 },
|
||||
{ ABS_MT_ORIENTATION, 0, 255, 0, 0, 0 },
|
||||
{ ABS_MT_POSITION_X, 0, 960, 0, 0, 10 },
|
||||
{ ABS_MT_POSITION_Y, 0, 540, 0, 0, 10 },
|
||||
{ ABS_MT_TOOL_TYPE, 0, 2, 0, 0, 0 },
|
||||
{ ABS_MT_TRACKING_ID, 0, 65535, 0, 0, 0 },
|
||||
{ ABS_MT_PRESSURE, 0, 255, 0, 0, 0 },
|
||||
{ ABS_MT_DISTANCE, 0, 1, 0, 0, 0 },
|
||||
{ .value = -1 }
|
||||
};
|
||||
|
||||
struct litest_test_device litest_atmel_hover_device = {
|
||||
.type = LITEST_ATMEL_HOVER,
|
||||
.features = LITEST_TOUCHPAD | LITEST_BUTTON | LITEST_CLICKPAD | LITEST_HOVER,
|
||||
.shortname = "atmel hover",
|
||||
.setup = litest_atmel_hover_setup,
|
||||
.interface = &interface,
|
||||
.create = atmel_hover_create,
|
||||
|
||||
.name = "Atmel maXTouch Touchpad",
|
||||
.id = &input_id,
|
||||
.events = events,
|
||||
.absinfo = absinfo,
|
||||
};
|
||||
|
||||
static void
|
||||
atmel_hover_create(struct litest_device *d)
|
||||
{
|
||||
struct litest_semi_mt *semi_mt = zalloc(sizeof(*semi_mt));
|
||||
assert(semi_mt);
|
||||
|
||||
d->private = semi_mt;
|
||||
|
||||
d->uinput = litest_create_uinput_device_from_description(
|
||||
litest_atmel_hover_device.name,
|
||||
litest_atmel_hover_device.id,
|
||||
absinfo,
|
||||
events);
|
||||
d->interface = &interface;
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ static void litest_bcm5974_setup(void)
|
|||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
struct input_event down[] = {
|
||||
static struct input_event down[] = {
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_PRESSURE, .value = 30 },
|
||||
|
|
|
|||
350
test/litest-keyboard-razer-blackwidow.c
Normal file
350
test/litest-keyboard-razer-blackwidow.c
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* Copyright © 2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
||||
/* Recording from https://bugs.freedesktop.org/show_bug.cgi?id=89783
|
||||
* This is the second of 4 devices exported by this keyboard, the first is
|
||||
* just a basic keyboard that is identical to the normal litest-keyboard.c
|
||||
* file.
|
||||
*/
|
||||
|
||||
static void litest_blackwidow_setup(void)
|
||||
{
|
||||
struct litest_device *d = litest_create_device(LITEST_KEYBOARD_BLACKWIDOW);
|
||||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x3,
|
||||
.vendor = 0x1532,
|
||||
.product = 0x11b,
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
EV_REL, REL_HWHEEL,
|
||||
EV_KEY, KEY_ESC,
|
||||
EV_KEY, KEY_1,
|
||||
EV_KEY, KEY_2,
|
||||
EV_KEY, KEY_3,
|
||||
EV_KEY, KEY_4,
|
||||
EV_KEY, KEY_5,
|
||||
EV_KEY, KEY_6,
|
||||
EV_KEY, KEY_7,
|
||||
EV_KEY, KEY_8,
|
||||
EV_KEY, KEY_9,
|
||||
EV_KEY, KEY_0,
|
||||
EV_KEY, KEY_MINUS,
|
||||
EV_KEY, KEY_EQUAL,
|
||||
EV_KEY, KEY_BACKSPACE,
|
||||
EV_KEY, KEY_TAB,
|
||||
EV_KEY, KEY_Q,
|
||||
EV_KEY, KEY_W,
|
||||
EV_KEY, KEY_E,
|
||||
EV_KEY, KEY_R,
|
||||
EV_KEY, KEY_T,
|
||||
EV_KEY, KEY_Y,
|
||||
EV_KEY, KEY_U,
|
||||
EV_KEY, KEY_I,
|
||||
EV_KEY, KEY_O,
|
||||
EV_KEY, KEY_P,
|
||||
EV_KEY, KEY_LEFTBRACE,
|
||||
EV_KEY, KEY_RIGHTBRACE,
|
||||
EV_KEY, KEY_ENTER,
|
||||
EV_KEY, KEY_LEFTCTRL,
|
||||
EV_KEY, KEY_A,
|
||||
EV_KEY, KEY_S,
|
||||
EV_KEY, KEY_D,
|
||||
EV_KEY, KEY_F,
|
||||
EV_KEY, KEY_G,
|
||||
EV_KEY, KEY_H,
|
||||
EV_KEY, KEY_J,
|
||||
EV_KEY, KEY_K,
|
||||
EV_KEY, KEY_L,
|
||||
EV_KEY, KEY_SEMICOLON,
|
||||
EV_KEY, KEY_APOSTROPHE,
|
||||
EV_KEY, KEY_GRAVE,
|
||||
EV_KEY, KEY_LEFTSHIFT,
|
||||
EV_KEY, KEY_BACKSLASH,
|
||||
EV_KEY, KEY_Z,
|
||||
EV_KEY, KEY_X,
|
||||
EV_KEY, KEY_C,
|
||||
EV_KEY, KEY_V,
|
||||
EV_KEY, KEY_B,
|
||||
EV_KEY, KEY_N,
|
||||
EV_KEY, KEY_M,
|
||||
EV_KEY, KEY_COMMA,
|
||||
EV_KEY, KEY_DOT,
|
||||
EV_KEY, KEY_SLASH,
|
||||
EV_KEY, KEY_RIGHTSHIFT,
|
||||
EV_KEY, KEY_KPASTERISK,
|
||||
EV_KEY, KEY_LEFTALT,
|
||||
EV_KEY, KEY_SPACE,
|
||||
EV_KEY, KEY_CAPSLOCK,
|
||||
EV_KEY, KEY_F1,
|
||||
EV_KEY, KEY_F2,
|
||||
EV_KEY, KEY_F3,
|
||||
EV_KEY, KEY_F4,
|
||||
EV_KEY, KEY_F5,
|
||||
EV_KEY, KEY_F6,
|
||||
EV_KEY, KEY_F7,
|
||||
EV_KEY, KEY_F8,
|
||||
EV_KEY, KEY_F9,
|
||||
EV_KEY, KEY_F10,
|
||||
EV_KEY, KEY_NUMLOCK,
|
||||
EV_KEY, KEY_SCROLLLOCK,
|
||||
EV_KEY, KEY_KP7,
|
||||
EV_KEY, KEY_KP8,
|
||||
EV_KEY, KEY_KP9,
|
||||
EV_KEY, KEY_KPMINUS,
|
||||
EV_KEY, KEY_KP4,
|
||||
EV_KEY, KEY_KP5,
|
||||
EV_KEY, KEY_KP6,
|
||||
EV_KEY, KEY_KPPLUS,
|
||||
EV_KEY, KEY_KP1,
|
||||
EV_KEY, KEY_KP2,
|
||||
EV_KEY, KEY_KP3,
|
||||
EV_KEY, KEY_KP0,
|
||||
EV_KEY, KEY_KPDOT,
|
||||
EV_KEY, KEY_ZENKAKUHANKAKU,
|
||||
EV_KEY, KEY_102ND,
|
||||
EV_KEY, KEY_F11,
|
||||
EV_KEY, KEY_F12,
|
||||
EV_KEY, KEY_RO,
|
||||
EV_KEY, KEY_KATAKANA,
|
||||
EV_KEY, KEY_HIRAGANA,
|
||||
EV_KEY, KEY_HENKAN,
|
||||
EV_KEY, KEY_KATAKANAHIRAGANA,
|
||||
EV_KEY, KEY_MUHENKAN,
|
||||
EV_KEY, KEY_KPJPCOMMA,
|
||||
EV_KEY, KEY_KPENTER,
|
||||
EV_KEY, KEY_RIGHTCTRL,
|
||||
EV_KEY, KEY_KPSLASH,
|
||||
EV_KEY, KEY_SYSRQ,
|
||||
EV_KEY, KEY_RIGHTALT,
|
||||
EV_KEY, KEY_HOME,
|
||||
EV_KEY, KEY_UP,
|
||||
EV_KEY, KEY_PAGEUP,
|
||||
EV_KEY, KEY_LEFT,
|
||||
EV_KEY, KEY_RIGHT,
|
||||
EV_KEY, KEY_END,
|
||||
EV_KEY, KEY_DOWN,
|
||||
EV_KEY, KEY_PAGEDOWN,
|
||||
EV_KEY, KEY_INSERT,
|
||||
EV_KEY, KEY_DELETE,
|
||||
EV_KEY, KEY_MUTE,
|
||||
EV_KEY, KEY_VOLUMEDOWN,
|
||||
EV_KEY, KEY_VOLUMEUP,
|
||||
EV_KEY, KEY_POWER,
|
||||
EV_KEY, KEY_KPEQUAL,
|
||||
EV_KEY, KEY_PAUSE,
|
||||
EV_KEY, KEY_KPCOMMA,
|
||||
EV_KEY, KEY_HANGEUL,
|
||||
EV_KEY, KEY_HANJA,
|
||||
EV_KEY, KEY_YEN,
|
||||
EV_KEY, KEY_LEFTMETA,
|
||||
EV_KEY, KEY_RIGHTMETA,
|
||||
EV_KEY, KEY_COMPOSE,
|
||||
EV_KEY, KEY_STOP,
|
||||
EV_KEY, KEY_AGAIN,
|
||||
EV_KEY, KEY_PROPS,
|
||||
EV_KEY, KEY_UNDO,
|
||||
EV_KEY, KEY_FRONT,
|
||||
EV_KEY, KEY_COPY,
|
||||
EV_KEY, KEY_OPEN,
|
||||
EV_KEY, KEY_PASTE,
|
||||
EV_KEY, KEY_FIND,
|
||||
EV_KEY, KEY_CUT,
|
||||
EV_KEY, KEY_HELP,
|
||||
EV_KEY, KEY_MENU,
|
||||
EV_KEY, KEY_CALC,
|
||||
EV_KEY, KEY_SLEEP,
|
||||
EV_KEY, KEY_WAKEUP,
|
||||
EV_KEY, KEY_FILE,
|
||||
EV_KEY, KEY_WWW,
|
||||
EV_KEY, KEY_COFFEE,
|
||||
EV_KEY, KEY_MAIL,
|
||||
EV_KEY, KEY_BOOKMARKS,
|
||||
EV_KEY, KEY_BACK,
|
||||
EV_KEY, KEY_FORWARD,
|
||||
EV_KEY, KEY_EJECTCD,
|
||||
EV_KEY, KEY_NEXTSONG,
|
||||
EV_KEY, KEY_PLAYPAUSE,
|
||||
EV_KEY, KEY_PREVIOUSSONG,
|
||||
EV_KEY, KEY_STOPCD,
|
||||
EV_KEY, KEY_RECORD,
|
||||
EV_KEY, KEY_REWIND,
|
||||
EV_KEY, KEY_PHONE,
|
||||
EV_KEY, KEY_CONFIG,
|
||||
EV_KEY, KEY_HOMEPAGE,
|
||||
EV_KEY, KEY_REFRESH,
|
||||
EV_KEY, KEY_EXIT,
|
||||
EV_KEY, KEY_EDIT,
|
||||
EV_KEY, KEY_SCROLLUP,
|
||||
EV_KEY, KEY_SCROLLDOWN,
|
||||
EV_KEY, KEY_KPLEFTPAREN,
|
||||
EV_KEY, KEY_KPRIGHTPAREN,
|
||||
EV_KEY, KEY_NEW,
|
||||
EV_KEY, KEY_F13,
|
||||
EV_KEY, KEY_F14,
|
||||
EV_KEY, KEY_F15,
|
||||
EV_KEY, KEY_F16,
|
||||
EV_KEY, KEY_F17,
|
||||
EV_KEY, KEY_F18,
|
||||
EV_KEY, KEY_F19,
|
||||
EV_KEY, KEY_F20,
|
||||
EV_KEY, KEY_F21,
|
||||
EV_KEY, KEY_F22,
|
||||
EV_KEY, KEY_F23,
|
||||
EV_KEY, KEY_F24,
|
||||
EV_KEY, KEY_CLOSE,
|
||||
EV_KEY, KEY_PLAY,
|
||||
EV_KEY, KEY_FASTFORWARD,
|
||||
EV_KEY, KEY_BASSBOOST,
|
||||
EV_KEY, KEY_PRINT,
|
||||
EV_KEY, KEY_CAMERA,
|
||||
EV_KEY, KEY_CHAT,
|
||||
EV_KEY, KEY_SEARCH,
|
||||
EV_KEY, KEY_FINANCE,
|
||||
EV_KEY, KEY_BRIGHTNESSDOWN,
|
||||
EV_KEY, KEY_BRIGHTNESSUP,
|
||||
EV_KEY, KEY_KBDILLUMTOGGLE,
|
||||
EV_KEY, KEY_SAVE,
|
||||
EV_KEY, KEY_DOCUMENTS,
|
||||
EV_KEY, KEY_UNKNOWN,
|
||||
EV_KEY, KEY_VIDEO_NEXT,
|
||||
EV_KEY, KEY_BRIGHTNESS_AUTO,
|
||||
EV_KEY, BTN_0,
|
||||
EV_KEY, KEY_SELECT,
|
||||
EV_KEY, KEY_GOTO,
|
||||
EV_KEY, KEY_INFO,
|
||||
EV_KEY, KEY_PROGRAM,
|
||||
EV_KEY, KEY_PVR,
|
||||
EV_KEY, KEY_SUBTITLE,
|
||||
EV_KEY, KEY_ZOOM,
|
||||
EV_KEY, KEY_KEYBOARD,
|
||||
EV_KEY, KEY_PC,
|
||||
EV_KEY, KEY_TV,
|
||||
EV_KEY, KEY_TV2,
|
||||
EV_KEY, KEY_VCR,
|
||||
EV_KEY, KEY_VCR2,
|
||||
EV_KEY, KEY_SAT,
|
||||
EV_KEY, KEY_CD,
|
||||
EV_KEY, KEY_TAPE,
|
||||
EV_KEY, KEY_TUNER,
|
||||
EV_KEY, KEY_PLAYER,
|
||||
EV_KEY, KEY_DVD,
|
||||
EV_KEY, KEY_AUDIO,
|
||||
EV_KEY, KEY_VIDEO,
|
||||
EV_KEY, KEY_MEMO,
|
||||
EV_KEY, KEY_CALENDAR,
|
||||
EV_KEY, KEY_RED,
|
||||
EV_KEY, KEY_GREEN,
|
||||
EV_KEY, KEY_YELLOW,
|
||||
EV_KEY, KEY_BLUE,
|
||||
EV_KEY, KEY_CHANNELUP,
|
||||
EV_KEY, KEY_CHANNELDOWN,
|
||||
EV_KEY, KEY_LAST,
|
||||
EV_KEY, KEY_NEXT,
|
||||
EV_KEY, KEY_RESTART,
|
||||
EV_KEY, KEY_SLOW,
|
||||
EV_KEY, KEY_SHUFFLE,
|
||||
EV_KEY, KEY_PREVIOUS,
|
||||
EV_KEY, KEY_VIDEOPHONE,
|
||||
EV_KEY, KEY_GAMES,
|
||||
EV_KEY, KEY_ZOOMIN,
|
||||
EV_KEY, KEY_ZOOMOUT,
|
||||
EV_KEY, KEY_ZOOMRESET,
|
||||
EV_KEY, KEY_WORDPROCESSOR,
|
||||
EV_KEY, KEY_EDITOR,
|
||||
EV_KEY, KEY_SPREADSHEET,
|
||||
EV_KEY, KEY_GRAPHICSEDITOR,
|
||||
EV_KEY, KEY_PRESENTATION,
|
||||
EV_KEY, KEY_DATABASE,
|
||||
EV_KEY, KEY_NEWS,
|
||||
EV_KEY, KEY_VOICEMAIL,
|
||||
EV_KEY, KEY_ADDRESSBOOK,
|
||||
EV_KEY, KEY_MESSENGER,
|
||||
EV_KEY, KEY_DISPLAYTOGGLE,
|
||||
EV_KEY, KEY_SPELLCHECK,
|
||||
EV_KEY, KEY_LOGOFF,
|
||||
EV_KEY, KEY_MEDIA_REPEAT,
|
||||
EV_KEY, KEY_IMAGES,
|
||||
EV_KEY, KEY_BUTTONCONFIG,
|
||||
EV_KEY, KEY_TASKMANAGER,
|
||||
EV_KEY, KEY_JOURNAL,
|
||||
EV_KEY, KEY_CONTROLPANEL,
|
||||
EV_KEY, KEY_APPSELECT,
|
||||
EV_KEY, KEY_SCREENSAVER,
|
||||
EV_KEY, KEY_VOICECOMMAND,
|
||||
EV_KEY, KEY_BRIGHTNESS_MIN,
|
||||
EV_KEY, KEY_BRIGHTNESS_MAX,
|
||||
EV_MSC, MSC_SCAN,
|
||||
-1 , -1,
|
||||
};
|
||||
|
||||
static struct input_absinfo absinfo[] = {
|
||||
{ ABS_VOLUME, 0, 572, 0, 0, 0 },
|
||||
{ ABS_MISC, 0, 255, 0, 0, 0 },
|
||||
{ 0x29, 0, 255, 0, 0, 0 },
|
||||
{ 0x2a, 0, 255, 0, 0, 0 },
|
||||
{ 0x2b, 0, 255, 0, 0, 0 },
|
||||
{ 0x2c, 0, 255, 0, 0, 0 },
|
||||
{ 0x2d, 0, 255, 0, 0, 0 },
|
||||
{ 0x2e, 0, 255, 0, 0, 0 },
|
||||
{ 0x2f, 0, 255, 0, 0, 0 },
|
||||
{ 0x30, 0, 255, 0, 0, 0 },
|
||||
{ 0x31, 0, 255, 0, 0, 0 },
|
||||
{ 0x32, 0, 255, 0, 0, 0 },
|
||||
{ 0x33, 0, 255, 0, 0, 0 },
|
||||
{ 0x34, 0, 255, 0, 0, 0 },
|
||||
{ 0x35, 0, 255, 0, 0, 0 },
|
||||
{ 0x36, 0, 255, 0, 0, 0 },
|
||||
{ 0x37, 0, 255, 0, 0, 0 },
|
||||
{ 0x38, 0, 255, 0, 0, 0 },
|
||||
{ 0x39, 0, 255, 0, 0, 0 },
|
||||
{ 0x3a, 0, 255, 0, 0, 0 },
|
||||
{ 0x3b, 0, 255, 0, 0, 0 },
|
||||
{ 0x3c, 0, 255, 0, 0, 0 },
|
||||
{ 0x3d, 0, 255, 0, 0, 0 },
|
||||
{ 0x3e, 0, 255, 0, 0, 0 },
|
||||
{ 0x3f, 0, 255, 0, 0, 0 },
|
||||
{ .value = -1 },
|
||||
};
|
||||
|
||||
struct litest_test_device litest_keyboard_blackwidow_device = {
|
||||
.type = LITEST_KEYBOARD_BLACKWIDOW,
|
||||
.features = LITEST_KEYS | LITEST_WHEEL,
|
||||
.shortname = "blackwidow",
|
||||
.setup = litest_blackwidow_setup,
|
||||
.interface = NULL,
|
||||
|
||||
.name = "Razer Razer BlackWidow 2013",
|
||||
.id = &input_id,
|
||||
.absinfo = absinfo,
|
||||
.events = events,
|
||||
};
|
||||
64
test/litest-logitech-trackball.c
Normal file
64
test/litest-logitech-trackball.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright © 2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
||||
static void litest_logitech_trackball_setup(void)
|
||||
{
|
||||
struct litest_device *d = litest_create_device(LITEST_LOGITECH_TRACKBALL);
|
||||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x3,
|
||||
.vendor = 0x46d,
|
||||
.product = 0xc408,
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
EV_KEY, BTN_MIDDLE,
|
||||
EV_KEY, BTN_SIDE,
|
||||
EV_KEY, BTN_EXTRA,
|
||||
EV_REL, REL_X,
|
||||
EV_REL, REL_Y,
|
||||
-1 , -1,
|
||||
};
|
||||
|
||||
struct litest_test_device litest_logitech_trackball_device = {
|
||||
.type = LITEST_LOGITECH_TRACKBALL,
|
||||
.features = LITEST_RELATIVE | LITEST_BUTTON,
|
||||
.shortname = "logitech trackball",
|
||||
.setup = litest_logitech_trackball_setup,
|
||||
.interface = NULL,
|
||||
|
||||
.name = "Logitech USB Trackball",
|
||||
.id = &input_id,
|
||||
.absinfo = NULL,
|
||||
.events = events,
|
||||
};
|
||||
205
test/litest-mouse-roccat.c
Normal file
205
test/litest-mouse-roccat.c
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* Copyright © 2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
||||
static void litest_mouse_roccat_setup(void)
|
||||
{
|
||||
struct litest_device *d = litest_create_device(LITEST_MOUSE_ROCCAT);
|
||||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x3,
|
||||
.vendor = 0x1e7d,
|
||||
.product = 0x2e22,
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
EV_REL, REL_X,
|
||||
EV_REL, REL_Y,
|
||||
EV_REL, REL_WHEEL,
|
||||
EV_REL, REL_HWHEEL,
|
||||
EV_REL, REL_DIAL,
|
||||
EV_KEY, KEY_ESC,
|
||||
EV_KEY, KEY_ENTER,
|
||||
EV_KEY, KEY_KPMINUS,
|
||||
EV_KEY, KEY_KPPLUS,
|
||||
EV_KEY, KEY_UP,
|
||||
EV_KEY, KEY_LEFT,
|
||||
EV_KEY, KEY_RIGHT,
|
||||
EV_KEY, KEY_DOWN,
|
||||
EV_KEY, KEY_MUTE,
|
||||
EV_KEY, KEY_VOLUMEDOWN,
|
||||
EV_KEY, KEY_VOLUMEUP,
|
||||
EV_KEY, KEY_POWER,
|
||||
EV_KEY, KEY_PAUSE,
|
||||
EV_KEY, KEY_STOP,
|
||||
EV_KEY, KEY_PROPS,
|
||||
EV_KEY, KEY_UNDO,
|
||||
EV_KEY, KEY_COPY,
|
||||
EV_KEY, KEY_OPEN,
|
||||
EV_KEY, KEY_PASTE,
|
||||
EV_KEY, KEY_FIND,
|
||||
EV_KEY, KEY_CUT,
|
||||
EV_KEY, KEY_HELP,
|
||||
EV_KEY, KEY_MENU,
|
||||
EV_KEY, KEY_CALC,
|
||||
EV_KEY, KEY_SLEEP,
|
||||
EV_KEY, KEY_FILE,
|
||||
EV_KEY, KEY_WWW,
|
||||
EV_KEY, KEY_COFFEE,
|
||||
EV_KEY, KEY_MAIL,
|
||||
EV_KEY, KEY_BOOKMARKS,
|
||||
EV_KEY, KEY_BACK,
|
||||
EV_KEY, KEY_FORWARD,
|
||||
EV_KEY, KEY_EJECTCD,
|
||||
EV_KEY, KEY_NEXTSONG,
|
||||
EV_KEY, KEY_PLAYPAUSE,
|
||||
EV_KEY, KEY_PREVIOUSSONG,
|
||||
EV_KEY, KEY_STOPCD,
|
||||
EV_KEY, KEY_RECORD,
|
||||
EV_KEY, KEY_REWIND,
|
||||
EV_KEY, KEY_PHONE,
|
||||
EV_KEY, KEY_CONFIG,
|
||||
EV_KEY, KEY_HOMEPAGE,
|
||||
EV_KEY, KEY_REFRESH,
|
||||
EV_KEY, KEY_EXIT,
|
||||
EV_KEY, KEY_SCROLLUP,
|
||||
EV_KEY, KEY_SCROLLDOWN,
|
||||
EV_KEY, KEY_NEW,
|
||||
EV_KEY, KEY_CLOSE,
|
||||
EV_KEY, KEY_PLAY,
|
||||
EV_KEY, KEY_FASTFORWARD,
|
||||
EV_KEY, KEY_BASSBOOST,
|
||||
EV_KEY, KEY_PRINT,
|
||||
EV_KEY, KEY_CAMERA,
|
||||
EV_KEY, KEY_CHAT,
|
||||
EV_KEY, KEY_SEARCH,
|
||||
EV_KEY, KEY_FINANCE,
|
||||
EV_KEY, KEY_BRIGHTNESSDOWN,
|
||||
EV_KEY, KEY_BRIGHTNESSUP,
|
||||
EV_KEY, KEY_KBDILLUMTOGGLE,
|
||||
EV_KEY, KEY_SAVE,
|
||||
EV_KEY, KEY_DOCUMENTS,
|
||||
EV_KEY, KEY_UNKNOWN,
|
||||
EV_KEY, KEY_VIDEO_NEXT,
|
||||
EV_KEY, KEY_BRIGHTNESS_AUTO,
|
||||
EV_KEY, BTN_0,
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
EV_KEY, BTN_MIDDLE,
|
||||
EV_KEY, BTN_SIDE,
|
||||
EV_KEY, BTN_EXTRA,
|
||||
EV_KEY, KEY_SELECT,
|
||||
EV_KEY, KEY_GOTO,
|
||||
EV_KEY, KEY_INFO,
|
||||
EV_KEY, KEY_PROGRAM,
|
||||
EV_KEY, KEY_PVR,
|
||||
EV_KEY, KEY_SUBTITLE,
|
||||
EV_KEY, KEY_ZOOM,
|
||||
EV_KEY, KEY_KEYBOARD,
|
||||
EV_KEY, KEY_PC,
|
||||
EV_KEY, KEY_TV,
|
||||
EV_KEY, KEY_TV2,
|
||||
EV_KEY, KEY_VCR,
|
||||
EV_KEY, KEY_VCR2,
|
||||
EV_KEY, KEY_SAT,
|
||||
EV_KEY, KEY_CD,
|
||||
EV_KEY, KEY_TAPE,
|
||||
EV_KEY, KEY_TUNER,
|
||||
EV_KEY, KEY_PLAYER,
|
||||
EV_KEY, KEY_DVD,
|
||||
EV_KEY, KEY_AUDIO,
|
||||
EV_KEY, KEY_VIDEO,
|
||||
EV_KEY, KEY_MEMO,
|
||||
EV_KEY, KEY_CALENDAR,
|
||||
EV_KEY, KEY_RED,
|
||||
EV_KEY, KEY_GREEN,
|
||||
EV_KEY, KEY_YELLOW,
|
||||
EV_KEY, KEY_BLUE,
|
||||
EV_KEY, KEY_CHANNELUP,
|
||||
EV_KEY, KEY_CHANNELDOWN,
|
||||
EV_KEY, KEY_LAST,
|
||||
EV_KEY, KEY_NEXT,
|
||||
EV_KEY, KEY_RESTART,
|
||||
EV_KEY, KEY_SLOW,
|
||||
EV_KEY, KEY_SHUFFLE,
|
||||
EV_KEY, KEY_PREVIOUS,
|
||||
EV_KEY, KEY_VIDEOPHONE,
|
||||
EV_KEY, KEY_GAMES,
|
||||
EV_KEY, KEY_ZOOMIN,
|
||||
EV_KEY, KEY_ZOOMOUT,
|
||||
EV_KEY, KEY_ZOOMRESET,
|
||||
EV_KEY, KEY_WORDPROCESSOR,
|
||||
EV_KEY, KEY_EDITOR,
|
||||
EV_KEY, KEY_SPREADSHEET,
|
||||
EV_KEY, KEY_GRAPHICSEDITOR,
|
||||
EV_KEY, KEY_PRESENTATION,
|
||||
EV_KEY, KEY_DATABASE,
|
||||
EV_KEY, KEY_NEWS,
|
||||
EV_KEY, KEY_VOICEMAIL,
|
||||
EV_KEY, KEY_ADDRESSBOOK,
|
||||
EV_KEY, KEY_MESSENGER,
|
||||
EV_KEY, KEY_DISPLAYTOGGLE,
|
||||
EV_KEY, KEY_SPELLCHECK,
|
||||
EV_KEY, KEY_LOGOFF,
|
||||
EV_KEY, KEY_MEDIA_REPEAT,
|
||||
EV_KEY, KEY_IMAGES,
|
||||
EV_KEY, KEY_BUTTONCONFIG,
|
||||
EV_KEY, KEY_TASKMANAGER,
|
||||
EV_KEY, KEY_JOURNAL,
|
||||
EV_KEY, KEY_CONTROLPANEL,
|
||||
EV_KEY, KEY_APPSELECT,
|
||||
EV_KEY, KEY_SCREENSAVER,
|
||||
EV_KEY, KEY_VOICECOMMAND,
|
||||
EV_KEY, KEY_BRIGHTNESS_MIN,
|
||||
EV_KEY, KEY_BRIGHTNESS_MAX,
|
||||
-1 , -1,
|
||||
};
|
||||
|
||||
static struct input_absinfo absinfo[] = {
|
||||
{ ABS_VOLUME, 0, 572, 0, 0, 0 },
|
||||
{ ABS_MISC, 0, 0, 0, 0, 0 },
|
||||
{ ABS_MISC + 1, 0, 0, 0, 0, 0 },
|
||||
{ ABS_MISC + 2, 0, 0, 0, 0, 0 },
|
||||
{ ABS_MISC + 3, 0, 0, 0, 0, 0 },
|
||||
{ .value = -1 }
|
||||
};
|
||||
|
||||
struct litest_test_device litest_mouse_roccat_device = {
|
||||
.type = LITEST_MOUSE_ROCCAT,
|
||||
.features = LITEST_RELATIVE | LITEST_BUTTON | LITEST_WHEEL | LITEST_KEYS,
|
||||
.shortname = "mouse_roccat",
|
||||
.setup = litest_mouse_roccat_setup,
|
||||
.interface = NULL,
|
||||
|
||||
.name = "ROCCAT ROCCAT Kone XTD",
|
||||
.id = &input_id,
|
||||
.absinfo = absinfo,
|
||||
.events = events,
|
||||
};
|
||||
|
|
@ -35,6 +35,8 @@ litest_ms_surface_cover_setup(void)
|
|||
}
|
||||
|
||||
static struct input_event down[] = {
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
||||
|
|
@ -59,6 +61,8 @@ static struct litest_device_interface interface = {
|
|||
};
|
||||
|
||||
static struct input_absinfo absinfo[] = {
|
||||
{ ABS_X, 0, 1022, 0, 0, 12 },
|
||||
{ ABS_Y, 0, 487, 0, 0, 12 },
|
||||
{ ABS_VOLUME, 0, 1023, 0, 0, 0 },
|
||||
{ ABS_MISC, 0, 255, 0, 0, 0 },
|
||||
{ 41, 0, 255, 0, 0, 0 },
|
||||
|
|
@ -90,7 +94,7 @@ static struct input_absinfo absinfo[] = {
|
|||
static struct input_id input_id = {
|
||||
.bustype = 0x3,
|
||||
.vendor = 0x45e,
|
||||
.product = 0x7a9,
|
||||
.product = 0x7dc,
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
|
|
@ -368,18 +372,17 @@ static int events[] = {
|
|||
EV_LED, LED_NUML,
|
||||
EV_LED, LED_CAPSL,
|
||||
EV_LED, LED_SCROLLL,
|
||||
EV_REP, REP_DELAY,
|
||||
-1, -1,
|
||||
};
|
||||
|
||||
struct litest_test_device litest_ms_surface_cover_device = {
|
||||
.type = LITEST_MS_SURFACE_COVER,
|
||||
.features = LITEST_KEYBOARD | LITEST_RELATIVE | LITEST_FAKE_MT,
|
||||
.features = LITEST_KEYS | LITEST_ABSOLUTE | LITEST_RELATIVE | LITEST_FAKE_MT | LITEST_BUTTON | LITEST_WHEEL,
|
||||
.shortname = "MS surface cover",
|
||||
.setup = litest_ms_surface_cover_setup,
|
||||
.interface = &interface,
|
||||
|
||||
.name = "MICROSOFT SAM",
|
||||
.name = "Microsoft Surface Type Cover",
|
||||
.id = &input_id,
|
||||
.events = events,
|
||||
.absinfo = absinfo,
|
||||
|
|
|
|||
369
test/litest-selftest.c
Normal file
369
test/litest-selftest.c
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
#include <config.h>
|
||||
|
||||
#include <check.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "litest.h"
|
||||
|
||||
START_TEST(litest_assert_trigger)
|
||||
{
|
||||
litest_assert(1 == 2);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_assert_notrigger)
|
||||
{
|
||||
litest_assert(1 == 1);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_assert_msg_trigger)
|
||||
{
|
||||
litest_assert_msg(1 == 2, "1 is not 2\n");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_assert_msg_NULL_trigger)
|
||||
{
|
||||
litest_assert_msg(1 == 2, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_assert_msg_notrigger)
|
||||
{
|
||||
litest_assert_msg(1 == 1, "1 is not 2\n");
|
||||
litest_assert_msg(1 == 1, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_abort_msg_trigger)
|
||||
{
|
||||
litest_abort_msg("message\n");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_abort_msg_NULL_trigger)
|
||||
{
|
||||
litest_abort_msg(NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_int_eq_trigger)
|
||||
{
|
||||
int a = 10;
|
||||
int b = 20;
|
||||
litest_assert_int_eq(a, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_int_eq_notrigger)
|
||||
{
|
||||
int a = 10;
|
||||
int b = 10;
|
||||
litest_assert_int_eq(a, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_int_ne_trigger)
|
||||
{
|
||||
int a = 10;
|
||||
int b = 10;
|
||||
litest_assert_int_ne(a, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_int_ne_notrigger)
|
||||
{
|
||||
int a = 10;
|
||||
int b = 20;
|
||||
litest_assert_int_ne(a, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_int_lt_trigger_eq)
|
||||
{
|
||||
int a = 10;
|
||||
int b = 10;
|
||||
litest_assert_int_lt(a, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_int_lt_trigger_gt)
|
||||
{
|
||||
int a = 11;
|
||||
int b = 10;
|
||||
litest_assert_int_lt(a, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_int_lt_notrigger)
|
||||
{
|
||||
int a = 10;
|
||||
int b = 11;
|
||||
litest_assert_int_lt(a, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_int_le_trigger)
|
||||
{
|
||||
int a = 11;
|
||||
int b = 10;
|
||||
litest_assert_int_le(a, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_int_le_notrigger)
|
||||
{
|
||||
int a = 10;
|
||||
int b = 11;
|
||||
int c = 10;
|
||||
litest_assert_int_le(a, b);
|
||||
litest_assert_int_le(a, c);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_int_gt_trigger_eq)
|
||||
{
|
||||
int a = 10;
|
||||
int b = 10;
|
||||
litest_assert_int_gt(a, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_int_gt_trigger_lt)
|
||||
{
|
||||
int a = 9;
|
||||
int b = 10;
|
||||
litest_assert_int_gt(a, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_int_gt_notrigger)
|
||||
{
|
||||
int a = 10;
|
||||
int b = 9;
|
||||
litest_assert_int_gt(a, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_int_ge_trigger)
|
||||
{
|
||||
int a = 9;
|
||||
int b = 10;
|
||||
litest_assert_int_ge(a, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_int_ge_notrigger)
|
||||
{
|
||||
int a = 10;
|
||||
int b = 9;
|
||||
int c = 10;
|
||||
litest_assert_int_ge(a, b);
|
||||
litest_assert_int_ge(a, c);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_ptr_eq_notrigger)
|
||||
{
|
||||
int v = 10;
|
||||
int *a = &v;
|
||||
int *b = &v;
|
||||
int c = NULL;
|
||||
int d = NULL;
|
||||
|
||||
litest_assert_ptr_eq(a, b);
|
||||
litest_assert_ptr_eq(c, d);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_ptr_eq_trigger)
|
||||
{
|
||||
int v = 10;
|
||||
int v2 = 11;
|
||||
int *a = &v;
|
||||
int *b = &v2;
|
||||
|
||||
litest_assert_ptr_eq(a, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_ptr_eq_trigger_NULL)
|
||||
{
|
||||
int v = 10;
|
||||
int *a = &v;
|
||||
int *b = NULL;
|
||||
|
||||
litest_assert_ptr_eq(a, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_ptr_eq_trigger_NULL2)
|
||||
{
|
||||
int v = 10;
|
||||
int *a = &v;
|
||||
int *b = NULL;
|
||||
|
||||
litest_assert_ptr_eq(b, a);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_ptr_ne_trigger)
|
||||
{
|
||||
int v = 10;
|
||||
int *a = &v;
|
||||
int *b = &v;
|
||||
|
||||
litest_assert_ptr_ne(a, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_ptr_ne_trigger_NULL)
|
||||
{
|
||||
int *a = NULL;
|
||||
|
||||
litest_assert_ptr_ne(a, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_ptr_ne_trigger_NULL2)
|
||||
{
|
||||
int *a = NULL;
|
||||
|
||||
litest_assert_ptr_ne(NULL, a);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_ptr_ne_notrigger)
|
||||
{
|
||||
int v1 = 10;
|
||||
int v2 = 10;
|
||||
int *a = &v1;
|
||||
int *b = &v2;
|
||||
int *c = NULL;
|
||||
|
||||
litest_assert_ptr_ne(a, b);
|
||||
litest_assert_ptr_ne(a, c);
|
||||
litest_assert_ptr_ne(c, b);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_ptr_null_notrigger)
|
||||
{
|
||||
int *a = NULL;
|
||||
|
||||
litest_assert_ptr_null(a);
|
||||
litest_assert_ptr_null(NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_ptr_null_trigger)
|
||||
{
|
||||
int v;
|
||||
int *a = &v;
|
||||
|
||||
litest_assert_ptr_null(a);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_ptr_notnull_notrigger)
|
||||
{
|
||||
int v;
|
||||
int *a = &v;
|
||||
|
||||
litest_assert_ptr_notnull(a);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_ptr_notnull_trigger)
|
||||
{
|
||||
int *a = NULL;
|
||||
|
||||
litest_assert_ptr_notnull(a);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(litest_ptr_notnull_trigger_NULL)
|
||||
{
|
||||
litest_assert_ptr_notnull(NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Suite *
|
||||
litest_assert_macros_suite(void)
|
||||
{
|
||||
TCase *tc;
|
||||
Suite *s;
|
||||
|
||||
s = suite_create("litest:assert macros");
|
||||
tc = tcase_create("assert");
|
||||
tcase_add_test_raise_signal(tc, litest_assert_trigger, SIGABRT);
|
||||
tcase_add_test(tc, litest_assert_notrigger);
|
||||
tcase_add_test_raise_signal(tc, litest_assert_msg_trigger, SIGABRT);
|
||||
tcase_add_test_raise_signal(tc, litest_assert_msg_NULL_trigger, SIGABRT);
|
||||
tcase_add_test(tc, litest_assert_msg_notrigger);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("abort");
|
||||
tcase_add_test_raise_signal(tc, litest_abort_msg_trigger, SIGABRT);
|
||||
tcase_add_test_raise_signal(tc, litest_abort_msg_NULL_trigger, SIGABRT);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("int comparison ");
|
||||
tcase_add_test_raise_signal(tc, litest_int_eq_trigger, SIGABRT);
|
||||
tcase_add_test(tc, litest_int_eq_notrigger);
|
||||
tcase_add_test_raise_signal(tc, litest_int_ne_trigger, SIGABRT);
|
||||
tcase_add_test(tc, litest_int_ne_notrigger);
|
||||
tcase_add_test_raise_signal(tc, litest_int_le_trigger, SIGABRT);
|
||||
tcase_add_test(tc, litest_int_le_notrigger);
|
||||
tcase_add_test_raise_signal(tc, litest_int_lt_trigger_gt, SIGABRT);
|
||||
tcase_add_test_raise_signal(tc, litest_int_lt_trigger_eq, SIGABRT);
|
||||
tcase_add_test(tc, litest_int_lt_notrigger);
|
||||
tcase_add_test_raise_signal(tc, litest_int_ge_trigger, SIGABRT);
|
||||
tcase_add_test(tc, litest_int_ge_notrigger);
|
||||
tcase_add_test_raise_signal(tc, litest_int_gt_trigger_eq, SIGABRT);
|
||||
tcase_add_test_raise_signal(tc, litest_int_gt_trigger_lt, SIGABRT);
|
||||
tcase_add_test(tc, litest_int_gt_notrigger);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("pointer comparison ");
|
||||
tcase_add_test_raise_signal(tc, litest_ptr_eq_trigger, SIGABRT);
|
||||
tcase_add_test_raise_signal(tc, litest_ptr_eq_trigger_NULL, SIGABRT);
|
||||
tcase_add_test_raise_signal(tc, litest_ptr_eq_trigger_NULL2, SIGABRT);
|
||||
tcase_add_test(tc, litest_ptr_eq_notrigger);
|
||||
tcase_add_test_raise_signal(tc, litest_ptr_ne_trigger, SIGABRT);
|
||||
tcase_add_test_raise_signal(tc, litest_ptr_ne_trigger_NULL, SIGABRT);
|
||||
tcase_add_test_raise_signal(tc, litest_ptr_ne_trigger_NULL2, SIGABRT);
|
||||
tcase_add_test(tc, litest_ptr_ne_notrigger);
|
||||
tcase_add_test_raise_signal(tc, litest_ptr_null_trigger, SIGABRT);
|
||||
tcase_add_test(tc, litest_ptr_null_notrigger);
|
||||
tcase_add_test_raise_signal(tc, litest_ptr_notnull_trigger, SIGABRT);
|
||||
tcase_add_test_raise_signal(tc, litest_ptr_notnull_trigger_NULL, SIGABRT);
|
||||
tcase_add_test(tc, litest_ptr_notnull_notrigger);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int nfailed;
|
||||
Suite *s;
|
||||
SRunner *sr;
|
||||
|
||||
/* when running under valgrind we're using nofork mode, so a signal
|
||||
* raised by a test will fail in valgrind. There's nothing to
|
||||
* memcheck here anyway, so just skip the valgrind test */
|
||||
if (getenv("USING_VALGRIND"))
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
s = litest_assert_macros_suite();
|
||||
sr = srunner_create(s);
|
||||
|
||||
srunner_run_all(sr, CK_ENV);
|
||||
nfailed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
|
||||
return (nfailed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
68
test/litest-wheel-only.c
Normal file
68
test/litest-wheel-only.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright © 2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
||||
static void litest_wheel_only_setup(void)
|
||||
{
|
||||
struct litest_device *d = litest_create_device(LITEST_WHEEL_ONLY);
|
||||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x3,
|
||||
.vendor = 0x1,
|
||||
.product = 0x2,
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
EV_REL, REL_WHEEL,
|
||||
-1 , -1,
|
||||
};
|
||||
|
||||
static const char udev_rule[] =
|
||||
"ACTION==\"remove\", GOTO=\"wheel_only_end\"\n"
|
||||
"KERNEL!=\"event*\", GOTO=\"wheel_only_end\"\n"
|
||||
"\n"
|
||||
"ATTRS{name}==\"litest wheel only device*\",\\\n"
|
||||
" ENV{ID_INPUT_KEY}=\"1\"\n"
|
||||
"\n"
|
||||
"LABEL=\"wheel_only_end\"";
|
||||
|
||||
struct litest_test_device litest_wheel_only_device = {
|
||||
.type = LITEST_WHEEL_ONLY,
|
||||
.features = LITEST_WHEEL,
|
||||
.shortname = "wheel only",
|
||||
.setup = litest_wheel_only_setup,
|
||||
.interface = NULL,
|
||||
|
||||
.name = "wheel only device",
|
||||
.id = &input_id,
|
||||
.absinfo = NULL,
|
||||
.events = events,
|
||||
.udev_rule = udev_rule,
|
||||
};
|
||||
947
test/litest.c
947
test/litest.c
File diff suppressed because it is too large
Load diff
215
test/litest.h
215
test/litest.h
|
|
@ -32,6 +32,83 @@
|
|||
#include <libevdev/libevdev.h>
|
||||
#include <libevdev/libevdev-uinput.h>
|
||||
#include <libinput.h>
|
||||
#include <math.h>
|
||||
|
||||
#define litest_assert(cond) \
|
||||
do { \
|
||||
if (!(cond)) \
|
||||
litest_fail_condition(__FILE__, __LINE__, __func__, \
|
||||
#cond, NULL); \
|
||||
} while(0)
|
||||
|
||||
#define litest_assert_msg(cond, ...) \
|
||||
do { \
|
||||
if (!(cond)) \
|
||||
litest_fail_condition(__FILE__, __LINE__, __func__, \
|
||||
#cond, __VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define litest_abort_msg(...) \
|
||||
litest_fail_condition(__FILE__, __LINE__, __func__, \
|
||||
"aborting", __VA_ARGS__); \
|
||||
|
||||
#define litest_assert_notnull(cond) \
|
||||
do { \
|
||||
if ((cond) == NULL) \
|
||||
litest_fail_condition(__FILE__, __LINE__, __func__, \
|
||||
#cond, " expected to be not NULL\n"); \
|
||||
} while(0)
|
||||
|
||||
#define litest_assert_comparison_int_(a_, op_, b_) \
|
||||
do { \
|
||||
__typeof__(a_) _a = a_; \
|
||||
__typeof__(b_) _b = b_; \
|
||||
if (trunc(_a) != _a || trunc(_b) != _b) \
|
||||
litest_abort_msg("litest_assert_int_* used for non-integer value\n"); \
|
||||
if (!((_a) op_ (_b))) \
|
||||
litest_fail_comparison_int(__FILE__, __LINE__, __func__,\
|
||||
#op_, _a, _b, \
|
||||
#a_, #b_); \
|
||||
} while(0)
|
||||
|
||||
#define litest_assert_int_eq(a_, b_) \
|
||||
litest_assert_comparison_int_(a_, ==, b_)
|
||||
|
||||
#define litest_assert_int_ne(a_, b_) \
|
||||
litest_assert_comparison_int_(a_, !=, b_)
|
||||
|
||||
#define litest_assert_int_lt(a_, b_) \
|
||||
litest_assert_comparison_int_(a_, <, b_)
|
||||
|
||||
#define litest_assert_int_le(a_, b_) \
|
||||
litest_assert_comparison_int_(a_, <=, b_)
|
||||
|
||||
#define litest_assert_int_ge(a_, b_) \
|
||||
litest_assert_comparison_int_(a_, >=, b_)
|
||||
|
||||
#define litest_assert_int_gt(a_, b_) \
|
||||
litest_assert_comparison_int_(a_, >, b_)
|
||||
|
||||
#define litest_assert_comparison_ptr_(a_, op_, b_) \
|
||||
do { \
|
||||
__typeof__(a_) _a = a_; \
|
||||
__typeof__(b_) _b = b_; \
|
||||
if (!((_a) op_ (_b))) \
|
||||
litest_fail_comparison_ptr(__FILE__, __LINE__, __func__,\
|
||||
#a_ " " #op_ " " #b_); \
|
||||
} while(0)
|
||||
|
||||
#define litest_assert_ptr_eq(a_, b_) \
|
||||
litest_assert_comparison_ptr_(a_, ==, b_)
|
||||
|
||||
#define litest_assert_ptr_ne(a_, b_) \
|
||||
litest_assert_comparison_ptr_(a_, !=, b_)
|
||||
|
||||
#define litest_assert_ptr_null(a_) \
|
||||
litest_assert_comparison_ptr_(a_, ==, NULL)
|
||||
|
||||
#define litest_assert_ptr_notnull(a_) \
|
||||
litest_assert_comparison_ptr_(a_, !=, NULL)
|
||||
|
||||
enum litest_device_type {
|
||||
LITEST_NO_DEVICE = -1,
|
||||
|
|
@ -53,10 +130,15 @@ enum litest_device_type {
|
|||
LITEST_SYNAPTICS_TRACKPOINT_BUTTONS = -17,
|
||||
LITEST_PROTOCOL_A_SCREEN = -18,
|
||||
LITEST_WACOM_FINGER = -19,
|
||||
LITEST_WACOM_BAMBOO = -20,
|
||||
LITEST_WACOM_CINTIQ = -21,
|
||||
LITEST_WACOM_INTUOS = -22,
|
||||
LITEST_WACOM_ISDV4 = -23,
|
||||
LITEST_KEYBOARD_BLACKWIDOW = -20,
|
||||
LITEST_WHEEL_ONLY = -21,
|
||||
LITEST_MOUSE_ROCCAT = -22,
|
||||
LITEST_LOGITECH_TRACKBALL = -23,
|
||||
LITEST_ATMEL_HOVER = -24,
|
||||
LITEST_WACOM_BAMBOO = -25,
|
||||
LITEST_WACOM_CINTIQ = -26,
|
||||
LITEST_WACOM_INTUOS = -27,
|
||||
LITEST_WACOM_ISDV4 = -28,
|
||||
};
|
||||
|
||||
enum litest_device_feature {
|
||||
|
|
@ -77,9 +159,10 @@ enum litest_device_feature {
|
|||
LITEST_FAKE_MT = 1 << 12,
|
||||
LITEST_ABSOLUTE = 1 << 13,
|
||||
LITEST_PROTOCOL_A = 1 << 14,
|
||||
LITEST_TABLET = 1 << 15,
|
||||
LITEST_DISTANCE = 1 << 16,
|
||||
LITEST_TOOL_SERIAL = 1 << 17,
|
||||
LITEST_HOVER = 1 << 15,
|
||||
LITEST_TABLET = 1 << 16,
|
||||
LITEST_DISTANCE = 1 << 17,
|
||||
LITEST_TOOL_SERIAL = 1 << 18,
|
||||
};
|
||||
|
||||
struct litest_device {
|
||||
|
|
@ -103,20 +186,81 @@ struct axis_replacement {
|
|||
int32_t value;
|
||||
};
|
||||
|
||||
/* A loop range, resolves to:
|
||||
for (i = lower; i < upper; i++)
|
||||
*/
|
||||
struct range {
|
||||
int lower; /* inclusive */
|
||||
int upper; /* exclusive */
|
||||
};
|
||||
|
||||
struct libinput *litest_create_context(void);
|
||||
void litest_disable_log_handler(struct libinput *libinput);
|
||||
void litest_restore_log_handler(struct libinput *libinput);
|
||||
|
||||
void litest_add(const char *name, void *func,
|
||||
enum litest_device_feature required_feature,
|
||||
enum litest_device_feature excluded_feature);
|
||||
void
|
||||
litest_add_for_device(const char *name,
|
||||
void *func,
|
||||
enum litest_device_type type);
|
||||
void litest_add_no_device(const char *name, void *func);
|
||||
litest_fail_condition(const char *file,
|
||||
int line,
|
||||
const char *func,
|
||||
const char *condition,
|
||||
const char *message,
|
||||
...);
|
||||
void
|
||||
litest_fail_comparison_int(const char *file,
|
||||
int line,
|
||||
const char *func,
|
||||
const char *operator,
|
||||
int a,
|
||||
int b,
|
||||
const char *astr,
|
||||
const char *bstr);
|
||||
void
|
||||
litest_fail_comparison_ptr(const char *file,
|
||||
int line,
|
||||
const char *func,
|
||||
const char *comparison);
|
||||
|
||||
int litest_run(int argc, char **argv);
|
||||
#define litest_add(name_, func_, ...) \
|
||||
_litest_add(name_, #func_, func_, __VA_ARGS__)
|
||||
#define litest_add_ranged(name_, func_, ...) \
|
||||
_litest_add_ranged(name_, #func_, func_, __VA_ARGS__)
|
||||
#define litest_add_for_device(name_, func_, ...) \
|
||||
_litest_add_for_device(name_, #func_, func_, __VA_ARGS__)
|
||||
#define litest_add_ranged_for_device(name_, func_, ...) \
|
||||
_litest_add_ranged_for_device(name_, #func_, func_, __VA_ARGS__)
|
||||
#define litest_add_no_device(name_, func_) \
|
||||
_litest_add_no_device(name_, #func_, func_)
|
||||
#define litest_add_ranged_no_device(name_, func_, ...) \
|
||||
_litest_add_ranged_no_device(name_, #func_, func_, __VA_ARGS__)
|
||||
void _litest_add(const char *name,
|
||||
const char *funcname,
|
||||
void *func,
|
||||
enum litest_device_feature required_feature,
|
||||
enum litest_device_feature excluded_feature);
|
||||
void _litest_add_ranged(const char *name,
|
||||
const char *funcname,
|
||||
void *func,
|
||||
enum litest_device_feature required,
|
||||
enum litest_device_feature excluded,
|
||||
const struct range *range);
|
||||
void _litest_add_for_device(const char *name,
|
||||
const char *funcname,
|
||||
void *func,
|
||||
enum litest_device_type type);
|
||||
void _litest_add_ranged_for_device(const char *name,
|
||||
const char *funcname,
|
||||
void *func,
|
||||
enum litest_device_type type,
|
||||
const struct range *range);
|
||||
void _litest_add_no_device(const char *name,
|
||||
const char *funcname,
|
||||
void *func);
|
||||
void _litest_add_ranged_no_device(const char *name,
|
||||
const char *funcname,
|
||||
void *func,
|
||||
const struct range *range);
|
||||
|
||||
extern void litest_setup_tests(void);
|
||||
struct litest_device * litest_create_device(enum litest_device_type which);
|
||||
struct litest_device * litest_add_device(struct libinput *libinput,
|
||||
enum litest_device_type which);
|
||||
|
|
@ -149,7 +293,8 @@ void litest_event(struct litest_device *t,
|
|||
int value);
|
||||
int litest_auto_assign_value(struct litest_device *d,
|
||||
const struct input_event *ev,
|
||||
int slot, double x, double y);
|
||||
int slot, double x, double y,
|
||||
bool touching);
|
||||
void litest_touch_up(struct litest_device *d, unsigned int slot);
|
||||
void litest_touch_move(struct litest_device *d,
|
||||
unsigned int slot,
|
||||
|
|
@ -178,6 +323,25 @@ void litest_tablet_motion(struct litest_device *d,
|
|||
int x, int y,
|
||||
struct axis_replacement *axes);
|
||||
|
||||
void litest_hover_start(struct litest_device *d,
|
||||
unsigned int slot,
|
||||
double x,
|
||||
double y);
|
||||
void litest_hover_end(struct litest_device *d, unsigned int slot);
|
||||
void litest_hover_move(struct litest_device *d,
|
||||
unsigned int slot,
|
||||
double x,
|
||||
double y);
|
||||
void litest_hover_move_to(struct litest_device *d,
|
||||
unsigned int slot,
|
||||
double x_from, double y_from,
|
||||
double x_to, double y_to,
|
||||
int steps, int sleep_ms);
|
||||
void litest_hover_move_two_touches(struct litest_device *d,
|
||||
double x0, double y0,
|
||||
double x1, double y1,
|
||||
double dx, double dy,
|
||||
int steps, int sleep_ms);
|
||||
void litest_button_click(struct litest_device *d,
|
||||
unsigned int button,
|
||||
bool is_press);
|
||||
|
|
@ -191,6 +355,23 @@ void litest_wait_for_event(struct libinput *li);
|
|||
void litest_wait_for_event_of_type(struct libinput *li, ...);
|
||||
void litest_drain_events(struct libinput *li);
|
||||
void litest_assert_empty_queue(struct libinput *li);
|
||||
struct libinput_event_pointer * litest_is_button_event(
|
||||
struct libinput_event *event,
|
||||
unsigned int button,
|
||||
enum libinput_button_state state);
|
||||
struct libinput_event_pointer * litest_is_axis_event(
|
||||
struct libinput_event *event,
|
||||
enum libinput_pointer_axis axis,
|
||||
enum libinput_pointer_axis_source source);
|
||||
struct libinput_event_pointer * litest_is_motion_event(
|
||||
struct libinput_event *event);
|
||||
struct libinput_event_touch * litest_is_touch_event(
|
||||
struct libinput_event *event,
|
||||
enum libinput_event_type type);
|
||||
struct libinput_event_keyboard * litest_is_keyboard_event(
|
||||
struct libinput_event *event,
|
||||
unsigned int key,
|
||||
enum libinput_key_state state);
|
||||
void litest_assert_button_event(struct libinput *li,
|
||||
unsigned int button,
|
||||
enum libinput_button_state state);
|
||||
|
|
@ -229,10 +410,12 @@ struct libevdev_uinput * litest_create_uinput_abs_device(const char *name,
|
|||
ck_assert_int_ge((int)((a_) * 256), (int)((b_) * 256))
|
||||
|
||||
void litest_timeout_tap(void);
|
||||
void litest_timeout_tapndrag(void);
|
||||
void litest_timeout_softbuttons(void);
|
||||
void litest_timeout_buttonscroll(void);
|
||||
void litest_timeout_edgescroll(void);
|
||||
void litest_timeout_finger_switch(void);
|
||||
void litest_timeout_middlebutton(void);
|
||||
|
||||
void litest_push_event_frame(struct litest_device *dev);
|
||||
void litest_pop_event_frame(struct litest_device *dev);
|
||||
|
|
|
|||
11
test/log.c
11
test/log.c
|
|
@ -26,7 +26,6 @@
|
|||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libinput.h>
|
||||
#include <libudev.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "litest.h"
|
||||
|
|
@ -58,8 +57,8 @@ simple_log_handler(struct libinput *libinput,
|
|||
{
|
||||
log_handler_called++;
|
||||
if (log_handler_context)
|
||||
ck_assert(libinput == log_handler_context);
|
||||
ck_assert(format != NULL);
|
||||
litest_assert_ptr_eq(libinput, log_handler_context);
|
||||
litest_assert_notnull(format);
|
||||
}
|
||||
|
||||
START_TEST(log_default_priority)
|
||||
|
|
@ -140,11 +139,11 @@ START_TEST(log_priority)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
void
|
||||
litest_setup_tests(void)
|
||||
{
|
||||
litest_add_no_device("log:defaults", log_default_priority);
|
||||
litest_add_no_device("log:logging", log_handler_invoked);
|
||||
litest_add_no_device("log:logging", log_handler_NULL);
|
||||
litest_add_no_device("log:logging", log_priority);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
37
test/misc.c
37
test/misc.c
|
|
@ -65,7 +65,7 @@ create_simple_test_device(const char *name, ...)
|
|||
};
|
||||
|
||||
evdev = libevdev_new();
|
||||
ck_assert(evdev != NULL);
|
||||
litest_assert_notnull(evdev);
|
||||
libevdev_set_name(evdev, name);
|
||||
|
||||
va_start(args, name);
|
||||
|
|
@ -83,7 +83,7 @@ create_simple_test_device(const char *name, ...)
|
|||
rc = libevdev_uinput_create_from_device(evdev,
|
||||
LIBEVDEV_UINPUT_OPEN_MANAGED,
|
||||
&uinput);
|
||||
ck_assert_int_eq(rc, 0);
|
||||
litest_assert_int_eq(rc, 0);
|
||||
libevdev_free(evdev);
|
||||
|
||||
return uinput;
|
||||
|
|
@ -595,7 +595,35 @@ START_TEST(wheel_click_parser)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
struct parser_test_float {
|
||||
char *tag;
|
||||
double expected_value;
|
||||
};
|
||||
|
||||
START_TEST(trackpoint_accel_parser)
|
||||
{
|
||||
struct parser_test_float tests[] = {
|
||||
{ "0.5", 0.5 },
|
||||
{ "1.0", 1.0 },
|
||||
{ "2.0", 2.0 },
|
||||
{ "fail1.0", 0.0 },
|
||||
{ "1.0fail", 0.0 },
|
||||
{ "0,5", 0.0 },
|
||||
{ NULL, 0.0 }
|
||||
};
|
||||
int i;
|
||||
double accel;
|
||||
|
||||
for (i = 0; tests[i].tag != NULL; i++) {
|
||||
accel = parse_trackpoint_accel_property(tests[i].tag);
|
||||
ck_assert(accel == tests[i].expected_value);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
litest_setup_tests(void)
|
||||
{
|
||||
litest_add_no_device("events:conversion", event_conversion_device_notify);
|
||||
litest_add_for_device("events:conversion", event_conversion_pointer, LITEST_MOUSE);
|
||||
litest_add_for_device("events:conversion", event_conversion_pointer, LITEST_MOUSE);
|
||||
|
|
@ -611,6 +639,5 @@ int main (int argc, char **argv) {
|
|||
litest_add_no_device("misc:ratelimit", ratelimit_helpers);
|
||||
litest_add_no_device("misc:dpi parser", dpi_parser);
|
||||
litest_add_no_device("misc:wheel click parser", wheel_click_parser);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
litest_add_no_device("misc:trackpoint accel parser", trackpoint_accel_parser);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libinput.h>
|
||||
#include <libudev.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "litest.h"
|
||||
|
|
@ -875,8 +874,8 @@ START_TEST(path_seat_recycle)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
void
|
||||
litest_setup_tests(void)
|
||||
{
|
||||
litest_add_no_device("path:create", path_create_NULL);
|
||||
litest_add_no_device("path:create", path_create_invalid);
|
||||
|
|
@ -897,6 +896,4 @@ main(int argc, char **argv)
|
|||
litest_add_for_device("path:device events", path_remove_device, LITEST_SYNAPTICS_CLICKPAD);
|
||||
litest_add_for_device("path:device events", path_double_remove_device, LITEST_SYNAPTICS_CLICKPAD);
|
||||
litest_add_no_device("path:seat", path_seat_recycle);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
579
test/pointer.c
579
test/pointer.c
|
|
@ -42,12 +42,7 @@ get_accelerated_motion_event(struct libinput *li)
|
|||
|
||||
while (1) {
|
||||
event = libinput_get_event(li);
|
||||
ck_assert_notnull(event);
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
ck_assert_notnull(ptrev);
|
||||
ptrev = litest_is_motion_event(event);
|
||||
|
||||
if (fabs(libinput_event_pointer_get_dx(ptrev)) < DBL_MIN &&
|
||||
fabs(libinput_event_pointer_get_dy(ptrev)) < DBL_MIN) {
|
||||
|
|
@ -58,7 +53,7 @@ get_accelerated_motion_event(struct libinput *li)
|
|||
return ptrev;
|
||||
}
|
||||
|
||||
ck_abort_msg("No accelerated pointer motion event found");
|
||||
litest_abort_msg("No accelerated pointer motion event found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -95,17 +90,31 @@ test_relative_event(struct litest_device *dev, int dx, int dy)
|
|||
actual_dir = atan2(ev_dx, ev_dy);
|
||||
|
||||
/* Check the length of the motion vector (tolerate 1.0 indifference). */
|
||||
ck_assert(fabs(expected_length) >= actual_length);
|
||||
litest_assert(fabs(expected_length) >= actual_length);
|
||||
|
||||
/* Check the direction of the motion vector (tolerate 2π/4 radians
|
||||
* indifference). */
|
||||
ck_assert(fabs(expected_dir - actual_dir) < M_PI_2);
|
||||
litest_assert(fabs(expected_dir - actual_dir) < M_PI_2);
|
||||
|
||||
libinput_event_destroy(libinput_event_pointer_get_base_event(ptrev));
|
||||
|
||||
litest_drain_events(dev->libinput);
|
||||
}
|
||||
|
||||
static void
|
||||
disable_button_scrolling(struct litest_device *device)
|
||||
{
|
||||
struct libinput_device *dev = device->libinput_device;
|
||||
enum libinput_config_status status,
|
||||
expected;
|
||||
|
||||
status = libinput_device_config_scroll_set_method(dev,
|
||||
LIBINPUT_CONFIG_SCROLL_NO_SCROLL);
|
||||
|
||||
expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
litest_assert_int_eq(status, expected);
|
||||
}
|
||||
|
||||
START_TEST(pointer_motion_relative)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -131,21 +140,22 @@ test_absolute_event(struct litest_device *dev, double x, double y)
|
|||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
double ex, ey;
|
||||
enum libinput_event_type type = LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE;
|
||||
|
||||
litest_touch_down(dev, 0, x, y);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE);
|
||||
litest_assert_notnull(event);
|
||||
litest_assert_int_eq(libinput_event_get_type(event), type);
|
||||
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
ck_assert(ptrev != NULL);
|
||||
litest_assert(ptrev != NULL);
|
||||
|
||||
ex = libinput_event_pointer_get_absolute_x_transformed(ptrev, 100);
|
||||
ey = libinput_event_pointer_get_absolute_y_transformed(ptrev, 100);
|
||||
ck_assert_int_eq(ex + 0.5, x);
|
||||
ck_assert_int_eq(ey + 0.5, y);
|
||||
litest_assert_int_eq((int)(ex + 0.5), (int)x);
|
||||
litest_assert_int_eq((int)(ey + 0.5), (int)y);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
|
@ -162,6 +172,61 @@ START_TEST(pointer_motion_absolute)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_absolute_initial_state)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *libinput1, *libinput2;
|
||||
struct libinput_event *ev1, *ev2;
|
||||
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);
|
||||
|
||||
/* device is now on some x/y value */
|
||||
litest_drain_events(libinput1);
|
||||
|
||||
libinput2 = litest_create_context();
|
||||
libinput_path_add_device(libinput2,
|
||||
libevdev_uinput_get_devnode(dev->uinput));
|
||||
litest_drain_events(libinput2);
|
||||
|
||||
if (axis == ABS_X)
|
||||
litest_touch_down(dev, 0, 40, 70);
|
||||
else
|
||||
litest_touch_down(dev, 0, 70, 60);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_wait_for_event(libinput1);
|
||||
litest_wait_for_event(libinput2);
|
||||
|
||||
while (libinput_next_event_type(libinput1)) {
|
||||
ev1 = libinput_get_event(libinput1);
|
||||
ev2 = libinput_get_event(libinput2);
|
||||
|
||||
ck_assert_int_eq(libinput_event_get_type(ev1),
|
||||
LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE);
|
||||
ck_assert_int_eq(libinput_event_get_type(ev1),
|
||||
libinput_event_get_type(ev2));
|
||||
|
||||
p1 = libinput_event_get_pointer_event(ev1);
|
||||
p2 = libinput_event_get_pointer_event(ev2);
|
||||
|
||||
ck_assert_int_eq(libinput_event_pointer_get_absolute_x(p1),
|
||||
libinput_event_pointer_get_absolute_x(p2));
|
||||
ck_assert_int_eq(libinput_event_pointer_get_absolute_y(p1),
|
||||
libinput_event_pointer_get_absolute_y(p2));
|
||||
|
||||
libinput_event_destroy(ev1);
|
||||
libinput_event_destroy(ev2);
|
||||
}
|
||||
|
||||
libinput_unref(libinput2);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void
|
||||
test_unaccel_event(struct litest_device *dev, int dx, int dy)
|
||||
{
|
||||
|
|
@ -177,18 +242,13 @@ test_unaccel_event(struct litest_device *dev, int dx, int dy)
|
|||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert_notnull(event);
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
ck_assert(ptrev != NULL);
|
||||
ptrev = litest_is_motion_event(event);
|
||||
|
||||
ev_dx = libinput_event_pointer_get_dx_unaccelerated(ptrev);
|
||||
ev_dy = libinput_event_pointer_get_dy_unaccelerated(ptrev);
|
||||
|
||||
ck_assert_int_eq(dx, ev_dx);
|
||||
ck_assert_int_eq(dy, ev_dy);
|
||||
litest_assert_int_eq(dx, ev_dx);
|
||||
litest_assert_int_eq(dy, ev_dy);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
|
||||
|
|
@ -230,6 +290,8 @@ START_TEST(pointer_button)
|
|||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
||||
disable_button_scrolling(dev);
|
||||
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
test_button_event(dev, BTN_LEFT, 1);
|
||||
|
|
@ -245,8 +307,7 @@ START_TEST(pointer_button)
|
|||
}
|
||||
|
||||
/* Skip middle button test on trackpoints (used for scrolling) */
|
||||
if (!libevdev_has_property(dev->evdev, INPUT_PROP_POINTING_STICK) &&
|
||||
libevdev_has_event_code(dev->evdev, EV_KEY, BTN_MIDDLE)) {
|
||||
if (libevdev_has_event_code(dev->evdev, EV_KEY, BTN_MIDDLE)) {
|
||||
test_button_event(dev, BTN_MIDDLE, 1);
|
||||
test_button_event(dev, BTN_MIDDLE, 0);
|
||||
}
|
||||
|
|
@ -369,24 +430,18 @@ test_wheel_event(struct litest_device *dev, int which, int amount)
|
|||
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert(event != NULL);
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
ck_assert(ptrev != NULL);
|
||||
|
||||
axis = (which == REL_WHEEL) ?
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL :
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
|
||||
event = libinput_get_event(li);
|
||||
ptrev = litest_is_axis_event(event,
|
||||
axis,
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL);
|
||||
|
||||
ck_assert_int_eq(libinput_event_pointer_get_axis_value(ptrev, axis),
|
||||
litest_assert_int_eq(libinput_event_pointer_get_axis_value(ptrev, axis),
|
||||
expected);
|
||||
ck_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev),
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL);
|
||||
ck_assert_int_eq(libinput_event_pointer_get_axis_value_discrete(ptrev, axis),
|
||||
discrete);
|
||||
litest_assert_int_eq(libinput_event_pointer_get_axis_value_discrete(ptrev, axis),
|
||||
discrete);
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
|
|
@ -396,11 +451,17 @@ START_TEST(pointer_scroll_wheel)
|
|||
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
test_wheel_event(dev, REL_WHEEL, -1);
|
||||
test_wheel_event(dev, REL_WHEEL, 1);
|
||||
/* make sure we hit at least one of the below two conditions */
|
||||
ck_assert(libevdev_has_event_code(dev->evdev, EV_REL, REL_WHEEL) ||
|
||||
libevdev_has_event_code(dev->evdev, EV_REL, REL_HWHEEL));
|
||||
|
||||
test_wheel_event(dev, REL_WHEEL, -5);
|
||||
test_wheel_event(dev, REL_WHEEL, 6);
|
||||
if (libevdev_has_event_code(dev->evdev, EV_REL, REL_WHEEL)) {
|
||||
test_wheel_event(dev, REL_WHEEL, -1);
|
||||
test_wheel_event(dev, REL_WHEEL, 1);
|
||||
|
||||
test_wheel_event(dev, REL_WHEEL, -5);
|
||||
test_wheel_event(dev, REL_WHEEL, 6);
|
||||
}
|
||||
|
||||
if (libevdev_has_event_code(dev->evdev, EV_REL, REL_HWHEEL)) {
|
||||
test_wheel_event(dev, REL_HWHEEL, -1);
|
||||
|
|
@ -446,11 +507,17 @@ START_TEST(pointer_scroll_natural_wheel)
|
|||
|
||||
libinput_device_config_scroll_set_natural_scroll_enabled(device, 1);
|
||||
|
||||
test_wheel_event(dev, REL_WHEEL, -1);
|
||||
test_wheel_event(dev, REL_WHEEL, 1);
|
||||
/* make sure we hit at least one of the below two conditions */
|
||||
ck_assert(libevdev_has_event_code(dev->evdev, EV_REL, REL_WHEEL) ||
|
||||
libevdev_has_event_code(dev->evdev, EV_REL, REL_HWHEEL));
|
||||
|
||||
test_wheel_event(dev, REL_WHEEL, -5);
|
||||
test_wheel_event(dev, REL_WHEEL, 6);
|
||||
if (libevdev_has_event_code(dev->evdev, EV_REL, REL_WHEEL)) {
|
||||
test_wheel_event(dev, REL_WHEEL, -1);
|
||||
test_wheel_event(dev, REL_WHEEL, 1);
|
||||
|
||||
test_wheel_event(dev, REL_WHEEL, -5);
|
||||
test_wheel_event(dev, REL_WHEEL, 6);
|
||||
}
|
||||
|
||||
if (libevdev_has_event_code(dev->evdev, EV_REL, REL_HWHEEL)) {
|
||||
test_wheel_event(dev, REL_HWHEEL, -1);
|
||||
|
|
@ -732,6 +799,26 @@ START_TEST(pointer_scroll_button)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_scroll_nowheel_defaults)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
enum libinput_config_scroll_method method;
|
||||
uint32_t button;
|
||||
|
||||
method = libinput_device_config_scroll_get_method(device);
|
||||
ck_assert_int_eq(method, LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN);
|
||||
|
||||
method = libinput_device_config_scroll_get_default_method(device);
|
||||
ck_assert_int_eq(method, LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN);
|
||||
|
||||
button = libinput_device_config_scroll_get_button(device);
|
||||
ck_assert_int_eq(button, BTN_MIDDLE);
|
||||
button = libinput_device_config_scroll_get_default_button(device);
|
||||
ck_assert_int_eq(button, BTN_MIDDLE);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_accel_defaults)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -812,6 +899,17 @@ START_TEST(pointer_accel_defaults_absolute)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_accel_defaults_absolute_relative)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
|
||||
ck_assert(libinput_device_config_accel_is_available(device));
|
||||
ck_assert(libinput_device_config_accel_get_default_speed(device) == 0.0);
|
||||
ck_assert(libinput_device_config_accel_get_speed(device) == 0.0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_accel_direction_change)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -854,19 +952,389 @@ START_TEST(pointer_accel_direction_change)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
START_TEST(middlebutton)
|
||||
{
|
||||
struct litest_device *device = litest_current_device();
|
||||
struct libinput *li = device->libinput;
|
||||
enum libinput_config_status status;
|
||||
unsigned int i;
|
||||
const int btn[][4] = {
|
||||
{ BTN_LEFT, BTN_RIGHT, BTN_LEFT, BTN_RIGHT },
|
||||
{ BTN_LEFT, BTN_RIGHT, BTN_RIGHT, BTN_LEFT },
|
||||
{ BTN_RIGHT, BTN_LEFT, BTN_LEFT, BTN_RIGHT },
|
||||
{ BTN_RIGHT, BTN_LEFT, BTN_RIGHT, BTN_LEFT },
|
||||
};
|
||||
|
||||
disable_button_scrolling(device);
|
||||
|
||||
status = libinput_device_config_middle_emulation_set_enabled(
|
||||
device->libinput_device,
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
|
||||
if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED)
|
||||
return;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(btn); i++) {
|
||||
litest_button_click(device, btn[i][0], true);
|
||||
litest_button_click(device, btn[i][1], true);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(device, btn[i][2], false);
|
||||
litest_button_click(device, btn[i][3], false);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(middlebutton_timeout)
|
||||
{
|
||||
struct litest_device *device = litest_current_device();
|
||||
struct libinput *li = device->libinput;
|
||||
enum libinput_config_status status;
|
||||
unsigned int button;
|
||||
|
||||
disable_button_scrolling(device);
|
||||
|
||||
status = libinput_device_config_middle_emulation_set_enabled(
|
||||
device->libinput_device,
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
|
||||
if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED)
|
||||
return;
|
||||
|
||||
for (button = BTN_LEFT; button <= BTN_RIGHT; button++) {
|
||||
litest_drain_events(li);
|
||||
litest_button_click(device, button, true);
|
||||
litest_assert_empty_queue(li);
|
||||
litest_timeout_middlebutton();
|
||||
|
||||
litest_assert_button_event(li,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_button_click(device, button, false);
|
||||
litest_assert_button_event(li,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(middlebutton_doubleclick)
|
||||
{
|
||||
struct litest_device *device = litest_current_device();
|
||||
struct libinput *li = device->libinput;
|
||||
enum libinput_config_status status;
|
||||
unsigned int i;
|
||||
const int btn[][4] = {
|
||||
{ BTN_LEFT, BTN_RIGHT, BTN_LEFT, BTN_RIGHT },
|
||||
{ BTN_LEFT, BTN_RIGHT, BTN_RIGHT, BTN_LEFT },
|
||||
{ BTN_RIGHT, BTN_LEFT, BTN_LEFT, BTN_RIGHT },
|
||||
{ BTN_RIGHT, BTN_LEFT, BTN_RIGHT, BTN_LEFT },
|
||||
};
|
||||
|
||||
disable_button_scrolling(device);
|
||||
|
||||
status = libinput_device_config_middle_emulation_set_enabled(
|
||||
device->libinput_device,
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
|
||||
if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED)
|
||||
return;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(btn); i++) {
|
||||
litest_button_click(device, btn[i][0], true);
|
||||
litest_button_click(device, btn[i][1], true);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(device, btn[i][2], false);
|
||||
litest_button_click(device, btn[i][2], true);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_button_click(device, btn[i][3], false);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(middlebutton_middleclick)
|
||||
{
|
||||
struct litest_device *device = litest_current_device();
|
||||
struct libinput *li = device->libinput;
|
||||
enum libinput_config_status status;
|
||||
unsigned int button;
|
||||
|
||||
disable_button_scrolling(device);
|
||||
|
||||
if (!libevdev_has_event_code(device->evdev, EV_KEY, BTN_MIDDLE))
|
||||
return;
|
||||
|
||||
status = libinput_device_config_middle_emulation_set_enabled(
|
||||
device->libinput_device,
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
|
||||
if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED)
|
||||
return;
|
||||
|
||||
/* one button down, then middle -> release buttons */
|
||||
for (button = BTN_LEFT; button <= BTN_RIGHT; button++) {
|
||||
/* release button before middle */
|
||||
litest_drain_events(li);
|
||||
litest_button_click(device, button, true);
|
||||
litest_button_click(device, BTN_MIDDLE, true);
|
||||
litest_assert_button_event(li,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_empty_queue(li);
|
||||
litest_button_click(device, button, false);
|
||||
litest_assert_button_event(li,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_button_click(device, BTN_MIDDLE, false);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* release middle before button */
|
||||
litest_button_click(device, button, true);
|
||||
litest_button_click(device, BTN_MIDDLE, true);
|
||||
litest_assert_button_event(li,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_empty_queue(li);
|
||||
litest_button_click(device, BTN_MIDDLE, false);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_button_click(device, button, false);
|
||||
litest_assert_button_event(li,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(middlebutton_middleclick_during)
|
||||
{
|
||||
struct litest_device *device = litest_current_device();
|
||||
struct libinput *li = device->libinput;
|
||||
enum libinput_config_status status;
|
||||
unsigned int button;
|
||||
|
||||
disable_button_scrolling(device);
|
||||
|
||||
if (!libevdev_has_event_code(device->evdev, EV_KEY, BTN_MIDDLE))
|
||||
return;
|
||||
|
||||
status = libinput_device_config_middle_emulation_set_enabled(
|
||||
device->libinput_device,
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
|
||||
if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED)
|
||||
return;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* trigger emulation, then real middle */
|
||||
for (button = BTN_LEFT; button <= BTN_RIGHT; button++) {
|
||||
litest_button_click(device, BTN_LEFT, true);
|
||||
litest_button_click(device, BTN_RIGHT, true);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_button_click(device, BTN_MIDDLE, true);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* middle still down, release left/right */
|
||||
litest_button_click(device, button, false);
|
||||
litest_assert_empty_queue(li);
|
||||
litest_button_click(device, button, true);
|
||||
litest_assert_button_event(li,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* release both */
|
||||
litest_button_click(device, BTN_LEFT, false);
|
||||
litest_button_click(device, BTN_RIGHT, false);
|
||||
litest_assert_button_event(li,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(device, BTN_MIDDLE, false);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(middlebutton_default_enabled)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
enum libinput_config_status status;
|
||||
int available;
|
||||
enum libinput_config_middle_emulation_state deflt, state;
|
||||
|
||||
available = libinput_device_config_middle_emulation_is_available(device);
|
||||
ck_assert(available);
|
||||
|
||||
if (libevdev_has_event_code(dev->evdev, EV_KEY, BTN_MIDDLE))
|
||||
deflt = LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
|
||||
else
|
||||
deflt = LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED;
|
||||
|
||||
state = libinput_device_config_middle_emulation_get_enabled(device);
|
||||
ck_assert_int_eq(state, deflt);
|
||||
|
||||
state = libinput_device_config_middle_emulation_get_default_enabled(
|
||||
device);
|
||||
ck_assert_int_eq(state, deflt);
|
||||
|
||||
status = libinput_device_config_middle_emulation_set_enabled(device,
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
status = libinput_device_config_middle_emulation_set_enabled(device,
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
status = libinput_device_config_middle_emulation_set_enabled(device, 3);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(middlebutton_default_clickpad)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
enum libinput_config_status status;
|
||||
enum libinput_config_middle_emulation_state state;
|
||||
int available;
|
||||
|
||||
available = libinput_device_config_middle_emulation_is_available(device);
|
||||
ck_assert(!available);
|
||||
|
||||
state = libinput_device_config_middle_emulation_get_enabled(device);
|
||||
ck_assert_int_eq(state, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
|
||||
state = libinput_device_config_middle_emulation_get_default_enabled(
|
||||
device);
|
||||
ck_assert_int_eq(state, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
|
||||
|
||||
status = libinput_device_config_middle_emulation_set_enabled(device,
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
|
||||
|
||||
status = libinput_device_config_middle_emulation_set_enabled(device,
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
status = libinput_device_config_middle_emulation_set_enabled(device, 3);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(middlebutton_default_touchpad)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
enum libinput_config_middle_emulation_state state;
|
||||
int available;
|
||||
|
||||
available = libinput_device_config_middle_emulation_is_available(device);
|
||||
ck_assert(!available);
|
||||
|
||||
if (libevdev_has_event_code(dev->evdev, EV_KEY, BTN_MIDDLE))
|
||||
return;
|
||||
|
||||
state = libinput_device_config_middle_emulation_get_enabled(
|
||||
device);
|
||||
ck_assert_int_eq(state, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
|
||||
state = libinput_device_config_middle_emulation_get_default_enabled(
|
||||
device);
|
||||
ck_assert_int_eq(state, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(middlebutton_default_disabled)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
enum libinput_config_middle_emulation_state state;
|
||||
enum libinput_config_status status;
|
||||
int available;
|
||||
|
||||
available = libinput_device_config_middle_emulation_is_available(device);
|
||||
ck_assert(!available);
|
||||
state = libinput_device_config_middle_emulation_get_enabled(device);
|
||||
ck_assert_int_eq(state, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
|
||||
state = libinput_device_config_middle_emulation_get_default_enabled(
|
||||
device);
|
||||
ck_assert_int_eq(state, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
|
||||
status = libinput_device_config_middle_emulation_set_enabled(device,
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
status = libinput_device_config_middle_emulation_set_enabled(device,
|
||||
LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
litest_setup_tests(void)
|
||||
{
|
||||
struct range axis_range = {ABS_X, ABS_Y + 1};
|
||||
|
||||
litest_add("pointer:motion", pointer_motion_relative, LITEST_RELATIVE, LITEST_ANY);
|
||||
litest_add("pointer:motion", pointer_motion_absolute, LITEST_ABSOLUTE, LITEST_ANY);
|
||||
litest_add("pointer:motion", pointer_motion_unaccel, LITEST_RELATIVE, LITEST_ANY);
|
||||
litest_add("pointer:button", pointer_button, LITEST_BUTTON, LITEST_CLICKPAD);
|
||||
litest_add_no_device("pointer:button_auto_release", pointer_button_auto_release);
|
||||
litest_add_no_device("pointer:button", pointer_button_auto_release);
|
||||
litest_add_no_device("pointer:button", pointer_seat_button_count);
|
||||
litest_add("pointer:scroll", pointer_scroll_wheel, LITEST_WHEEL, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_button, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_nowheel_defaults, LITEST_RELATIVE|LITEST_BUTTON, LITEST_WHEEL);
|
||||
litest_add("pointer:scroll", pointer_scroll_natural_defaults, LITEST_WHEEL, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_natural_enable_config, LITEST_WHEEL, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_natural_wheel, LITEST_WHEEL, LITEST_ANY);
|
||||
litest_add_no_device("pointer:seat button count", pointer_seat_button_count);
|
||||
|
||||
litest_add("pointer:calibration", pointer_no_calibration, LITEST_ANY, LITEST_TOUCH|LITEST_SINGLE_TOUCH|LITEST_ABSOLUTE|LITEST_PROTOCOL_A);
|
||||
|
||||
|
|
@ -878,8 +1346,19 @@ int main (int argc, char **argv) {
|
|||
|
||||
litest_add("pointer:accel", pointer_accel_defaults, LITEST_RELATIVE, LITEST_ANY);
|
||||
litest_add("pointer:accel", pointer_accel_invalid, LITEST_RELATIVE, LITEST_ANY);
|
||||
litest_add("pointer:accel", pointer_accel_defaults_absolute, LITEST_ABSOLUTE, LITEST_ANY);
|
||||
litest_add("pointer:accel", pointer_accel_defaults_absolute, LITEST_ABSOLUTE, LITEST_RELATIVE);
|
||||
litest_add("pointer:accel", pointer_accel_defaults_absolute_relative, LITEST_ABSOLUTE|LITEST_RELATIVE, LITEST_ANY);
|
||||
litest_add("pointer:accel", pointer_accel_direction_change, LITEST_RELATIVE, LITEST_ANY);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
litest_add("pointer:middlebutton", middlebutton, LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:middlebutton", middlebutton_timeout, LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:middlebutton", middlebutton_doubleclick, LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:middlebutton", middlebutton_middleclick, LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:middlebutton", middlebutton_middleclick_during, LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:middlebutton", middlebutton_default_enabled, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_POINTINGSTICK);
|
||||
litest_add("pointer:middlebutton", middlebutton_default_clickpad, LITEST_CLICKPAD, LITEST_ANY);
|
||||
litest_add("pointer:middlebutton", middlebutton_default_touchpad, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
litest_add("pointer:middlebutton", middlebutton_default_disabled, LITEST_ANY, LITEST_BUTTON);
|
||||
|
||||
litest_add_ranged("pointer:state", pointer_absolute_initial_state, LITEST_ABSOLUTE, LITEST_ANY, &axis_range);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1662,8 +1662,8 @@ START_TEST(artpen_rotation)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
void
|
||||
litest_setup_tests(void)
|
||||
{
|
||||
litest_add("tablet:tool", tool_ref, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
|
||||
litest_add_no_device("tablet:tool", tool_capabilities);
|
||||
|
|
@ -1692,6 +1692,4 @@ main(int argc, char **argv)
|
|||
litest_add("tablet:airbrush", airbrush_wheel, LITEST_TABLET, LITEST_ANY);
|
||||
litest_add("tablet:artpen", artpen_tool, LITEST_TABLET, LITEST_ANY);
|
||||
litest_add("tablet:artpen", artpen_rotation, LITEST_TABLET, LITEST_ANY);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
98
test/touch.c
98
test/touch.c
|
|
@ -182,6 +182,9 @@ START_TEST(touch_double_touch_down_up)
|
|||
dev = litest_current_device();
|
||||
libinput = dev->libinput;
|
||||
|
||||
/* note: this test is a false negative, libevdev will filter
|
||||
* tracking IDs re-used in the same slot. */
|
||||
|
||||
litest_touch_down(dev, 0, 0, 0);
|
||||
litest_touch_down(dev, 0, 0, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
|
@ -241,9 +244,7 @@ START_TEST(touch_calibration_scale)
|
|||
|
||||
litest_wait_for_event(li);
|
||||
ev = libinput_get_event(li);
|
||||
ck_assert_int_eq(libinput_event_get_type(ev),
|
||||
LIBINPUT_EVENT_TOUCH_DOWN);
|
||||
tev = libinput_event_get_touch_event(ev);
|
||||
tev = litest_is_touch_event(ev, LIBINPUT_EVENT_TOUCH_DOWN);
|
||||
|
||||
x = libinput_event_touch_get_x_transformed(tev, width);
|
||||
y = libinput_event_touch_get_y_transformed(tev, height);
|
||||
|
|
@ -312,9 +313,7 @@ START_TEST(touch_calibration_rotation)
|
|||
litest_touch_up(dev, 0);
|
||||
litest_wait_for_event(li);
|
||||
ev = libinput_get_event(li);
|
||||
ck_assert_int_eq(libinput_event_get_type(ev),
|
||||
LIBINPUT_EVENT_TOUCH_DOWN);
|
||||
tev = libinput_event_get_touch_event(ev);
|
||||
tev = litest_is_touch_event(ev, LIBINPUT_EVENT_TOUCH_DOWN);
|
||||
|
||||
x = libinput_event_touch_get_x_transformed(tev, width);
|
||||
y = libinput_event_touch_get_y_transformed(tev, height);
|
||||
|
|
@ -378,9 +377,7 @@ START_TEST(touch_calibration_translation)
|
|||
|
||||
litest_wait_for_event(li);
|
||||
ev = libinput_get_event(li);
|
||||
ck_assert_int_eq(libinput_event_get_type(ev),
|
||||
LIBINPUT_EVENT_TOUCH_DOWN);
|
||||
tev = libinput_event_get_touch_event(ev);
|
||||
tev = litest_is_touch_event(ev, LIBINPUT_EVENT_TOUCH_DOWN);
|
||||
|
||||
x = libinput_event_touch_get_x_transformed(tev, width);
|
||||
y = libinput_event_touch_get_y_transformed(tev, height);
|
||||
|
|
@ -439,6 +436,8 @@ START_TEST(fake_mt_exists)
|
|||
* have different capabilities */
|
||||
ck_assert(libinput_device_has_capability(device,
|
||||
LIBINPUT_DEVICE_CAP_POINTER));
|
||||
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
|
@ -460,7 +459,8 @@ START_TEST(fake_mt_no_touch_events)
|
|||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
litest_assert_only_typed_events(li,
|
||||
LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
|
@ -493,7 +493,7 @@ START_TEST(touch_protocol_a_touch)
|
|||
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_DOWN, -1);
|
||||
|
||||
ev = libinput_get_event(li);
|
||||
tev = libinput_event_get_touch_event(ev);
|
||||
tev = litest_is_touch_event(ev, LIBINPUT_EVENT_TOUCH_DOWN);
|
||||
|
||||
oldx = libinput_event_touch_get_x(tev);
|
||||
oldy = libinput_event_touch_get_y(tev);
|
||||
|
|
@ -582,9 +582,79 @@ START_TEST(touch_protocol_a_2fg_touch)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
START_TEST(touch_initial_state)
|
||||
{
|
||||
struct litest_device *dev;
|
||||
struct libinput *libinput1, *libinput2;
|
||||
struct libinput_event *ev1, *ev2;
|
||||
struct libinput_event_touch *t1, *t2;
|
||||
struct libinput_device *device1, *device2;
|
||||
int axis = _i; /* looped test */
|
||||
|
||||
dev = litest_current_device();
|
||||
device1 = dev->libinput_device;
|
||||
libinput_device_config_tap_set_enabled(device1,
|
||||
LIBINPUT_CONFIG_TAP_DISABLED);
|
||||
|
||||
libinput1 = dev->libinput;
|
||||
litest_touch_down(dev, 0, 40, 60);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
/* device is now on some x/y value */
|
||||
litest_drain_events(libinput1);
|
||||
|
||||
libinput2 = litest_create_context();
|
||||
device2 = libinput_path_add_device(libinput2,
|
||||
libevdev_uinput_get_devnode(
|
||||
dev->uinput));
|
||||
libinput_device_config_tap_set_enabled(device2,
|
||||
LIBINPUT_CONFIG_TAP_DISABLED);
|
||||
litest_drain_events(libinput2);
|
||||
|
||||
if (axis == ABS_X)
|
||||
litest_touch_down(dev, 0, 40, 70);
|
||||
else
|
||||
litest_touch_down(dev, 0, 70, 60);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_wait_for_event(libinput1);
|
||||
litest_wait_for_event(libinput2);
|
||||
|
||||
while (libinput_next_event_type(libinput1)) {
|
||||
ev1 = libinput_get_event(libinput1);
|
||||
ev2 = libinput_get_event(libinput2);
|
||||
|
||||
t1 = litest_is_touch_event(ev1, 0);
|
||||
t2 = litest_is_touch_event(ev2, 0);
|
||||
|
||||
ck_assert_int_eq(libinput_event_get_type(ev1),
|
||||
libinput_event_get_type(ev2));
|
||||
|
||||
if (libinput_event_get_type(ev1) == LIBINPUT_EVENT_TOUCH_UP ||
|
||||
libinput_event_get_type(ev1) == LIBINPUT_EVENT_TOUCH_FRAME)
|
||||
break;
|
||||
|
||||
ck_assert_int_eq(libinput_event_touch_get_x(t1),
|
||||
libinput_event_touch_get_x(t2));
|
||||
ck_assert_int_eq(libinput_event_touch_get_y(t1),
|
||||
libinput_event_touch_get_y(t2));
|
||||
|
||||
libinput_event_destroy(ev1);
|
||||
libinput_event_destroy(ev2);
|
||||
}
|
||||
|
||||
libinput_event_destroy(ev1);
|
||||
libinput_event_destroy(ev2);
|
||||
|
||||
libinput_unref(libinput2);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
litest_setup_tests(void)
|
||||
{
|
||||
struct range axes = { ABS_X, ABS_Y + 1};
|
||||
|
||||
litest_add("touch:frame", touch_frame_events, LITEST_TOUCH, LITEST_ANY);
|
||||
litest_add_no_device("touch:abs-transform", touch_abs_transform);
|
||||
litest_add_no_device("touch:many-slots", touch_many_slots);
|
||||
|
|
@ -605,5 +675,5 @@ main(int argc, char **argv)
|
|||
litest_add("touch:protocol a", touch_protocol_a_touch, LITEST_PROTOCOL_A, LITEST_ANY);
|
||||
litest_add("touch:protocol a", touch_protocol_a_2fg_touch, LITEST_PROTOCOL_A, LITEST_ANY);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
litest_add_ranged("touch:state", touch_initial_state, LITEST_TOUCH, LITEST_PROTOCOL_A, &axes);
|
||||
}
|
||||
|
|
|
|||
1330
test/touchpad.c
1330
test/touchpad.c
File diff suppressed because it is too large
Load diff
|
|
@ -130,12 +130,11 @@ START_TEST(trackpoint_scroll_source)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
void
|
||||
litest_setup_tests(void)
|
||||
{
|
||||
litest_add("trackpoint:middlebutton", trackpoint_middlebutton, LITEST_POINTINGSTICK, LITEST_ANY);
|
||||
litest_add("trackpoint:middlebutton", trackpoint_middlebutton_noscroll, LITEST_POINTINGSTICK, LITEST_ANY);
|
||||
litest_add("trackpoint:scroll", trackpoint_scroll, LITEST_POINTINGSTICK, LITEST_ANY);
|
||||
litest_add("trackpoint:scroll", trackpoint_scroll_source, LITEST_POINTINGSTICK, LITEST_ANY);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -502,8 +502,8 @@ START_TEST(udev_seat_recycle)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
void
|
||||
litest_setup_tests(void)
|
||||
{
|
||||
litest_add_no_device("udev:create", udev_create_NULL);
|
||||
litest_add_no_device("udev:create", udev_create_seat0);
|
||||
|
|
@ -518,6 +518,4 @@ main(int argc, char **argv)
|
|||
litest_add_for_device("udev:suspend", udev_suspend_resume, LITEST_SYNAPTICS_CLICKPAD);
|
||||
litest_add_for_device("udev:device events", udev_device_sysname, LITEST_SYNAPTICS_CLICKPAD);
|
||||
litest_add_for_device("udev:seat", udev_seat_recycle, LITEST_SYNAPTICS_CLICKPAD);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,3 +31,11 @@
|
|||
...
|
||||
fun:g_malloc0
|
||||
}
|
||||
{
|
||||
libunwind:msync_uninitialized_bytes
|
||||
Memcheck:Param
|
||||
msync(start)
|
||||
fun:__msync_nocancel
|
||||
...
|
||||
fun:litest_backtrace
|
||||
}
|
||||
|
|
|
|||
3
tools/.gitignore
vendored
3
tools/.gitignore
vendored
|
|
@ -1,2 +1,5 @@
|
|||
event-debug
|
||||
event-gui
|
||||
ptraccel-debug
|
||||
libinput-list-devices
|
||||
libinput-debug-events
|
||||
|
|
|
|||
|
|
@ -1,19 +1,36 @@
|
|||
noinst_PROGRAMS = event-debug
|
||||
noinst_PROGRAMS = event-debug ptraccel-debug
|
||||
bin_PROGRAMS = libinput-list-devices libinput-debug-events
|
||||
noinst_LTLIBRARIES = libshared.la
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/src
|
||||
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_builddir)/src # for libinput-version.h
|
||||
|
||||
libshared_la_SOURCES = \
|
||||
shared.c \
|
||||
shared.h
|
||||
libshared_la_CFLAGS = $(LIBEVDEV_CFLAGS)
|
||||
libshared_la_LIBADD = $(LIBEVDEV_LIBS)
|
||||
|
||||
event_debug_SOURCES = event-debug.c
|
||||
event_debug_LDADD = ../src/libinput.la libshared.la $(LIBUDEV_LIBS)
|
||||
event_debug_LDFLAGS = -no-install
|
||||
event_debug_CFLAGS = $(LIBUDEV_CFLAGS)
|
||||
|
||||
ptraccel_debug_SOURCES = ptraccel-debug.c
|
||||
ptraccel_debug_LDADD = ../src/libfilter.la
|
||||
ptraccel_debug_LDFLAGS = -no-install
|
||||
|
||||
libinput_list_devices_SOURCES = libinput-list-devices.c
|
||||
libinput_list_devices_LDADD = ../src/libinput.la libshared.la $(LIBUDEV_LIBS)
|
||||
libinput_list_devices_CFLAGS = $(LIBUDEV_CFLAGS)
|
||||
dist_man1_MANS = libinput-list-devices.man
|
||||
|
||||
libinput_debug_events_SOURCES = $(event_debug_SOURCES)
|
||||
libinput_debug_events_LDADD = $(event_debug_LDADD)
|
||||
libinput_debug_events_CFLAGS = $(event_debug_CFLAGS)
|
||||
dist_man1_MANS += libinput-debug-events.man
|
||||
|
||||
if BUILD_EVENTGUI
|
||||
noinst_PROGRAMS += event-gui
|
||||
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ struct window {
|
|||
int absx, absy;
|
||||
|
||||
/* scroll bar positions */
|
||||
int vx, vy;
|
||||
int hx, hy;
|
||||
double vx, vy;
|
||||
double hx, hy;
|
||||
|
||||
/* touch positions */
|
||||
struct touch touches[32];
|
||||
|
|
@ -279,14 +279,8 @@ handle_event_device_notify(struct libinput_event *ev)
|
|||
libinput_device_get_name(dev),
|
||||
type);
|
||||
|
||||
if (libinput_device_config_tap_get_finger_count(dev) > 0) {
|
||||
enum libinput_config_status status;
|
||||
status = libinput_device_config_tap_set_enabled(dev,
|
||||
LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
if (status != LIBINPUT_CONFIG_STATUS_SUCCESS)
|
||||
error("%s: Failed to enable tapping\n",
|
||||
libinput_device_get_sysname(dev));
|
||||
}
|
||||
tools_device_apply_config(libinput_event_get_device(ev),
|
||||
&options);
|
||||
|
||||
li = libinput_event_get_context(ev);
|
||||
w = libinput_get_user_data(li);
|
||||
|
|
@ -369,7 +363,7 @@ handle_event_axis(struct libinput_event *ev, struct window *w)
|
|||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) {
|
||||
value = libinput_event_pointer_get_axis_value(p,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
||||
w->vy += (int)value;
|
||||
w->vy += value;
|
||||
w->vy = clip(w->vy, 0, w->height);
|
||||
}
|
||||
|
||||
|
|
@ -377,7 +371,7 @@ handle_event_axis(struct libinput_event *ev, struct window *w)
|
|||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) {
|
||||
value = libinput_event_pointer_get_axis_value(p,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
|
||||
w->hx += (int)value;
|
||||
w->hx += value;
|
||||
w->hx = clip(w->hx, 0, w->width);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
31
tools/libinput-debug-events.man
Normal file
31
tools/libinput-debug-events.man
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
.TH LIBINPUT-DEBUG-EVENTS "1"
|
||||
.SH NAME
|
||||
libinput-debug-events \- debug helper for libinput
|
||||
.SH SYNOPSIS
|
||||
.B libinput-debug-events [--help]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
The
|
||||
.I libinput-debug-events
|
||||
tool creates a libinput context and prints all events from these devices.
|
||||
.PP
|
||||
This is a debugging tool only, its output may change at any time. Do not
|
||||
rely on the output.
|
||||
.PP
|
||||
This tool usually needs to be run as root to have access to the
|
||||
/dev/input/eventX nodes.
|
||||
.SH OPTIONS
|
||||
.TP 8
|
||||
.B --help
|
||||
Print help
|
||||
.PP
|
||||
For all other options, see the output from --help. Options may be added or
|
||||
removed at any time.
|
||||
.SH NOTES
|
||||
.PP
|
||||
Events shown by this tool may not correspond to the events seen by a
|
||||
different user of libinput. This tool initializes a separate context.
|
||||
.PP
|
||||
Events shown by this tool include key codes in plain text. Anything you type
|
||||
while this tool is running will show up in the output, including your
|
||||
passwords.
|
||||
313
tools/libinput-list-devices.c
Normal file
313
tools/libinput-list-devices.c
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* Copyright © 2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <libudev.h>
|
||||
|
||||
#include <libinput.h>
|
||||
#include <libinput-version.h>
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
static int
|
||||
open_restricted(const char *path, int flags, void *user_data)
|
||||
{
|
||||
int fd = open(path, flags);
|
||||
if (fd < 0)
|
||||
fprintf(stderr, "Failed to open %s (%s)\n",
|
||||
path, strerror(errno));
|
||||
return fd < 0 ? -errno : fd;
|
||||
}
|
||||
|
||||
static void
|
||||
close_restricted(int fd, void *user_data)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static const struct libinput_interface interface = {
|
||||
.open_restricted = open_restricted,
|
||||
.close_restricted = close_restricted,
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
if (!libinput_device_config_tap_get_finger_count(device))
|
||||
return "n/a";
|
||||
|
||||
if (libinput_device_config_tap_get_default_enabled(device))
|
||||
return "enabled";
|
||||
else
|
||||
return "disabled";
|
||||
}
|
||||
|
||||
static const char*
|
||||
left_handed_default(struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_left_handed_is_available(device))
|
||||
return "n/a";
|
||||
|
||||
if (libinput_device_config_left_handed_get_default(device))
|
||||
return "enabled";
|
||||
else
|
||||
return "disabled";
|
||||
}
|
||||
|
||||
static const char *
|
||||
nat_scroll_default(struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_scroll_has_natural_scroll(device))
|
||||
return "n/a";
|
||||
|
||||
if (libinput_device_config_scroll_get_default_natural_scroll_enabled(device))
|
||||
return "enabled";
|
||||
else
|
||||
return "disabled";
|
||||
}
|
||||
|
||||
static const char *
|
||||
middle_emulation_default(struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_middle_emulation_is_available(device))
|
||||
return "n/a";
|
||||
|
||||
if (libinput_device_config_middle_emulation_get_default_enabled(device))
|
||||
return "enabled";
|
||||
else
|
||||
return "disabled";
|
||||
}
|
||||
|
||||
static char *
|
||||
calibration_default(struct libinput_device *device)
|
||||
{
|
||||
char *str;
|
||||
float calibration[6];
|
||||
|
||||
if (!libinput_device_config_calibration_has_matrix(device)) {
|
||||
asprintf(&str, "n/a");
|
||||
return str;
|
||||
}
|
||||
|
||||
if (libinput_device_config_calibration_get_default_matrix(device,
|
||||
calibration) == 0) {
|
||||
asprintf(&str, "identity matrix");
|
||||
return str;
|
||||
}
|
||||
|
||||
asprintf(&str,
|
||||
"%.2f %.2f %.2f %.2f %.2f %.2f",
|
||||
calibration[0],
|
||||
calibration[1],
|
||||
calibration[2],
|
||||
calibration[3],
|
||||
calibration[4],
|
||||
calibration[5]);
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *
|
||||
scroll_defaults(struct libinput_device *device)
|
||||
{
|
||||
uint32_t scroll_methods;
|
||||
char *str;
|
||||
enum libinput_config_scroll_method method;
|
||||
|
||||
scroll_methods = libinput_device_config_scroll_get_methods(device);
|
||||
if (scroll_methods == LIBINPUT_CONFIG_SCROLL_NO_SCROLL) {
|
||||
asprintf(&str, "none");
|
||||
return str;
|
||||
}
|
||||
|
||||
method = libinput_device_config_scroll_get_default_method(device);
|
||||
|
||||
asprintf(&str,
|
||||
"%s%s%s%s%s%s",
|
||||
(method == LIBINPUT_CONFIG_SCROLL_2FG) ? "*" : "",
|
||||
(scroll_methods & LIBINPUT_CONFIG_SCROLL_2FG) ? "two-finger " : "",
|
||||
(method == LIBINPUT_CONFIG_SCROLL_EDGE) ? "*" : "",
|
||||
(scroll_methods & LIBINPUT_CONFIG_SCROLL_EDGE) ? "edge " : "",
|
||||
(method == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) ? "*" : "",
|
||||
(scroll_methods & LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) ? "button" : "");
|
||||
return str;
|
||||
}
|
||||
|
||||
static char*
|
||||
click_defaults(struct libinput_device *device)
|
||||
{
|
||||
uint32_t click_methods;
|
||||
char *str;
|
||||
enum libinput_config_click_method method;
|
||||
|
||||
click_methods = libinput_device_config_click_get_methods(device);
|
||||
if (click_methods == LIBINPUT_CONFIG_CLICK_METHOD_NONE) {
|
||||
asprintf(&str, "none");
|
||||
return str;
|
||||
}
|
||||
|
||||
method = libinput_device_config_click_get_default_method(device);
|
||||
asprintf(&str,
|
||||
"%s%s%s%s",
|
||||
(method == LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS) ? "*" : "",
|
||||
(click_methods & LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS) ? "button-areas " : "",
|
||||
(method == LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) ? "*" : "",
|
||||
(click_methods & LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) ? "clickfinger " : "");
|
||||
return str;
|
||||
}
|
||||
|
||||
static void
|
||||
print_device_notify(struct libinput_event *ev)
|
||||
{
|
||||
struct libinput_device *dev = libinput_event_get_device(ev);
|
||||
struct libinput_seat *seat = libinput_device_get_seat(dev);
|
||||
struct libinput_device_group *group;
|
||||
double w, h;
|
||||
static int next_group_id = 0;
|
||||
intptr_t group_id;
|
||||
const char *devnode;
|
||||
char *str;
|
||||
|
||||
group = libinput_device_get_device_group(dev);
|
||||
group_id = (intptr_t)libinput_device_group_get_user_data(group);
|
||||
if (!group_id) {
|
||||
group_id = ++next_group_id;
|
||||
libinput_device_group_set_user_data(group, (void*)group_id);
|
||||
}
|
||||
|
||||
devnode = udev_device_get_devnode(
|
||||
libinput_device_get_udev_device(dev));
|
||||
|
||||
printf("Device: %s\n"
|
||||
"Kernel: %s\n"
|
||||
"Group: %d\n"
|
||||
"Seat: %s, %s\n",
|
||||
libinput_device_get_name(dev),
|
||||
devnode,
|
||||
(int)group_id,
|
||||
libinput_seat_get_physical_name(seat),
|
||||
libinput_seat_get_logical_name(seat));
|
||||
|
||||
if (libinput_device_get_size(dev, &w, &h) == 0)
|
||||
printf("Size: %.2fx%.2fmm\n", w, h);
|
||||
printf("Capabilities: ");
|
||||
if (libinput_device_has_capability(dev,
|
||||
LIBINPUT_DEVICE_CAP_KEYBOARD))
|
||||
printf("keyboard ");
|
||||
if (libinput_device_has_capability(dev,
|
||||
LIBINPUT_DEVICE_CAP_POINTER))
|
||||
printf("pointer ");
|
||||
if (libinput_device_has_capability(dev,
|
||||
LIBINPUT_DEVICE_CAP_TOUCH))
|
||||
printf("touch");
|
||||
printf("\n");
|
||||
|
||||
printf("Tap-to-click: %s\n", tap_default(dev));
|
||||
printf("Left-handed: %s\n", left_handed_default(dev));
|
||||
printf("Nat.scrolling: %s\n", nat_scroll_default(dev));
|
||||
printf("Middle emulation: %s\n", middle_emulation_default(dev));
|
||||
str = calibration_default(dev);
|
||||
printf("Calibration: %s\n", str);
|
||||
free(str);
|
||||
|
||||
str = scroll_defaults(dev);
|
||||
printf("Scroll methods: %s\n", str);
|
||||
free(str);
|
||||
|
||||
str = click_defaults(dev);
|
||||
printf("Click methods: %s\n", str);
|
||||
free(str);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static inline void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage: %s [--help|--version]\n"
|
||||
"\n"
|
||||
"This tool creates a libinput context on the default seat \"seat0\"\n"
|
||||
"and lists all devices recognized by libinput and the configuration options.\n"
|
||||
"Where multiple options are possible, the default is prefixed with \"*\".\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
"--help ...... show this help\n"
|
||||
"--version ... show version information\n"
|
||||
"\n"
|
||||
"This tool requires access to the /dev/input/eventX nodes.\n",
|
||||
program_invocation_short_name);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct libinput *li;
|
||||
struct tools_options options;
|
||||
struct libinput_event *ev;
|
||||
|
||||
if (argc > 1) {
|
||||
if (strcmp(argv[1], "--help") == 0) {
|
||||
usage();
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "--version") == 0) {
|
||||
printf("%s\n", LIBINPUT_VERSION);
|
||||
return 0;
|
||||
} else {
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
tools_init_options(&options);
|
||||
|
||||
li = tools_open_backend(&options, NULL, &interface);
|
||||
if (!li)
|
||||
return 1;
|
||||
|
||||
libinput_dispatch(li);
|
||||
while ((ev = libinput_get_event(li))) {
|
||||
|
||||
if (libinput_event_get_type(ev) == LIBINPUT_EVENT_DEVICE_ADDED)
|
||||
print_device_notify(ev);
|
||||
|
||||
libinput_event_destroy(ev);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
libinput_unref(li);
|
||||
|
||||
return 0;
|
||||
}
|
||||
37
tools/libinput-list-devices.man
Normal file
37
tools/libinput-list-devices.man
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
.TH LIBINPUT-LIST-DEVICES "1"
|
||||
.SH NAME
|
||||
libinput-list-devices \- list local devices as recognized by libinput
|
||||
.SH SYNOPSIS
|
||||
.B libinput-list-devices [--help]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
The
|
||||
.I libinput-list-devices
|
||||
tool creates a libinput context on the default seat "seat0" and lists all
|
||||
devices regonized by libinput. Each device shows available configurations
|
||||
the respective default configuration setting.
|
||||
.PP
|
||||
For configuration options that allow multiple different settings (e.g.
|
||||
scrolling), all available settings are listed. The default setting is
|
||||
prefixed by an asterisk (*).
|
||||
.PP
|
||||
This tool usually needs to be run as root to have access to the
|
||||
/dev/input/eventX nodes.
|
||||
.SH OPTIONS
|
||||
.TP 8
|
||||
.B --help
|
||||
Print help
|
||||
.SH NOTES
|
||||
.PP
|
||||
Some specific feature may still be available on a device even when
|
||||
no configuration is exposed, a lack of a configuration option does not
|
||||
necessarily mean that this feature does not work.
|
||||
.PP
|
||||
A device may be recognized by libinput but not handled by the X.Org libinput
|
||||
driver or the Wayland compositor.
|
||||
.PP
|
||||
An xorg.conf(5) configuration entry or Wayland compositor setting may have
|
||||
changed configurations on a device. The
|
||||
.I libinput-list-devices
|
||||
tool only shows the device's default configuration, not the current
|
||||
configuration.
|
||||
300
tools/ptraccel-debug.c
Normal file
300
tools/ptraccel-debug.c
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* Copyright © 2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <filter.h>
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void
|
||||
print_ptraccel_deltas(struct motion_filter *filter, double step)
|
||||
{
|
||||
struct normalized_coords motion;
|
||||
uint64_t time = 0;
|
||||
double i;
|
||||
|
||||
printf("# gnuplot:\n");
|
||||
printf("# set xlabel dx unaccelerated\n");
|
||||
printf("# set ylabel dx accelerated\n");
|
||||
printf("# set style data lines\n");
|
||||
printf("# plot \"gnuplot.data\" using 1:2 title \"step %.2f\"\n", step);
|
||||
printf("#\n");
|
||||
|
||||
/* Accel flattens out after 15 and becomes linear */
|
||||
for (i = 0.0; i < 15.0; i += step) {
|
||||
motion.x = i;
|
||||
motion.y = 0;
|
||||
time += 12; /* pretend 80Hz data */
|
||||
|
||||
motion = filter_dispatch(filter, &motion, NULL, time);
|
||||
|
||||
printf("%.2f %.3f\n", i, motion.x);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_ptraccel_movement(struct motion_filter *filter,
|
||||
int nevents,
|
||||
double max_dx,
|
||||
double step)
|
||||
{
|
||||
struct normalized_coords motion;
|
||||
uint64_t time = 0;
|
||||
double dx;
|
||||
int i;
|
||||
|
||||
printf("# gnuplot:\n");
|
||||
printf("# set xlabel \"event number\"\n");
|
||||
printf("# set ylabel \"delta motion\"\n");
|
||||
printf("# set style data lines\n");
|
||||
printf("# plot \"gnuplot.data\" using 1:2 title \"dx out\", \\\n");
|
||||
printf("# \"gnuplot.data\" using 1:3 title \"dx in\"\n");
|
||||
printf("#\n");
|
||||
|
||||
if (nevents == 0) {
|
||||
if (step > 1.0)
|
||||
nevents = max_dx;
|
||||
else
|
||||
nevents = 1.0 * max_dx/step + 0.5;
|
||||
|
||||
/* Print more events than needed so we see the curve
|
||||
* flattening out */
|
||||
nevents *= 1.5;
|
||||
}
|
||||
|
||||
dx = 0;
|
||||
|
||||
for (i = 0; i < nevents; i++) {
|
||||
motion.x = dx;
|
||||
motion.y = 0;
|
||||
time += 12; /* pretend 80Hz data */
|
||||
|
||||
filter_dispatch(filter, &motion, NULL, time);
|
||||
|
||||
printf("%d %.3f %.3f\n", i, motion.x, dx);
|
||||
|
||||
if (dx < max_dx)
|
||||
dx += step;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_ptraccel_sequence(struct motion_filter *filter,
|
||||
int nevents,
|
||||
double *deltas)
|
||||
{
|
||||
struct normalized_coords motion;
|
||||
uint64_t time = 0;
|
||||
double *dx;
|
||||
int i;
|
||||
|
||||
printf("# gnuplot:\n");
|
||||
printf("# set xlabel \"event number\"\n");
|
||||
printf("# set ylabel \"delta motion\"\n");
|
||||
printf("# set style data lines\n");
|
||||
printf("# plot \"gnuplot.data\" using 1:2 title \"dx out\", \\\n");
|
||||
printf("# \"gnuplot.data\" using 1:3 title \"dx in\"\n");
|
||||
printf("#\n");
|
||||
|
||||
dx = deltas;
|
||||
|
||||
for (i = 0; i < nevents; i++, dx++) {
|
||||
motion.x = *dx;
|
||||
motion.y = 0;
|
||||
time += 12; /* pretend 80Hz data */
|
||||
|
||||
filter_dispatch(filter, &motion, NULL, time);
|
||||
|
||||
printf("%d %.3f %.3f\n", i, motion.x, *dx);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_accel_func(struct motion_filter *filter)
|
||||
{
|
||||
double vel;
|
||||
|
||||
printf("# gnuplot:\n");
|
||||
printf("# set xlabel \"speed\"\n");
|
||||
printf("# set ylabel \"raw accel factor\"\n");
|
||||
printf("# set style data lines\n");
|
||||
printf("# plot \"gnuplot.data\" using 1:2\n");
|
||||
for (vel = 0.0; vel < 3.0; vel += .0001) {
|
||||
double result = pointer_accel_profile_linear(filter,
|
||||
NULL,
|
||||
vel,
|
||||
0 /* time */);
|
||||
printf("%.4f\t%.4f\n", vel, result);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage: %s [options] [dx1] [dx2] [...] > gnuplot.data\n", program_invocation_short_name);
|
||||
printf("\n"
|
||||
"Options:\n"
|
||||
"--mode=<motion|accel|delta|sequence> \n"
|
||||
" motion ... print motion to accelerated motion (default)\n"
|
||||
" delta ... print delta to accelerated delta\n"
|
||||
" accel ... print accel factor\n"
|
||||
" sequence ... print motion for custom delta sequence\n"
|
||||
"--maxdx=<double>\n ... in motion mode only. Stop increasing dx at maxdx\n"
|
||||
"--steps=<double>\n ... in motion and delta modes only. Increase dx by step each round\n"
|
||||
"--speed=<double>\n ... accel speed [-1, 1], default 0\n"
|
||||
"\n"
|
||||
"If extra arguments are present and mode is not given, mode defaults to 'sequence'\n"
|
||||
"and the arguments are interpreted as sequence of delta x coordinates\n"
|
||||
"\n"
|
||||
"If stdin is a pipe, mode defaults to 'sequence' and the pipe is read \n"
|
||||
"for delta coordinates\n"
|
||||
"\n"
|
||||
"Output best viewed with gnuplot. See output for gnuplot commands\n");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct motion_filter *filter;
|
||||
double step = 0.1,
|
||||
max_dx = 10;
|
||||
int nevents = 0;
|
||||
bool print_accel = false,
|
||||
print_motion = true,
|
||||
print_delta = false,
|
||||
print_sequence = false;
|
||||
double custom_deltas[1024];
|
||||
double speed = 0.0;
|
||||
enum {
|
||||
OPT_MODE = 1,
|
||||
OPT_NEVENTS,
|
||||
OPT_MAXDX,
|
||||
OPT_STEP,
|
||||
OPT_SPEED,
|
||||
};
|
||||
|
||||
filter = create_pointer_accelerator_filter(pointer_accel_profile_linear);
|
||||
assert(filter != NULL);
|
||||
|
||||
while (1) {
|
||||
int c;
|
||||
int option_index = 0;
|
||||
static struct option long_options[] = {
|
||||
{"mode", 1, 0, OPT_MODE },
|
||||
{"nevents", 1, 0, OPT_NEVENTS },
|
||||
{"maxdx", 1, 0, OPT_MAXDX },
|
||||
{"step", 1, 0, OPT_STEP },
|
||||
{"speed", 1, 0, OPT_SPEED },
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case OPT_MODE:
|
||||
if (strcmp(optarg, "accel") == 0)
|
||||
print_accel = true;
|
||||
else if (strcmp(optarg, "motion") == 0)
|
||||
print_motion = true;
|
||||
else if (strcmp(optarg, "delta") == 0)
|
||||
print_delta = true;
|
||||
else if (strcmp(optarg, "sequence") == 0)
|
||||
print_sequence = true;
|
||||
else {
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case OPT_NEVENTS:
|
||||
nevents = atoi(optarg);
|
||||
if (nevents == 0) {
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case OPT_MAXDX:
|
||||
max_dx = strtod(optarg, NULL);
|
||||
if (max_dx == 0.0) {
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case OPT_STEP:
|
||||
step = strtod(optarg, NULL);
|
||||
if (step == 0.0) {
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case OPT_SPEED:
|
||||
speed = strtod(optarg, NULL);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
filter_set_speed(filter, speed);
|
||||
|
||||
if (!isatty(STDIN_FILENO)) {
|
||||
char buf[12];
|
||||
print_sequence = true;
|
||||
print_motion = false;
|
||||
nevents = 0;
|
||||
memset(custom_deltas, 0, sizeof(custom_deltas));
|
||||
|
||||
while(fgets(buf, sizeof(buf), stdin) && nevents < 1024) {
|
||||
custom_deltas[nevents++] = strtod(buf, NULL);
|
||||
}
|
||||
} else if (optind < argc) {
|
||||
print_sequence = true;
|
||||
print_motion = false;
|
||||
nevents = 0;
|
||||
memset(custom_deltas, 0, sizeof(custom_deltas));
|
||||
while (optind < argc)
|
||||
custom_deltas[nevents++] = strtod(argv[optind++], NULL);
|
||||
}
|
||||
|
||||
if (print_accel)
|
||||
print_accel_func(filter);
|
||||
else if (print_delta)
|
||||
print_ptraccel_deltas(filter, step);
|
||||
else if (print_motion)
|
||||
print_ptraccel_movement(filter, nevents, max_dx, step);
|
||||
else if (print_sequence)
|
||||
print_ptraccel_sequence(filter, nevents, custom_deltas);
|
||||
|
||||
filter_destroy(filter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -30,6 +30,8 @@
|
|||
#include <string.h>
|
||||
#include <libudev.h>
|
||||
|
||||
#include <libevdev/libevdev.h>
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
enum options {
|
||||
|
|
@ -43,7 +45,12 @@ enum options {
|
|||
OPT_NATURAL_SCROLL_DISABLE,
|
||||
OPT_LEFT_HANDED_ENABLE,
|
||||
OPT_LEFT_HANDED_DISABLE,
|
||||
OPT_MIDDLEBUTTON_ENABLE,
|
||||
OPT_MIDDLEBUTTON_DISABLE,
|
||||
OPT_CLICK_METHOD,
|
||||
OPT_SCROLL_METHOD,
|
||||
OPT_SCROLL_BUTTON,
|
||||
OPT_SPEED,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -70,7 +77,12 @@ tools_usage()
|
|||
"--disable-natural-scrolling.... enable/disable natural scrolling\n"
|
||||
"--enable-left-handed\n"
|
||||
"--disable-left-handed.... enable/disable left-handed button configuration\n"
|
||||
"--enable-middlebutton\n"
|
||||
"--disable-middlebutton.... enable/disable middle button emulation\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"
|
||||
"--set-speed=<value>.... set pointer acceleration speed\n"
|
||||
"\n"
|
||||
"These options apply to all applicable devices, if a feature\n"
|
||||
"is not explicitly specified it is left at each device's default.\n"
|
||||
|
|
@ -88,9 +100,13 @@ tools_init_options(struct tools_options *options)
|
|||
options->tapping = -1;
|
||||
options->natural_scroll = -1;
|
||||
options->left_handed = -1;
|
||||
options->middlebutton = -1;
|
||||
options->click_method = -1;
|
||||
options->scroll_method = -1;
|
||||
options->scroll_button = -1;
|
||||
options->backend = BACKEND_UDEV;
|
||||
options->seat = "seat0";
|
||||
options->speed = 0.0;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -110,7 +126,12 @@ tools_parse_args(int argc, char **argv, struct tools_options *options)
|
|||
{ "disable-natural-scrolling", 0, 0, OPT_NATURAL_SCROLL_DISABLE },
|
||||
{ "enable-left-handed", 0, 0, OPT_LEFT_HANDED_ENABLE },
|
||||
{ "disable-left-handed", 0, 0, OPT_LEFT_HANDED_DISABLE },
|
||||
{ "enable-middlebutton", 0, 0, OPT_MIDDLEBUTTON_ENABLE },
|
||||
{ "disable-middlebutton", 0, 0, OPT_MIDDLEBUTTON_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 },
|
||||
{ "speed", 1, 0, OPT_SPEED },
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
|
@ -157,6 +178,12 @@ tools_parse_args(int argc, char **argv, struct tools_options *options)
|
|||
case OPT_LEFT_HANDED_DISABLE:
|
||||
options->left_handed = 0;
|
||||
break;
|
||||
case OPT_MIDDLEBUTTON_ENABLE:
|
||||
options->middlebutton = 1;
|
||||
break;
|
||||
case OPT_MIDDLEBUTTON_DISABLE:
|
||||
options->middlebutton = 0;
|
||||
break;
|
||||
case OPT_CLICK_METHOD:
|
||||
if (!optarg) {
|
||||
tools_usage();
|
||||
|
|
@ -176,6 +203,50 @@ tools_parse_args(int argc, char **argv, struct tools_options *options)
|
|||
return 1;
|
||||
}
|
||||
break;
|
||||
case OPT_SCROLL_METHOD:
|
||||
if (!optarg) {
|
||||
tools_usage();
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(optarg, "none") == 0) {
|
||||
options->scroll_method =
|
||||
LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
|
||||
} else if (strcmp(optarg, "twofinger") == 0) {
|
||||
options->scroll_method =
|
||||
LIBINPUT_CONFIG_SCROLL_2FG;
|
||||
} else if (strcmp(optarg, "edge") == 0) {
|
||||
options->scroll_method =
|
||||
LIBINPUT_CONFIG_SCROLL_EDGE;
|
||||
} else if (strcmp(optarg, "button") == 0) {
|
||||
options->scroll_method =
|
||||
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
|
||||
} else {
|
||||
tools_usage();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case OPT_SCROLL_BUTTON:
|
||||
if (!optarg) {
|
||||
tools_usage();
|
||||
return 1;
|
||||
}
|
||||
options->scroll_button =
|
||||
libevdev_event_code_from_name(EV_KEY,
|
||||
optarg);
|
||||
if (options->scroll_button == -1) {
|
||||
fprintf(stderr,
|
||||
"Invalid button %s\n",
|
||||
optarg);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case OPT_SPEED:
|
||||
if (!optarg) {
|
||||
tools_usage();
|
||||
return 1;
|
||||
}
|
||||
options->speed = atof(optarg);
|
||||
break;
|
||||
default:
|
||||
tools_usage();
|
||||
return 1;
|
||||
|
|
@ -286,7 +357,21 @@ tools_device_apply_config(struct libinput_device *device,
|
|||
options->natural_scroll);
|
||||
if (options->left_handed != -1)
|
||||
libinput_device_config_left_handed_set(device, options->left_handed);
|
||||
if (options->middlebutton != -1)
|
||||
libinput_device_config_middle_emulation_set_enabled(device,
|
||||
options->middlebutton);
|
||||
|
||||
if (options->click_method != -1)
|
||||
libinput_device_config_click_set_method(device, options->click_method);
|
||||
|
||||
if (options->scroll_method != -1)
|
||||
libinput_device_config_scroll_set_method(device,
|
||||
options->scroll_method);
|
||||
if (options->scroll_button != -1)
|
||||
libinput_device_config_scroll_set_button(device,
|
||||
options->scroll_button);
|
||||
|
||||
if (libinput_device_config_accel_is_available(device))
|
||||
libinput_device_config_accel_set_speed(device,
|
||||
options->speed);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,11 @@ struct tools_options {
|
|||
int tapping;
|
||||
int natural_scroll;
|
||||
int left_handed;
|
||||
int middlebutton;
|
||||
enum libinput_config_click_method click_method;
|
||||
enum libinput_config_scroll_method scroll_method;
|
||||
int scroll_button;
|
||||
double speed;
|
||||
};
|
||||
|
||||
void tools_init_options(struct tools_options *options);
|
||||
|
|
|
|||
66
udev/90-libinput-model-quirks.hwdb
Normal file
66
udev/90-libinput-model-quirks.hwdb
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# Do not edit this file, it will be overwritten on update
|
||||
#
|
||||
# This file contains hwdb matches for libinput model-specific quirks.
|
||||
# The contents of this file are a contract between libinput, udev rules and
|
||||
# the hwdb.
|
||||
# IT IS NOT A STABLE API AND SUBJECT TO CHANGE AT ANY TIME
|
||||
|
||||
# The lookup keys are composed in:
|
||||
# 90-libinput-model-quirks.rules
|
||||
#
|
||||
# Match string formats:
|
||||
# libinput:<modalias>
|
||||
# libinput:name:<name>:dmi:<dmi string>
|
||||
|
||||
#
|
||||
# Sort by brand, model
|
||||
|
||||
##########################################
|
||||
# Google
|
||||
##########################################
|
||||
|
||||
# The various chromebooks, info from modinfo chromeos_laptop, touchpad names
|
||||
# extrapolated from the chromiumos touchad-tests repo
|
||||
# https://chromium.googlesource.com/chromiumos/platform/touchpad-tests
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*pnFalco:pvr*
|
||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*pn*Mario*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*pn*Butterfly*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*pn*Peppy*:
|
||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*pn*ZGB*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*pn*Parrot*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*bvn*coreboot*:pn*Leon*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*bvn*coreboot*:pn*Falco*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*bvn*coreboot*:pn*Wolf*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*svn*GOOGLE*:pn*Link*:
|
||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*pn*Alex*:
|
||||
libinput:name:Cypress APA Trackpad (cyapa):dmi:*svn*SAMSUNG*:pn*Lumpy*:
|
||||
libinput:name:Atmel maXTouch Touchpad:dmi:*svn*GOOGLE*:pn*Samus*:
|
||||
LIBINPUT_MODEL_CHROMEBOOK=1
|
||||
|
||||
##########################################
|
||||
# LENOVO
|
||||
##########################################
|
||||
|
||||
# X230 (Tablet)
|
||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPadX230*
|
||||
LIBINPUT_MODEL_LENOVO_X230=1
|
||||
|
||||
##########################################
|
||||
# System76
|
||||
##########################################
|
||||
|
||||
# Bonobo Professional
|
||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnSystem76*pvrbonp5*
|
||||
LIBINPUT_MODEL_SYSTEM76_BONOBO=1
|
||||
|
||||
# Clevo
|
||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*pnW740SU*rnW740SU*
|
||||
LIBINPUT_MODEL_CLEVO_W740SU=1
|
||||
|
||||
# Galago Ultra Pro
|
||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnSystem76*pvrgalu1*
|
||||
LIBINPUT_MODEL_SYSTEM76_GALAGO=1
|
||||
|
||||
# Kudu Professional
|
||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnSystem76*pvrkudp1*
|
||||
LIBINPUT_MODEL_SYSTEM76_KUDU=1
|
||||
25
udev/90-libinput-model-quirks.rules
Normal file
25
udev/90-libinput-model-quirks.rules
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Do not edit this file, it will be overwritten on update
|
||||
#
|
||||
# This file contains lookup rules for libinput model-specific quirks.
|
||||
# The contents of this file are a contract between libinput, udev rules and
|
||||
# the hwdb.
|
||||
# IT IS NOT A STABLE API AND SUBJECT TO CHANGE AT ANY TIME
|
||||
#
|
||||
# The hwdb database is in:
|
||||
# 90-libinput-model-quirks.hwdb
|
||||
|
||||
ACTION!="add|change", GOTO="libinput_model_quirks_end"
|
||||
KERNEL!="event*", GOTO="libinput_model_quirks_end"
|
||||
|
||||
# hwdb matches:
|
||||
#
|
||||
# libinput:<modalias>
|
||||
IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=libinput:", \
|
||||
GOTO="libinput_model_quirks_end"
|
||||
|
||||
# libinput:name:<name>:dmi:<dmi string>
|
||||
KERNELS=="input*", \
|
||||
IMPORT{builtin}="hwdb 'libinput:name:$attr{name}:$attr{[dmi/id]modalias}'", \
|
||||
GOTO="libinput_model_quirks_end"
|
||||
|
||||
LABEL="libinput_model_quirks_end"
|
||||
|
|
@ -6,4 +6,10 @@ libinput_device_group_CFLAGS = $(LIBUDEV_CFLAGS) $(GCC_CFLAGS)
|
|||
libinput_device_group_LDADD = $(LIBUDEV_LIBS)
|
||||
|
||||
udev_rulesdir=$(UDEV_DIR)/rules.d
|
||||
dist_udev_rules_DATA = 80-libinput-device-groups.rules
|
||||
dist_udev_rules_DATA = \
|
||||
80-libinput-device-groups.rules \
|
||||
90-libinput-model-quirks.rules
|
||||
|
||||
udev_hwdbdir=$(UDEV_DIR)/hwdb.d
|
||||
dist_udev_hwdb_DATA = \
|
||||
90-libinput-model-quirks.hwdb
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue