mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-26 01:40:08 +01:00
Merge branch 'master' into tablet-support
Conflicts: src/libinput.h
This commit is contained in:
commit
395c449c8e
49 changed files with 2727 additions and 716 deletions
63
configure.ac
63
configure.ac
|
|
@ -1,7 +1,7 @@
|
|||
AC_PREREQ([2.64])
|
||||
|
||||
m4_define([libinput_major_version], [0])
|
||||
m4_define([libinput_minor_version], [7])
|
||||
m4_define([libinput_minor_version], [8])
|
||||
m4_define([libinput_micro_version], [0])
|
||||
m4_define([libinput_version],
|
||||
[libinput_major_version.libinput_minor_version.libinput_micro_version])
|
||||
|
|
@ -30,7 +30,7 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
|
|||
# - If binary compatibility has been broken (eg removed or changed interfaces)
|
||||
# change to C+1:0:0
|
||||
# - If the interface is the same as the previous version, change to C:R+1:A
|
||||
LIBINPUT_LT_VERSION=6:0:1
|
||||
LIBINPUT_LT_VERSION=7:0:0
|
||||
AC_SUBST(LIBINPUT_LT_VERSION)
|
||||
|
||||
AM_SILENT_RULES([yes])
|
||||
|
|
@ -38,6 +38,7 @@ AM_SILENT_RULES([yes])
|
|||
# Check for programs
|
||||
AC_PROG_CC_C99
|
||||
AC_PROG_CXX # Only used by build C++ test
|
||||
AC_PROG_GREP
|
||||
|
||||
# Initialize libtool
|
||||
LT_PREREQ([2.2])
|
||||
|
|
@ -67,14 +68,55 @@ fi
|
|||
AC_SUBST(GCC_CFLAGS)
|
||||
AC_SUBST(GCC_CXXFLAGS)
|
||||
|
||||
AC_PATH_PROG(DOXYGEN, [doxygen])
|
||||
if test "x$DOXYGEN" = "x"; then
|
||||
AC_MSG_WARN([doxygen not found - required for documentation])
|
||||
have_doxygen="no"
|
||||
else
|
||||
have_doxygen="yes"
|
||||
AC_ARG_ENABLE([documentation],
|
||||
[AC_HELP_STRING([--enable-documentation],
|
||||
[Enable building the documentation (default=auto)])],
|
||||
[build_documentation="$enableval"],
|
||||
[build_documentation="auto"])
|
||||
|
||||
if test "x$build_documentation" = "xyes" -o "x$build_documentation" = "xauto"; then
|
||||
AC_PATH_PROG(DOXYGEN, doxygen)
|
||||
if test "x$DOXYGEN" = "x"; then
|
||||
if test "x$build_documentation" = "xyes"; then
|
||||
AC_MSG_ERROR([Documentation build requested but doxygen not found. Install doxygen or disable the documentation using --disable-documentation])
|
||||
fi
|
||||
else
|
||||
AC_MSG_CHECKING([for compatible doxygen version])
|
||||
doxygen_version=`$DOXYGEN --version`
|
||||
AS_VERSION_COMPARE([$doxygen_version], [1.6.0],
|
||||
[AC_MSG_RESULT([no])
|
||||
DOXYGEN=""],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[AC_MSG_RESULT([yes])])
|
||||
if test "x$DOXYGEN" = "x" -a "x$build_documentation" = "xyes"; then
|
||||
AC_MSG_ERROR([Doxygen $doxygen_version too old. Doxygen 1.6+ required for documentation build. Install required doxygen version or disable the documentation using --disable-documentation])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_PATH_PROG(DOT, dot)
|
||||
if test "x$DOT" = "x"; then
|
||||
if test "x$build_documentation" = "xyes"; then
|
||||
AC_MSG_ERROR([Documentation build requested but graphviz's dot not found. Install graphviz or disable the documentation using --disable-documentation])
|
||||
fi
|
||||
else
|
||||
AC_MSG_CHECKING([for compatible dot version])
|
||||
dot_version=`$DOT -V 2>&1|$GREP -oP '(?<=version\W)@<:@0-9.@:>@*(?=\W(.*))'`
|
||||
AS_VERSION_COMPARE([$dot_version], [2.26.0],
|
||||
[AC_MSG_RESULT([no])
|
||||
DOT=""],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[AC_MSG_RESULT([yes])])
|
||||
if test "x$DOT" = "x" -a "x$build_documentation" = "xyes"; then
|
||||
AC_MSG_ERROR([Graphviz dot $dot_version too old. Graphviz 2.26+ required for documentation build. Install required graphviz version or disable the documentation using --disable-documentation])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$DOXYGEN" != "x" -a "x$DOT" != "x"; then
|
||||
build_documentation="yes"
|
||||
else
|
||||
build_documentation="no"
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$have_doxygen" = "xyes"])
|
||||
|
||||
AC_ARG_ENABLE(event-gui,
|
||||
AS_HELP_STRING([--enable-event-gui], [Build the GUI event viewer (default=auto)]),
|
||||
|
|
@ -111,6 +153,7 @@ fi
|
|||
|
||||
AM_CONDITIONAL(HAVE_VALGRIND, [test "x$VALGRIND" != "x"])
|
||||
AM_CONDITIONAL(BUILD_TESTS, [test "x$build_tests" = "xyes"])
|
||||
AM_CONDITIONAL(BUILD_DOCS, [test "x$build_documentation" = "xyes"])
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
doc/Makefile
|
||||
|
|
@ -125,7 +168,7 @@ AC_OUTPUT
|
|||
AC_MSG_RESULT([
|
||||
Prefix ${prefix}
|
||||
|
||||
Build documentation ${have_doxygen}
|
||||
Build documentation ${build_documentation}
|
||||
Build tests ${build_tests}
|
||||
Tests use valgrind ${VALGRIND}
|
||||
Build GUI event tool ${build_eventgui}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,40 @@
|
|||
EXTRA_DIST = touchpad-tap-state-machine.svg touchpad-softbutton-state-machine.svg
|
||||
|
||||
if HAVE_DOXYGEN
|
||||
if BUILD_DOCS
|
||||
|
||||
noinst_DATA = html/index.html
|
||||
|
||||
header_files = \
|
||||
$(top_srcdir)/src/libinput.h \
|
||||
$(top_srcdir)/README.txt
|
||||
$(top_srcdir)/README.txt \
|
||||
$(srcdir)/absolute-axes.dox \
|
||||
$(srcdir)/clickpad-softbuttons.dox \
|
||||
$(srcdir)/device-configuration-via-udev.dox \
|
||||
$(srcdir)/normalization-of-relative-motion.dox \
|
||||
$(srcdir)/palm-detection.dox \
|
||||
$(srcdir)/scrolling.dox \
|
||||
$(srcdir)/seats.dox \
|
||||
$(srcdir)/t440-support.dox \
|
||||
$(srcdir)/tapping.dox
|
||||
|
||||
html/index.html: libinput.doxygen $(header_files)
|
||||
$(AM_V_GEN)$(DOXYGEN) $<
|
||||
diagram_files = \
|
||||
$(srcdir)/dot/seats-sketch.gv \
|
||||
$(srcdir)/dot/seats-sketch-libinput.gv \
|
||||
$(srcdir)/svg/button-scrolling.svg \
|
||||
$(srcdir)/svg/edge-scrolling.svg \
|
||||
$(srcdir)/svg/palm-detection.svg \
|
||||
$(srcdir)/svg/twofinger-scrolling.svg
|
||||
|
||||
html/index.html: libinput.doxygen $(header_files) $(diagram_files)
|
||||
$(AM_V_GEN)(cat $<; \
|
||||
echo "INPUT = $(header_files)"; \
|
||||
) | $(DOXYGEN) -
|
||||
|
||||
clean-local:
|
||||
$(AM_V_at)rm -rf html
|
||||
|
||||
doc_src= $(shell find html -type f -printf "html/%P\n" 2>/dev/null)
|
||||
EXTRA_DIST += $(builddir)/html/index.html $(doc_src)
|
||||
EXTRA_DIST += $(builddir)/html/index.html $(doc_src) $(diagram_files) $(header_files)
|
||||
|
||||
endif
|
||||
|
||||
|
|
|
|||
130
doc/absolute-axes.dox
Normal file
130
doc/absolute-axes.dox
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
@page absolute_axes Absolute axes
|
||||
|
||||
Devices with absolute axes are those that send positioning data for an axis in
|
||||
a device-specific coordinate range, defined by a minimum and a maximum value.
|
||||
Compare this to relative devices (e.g. a mouse) that can only detect
|
||||
directional data, not positional data.
|
||||
|
||||
libinput supports three types of devices with absolute axes:
|
||||
|
||||
- multi-touch screens
|
||||
- single-touch screens
|
||||
- graphics tablets (currently WIP)
|
||||
|
||||
Touchpads are technically absolute devices but libinput converts the axis values
|
||||
to directional motion and posts events as relative events. Touchpads do not count
|
||||
as absolute devices in libinput.
|
||||
|
||||
For all absolute devices in libinput, the default unit for x/y coordinates is
|
||||
in mm off the top left corner on the device, or more specifically off the
|
||||
device's sensor.
|
||||
|
||||
@section absolute_axes_handling Handling of absolute coordinates
|
||||
|
||||
In most use-cases, absolute input devices are mapped to a single screen. For
|
||||
direct input devices such as touchscreens the aspect ratio of the screen and
|
||||
the device match. Mapping the input device position to the output position is
|
||||
thus a simple mapping between two coordinates. libinput provides the API for
|
||||
this with
|
||||
|
||||
- libinput_event_pointer_get_absolute_x_transformed() for pointer events
|
||||
- libinput_event_touch_get_x_transformed() for touch events
|
||||
|
||||
libinput's API only provides the call to map into a single coordinate range.
|
||||
If the coordinate range has an offset, the compositor is responsible for
|
||||
applying that offset after the mapping. For example, if the device is mapped
|
||||
to the right of two outputs, add the output offset to the transformed
|
||||
coordinate.
|
||||
|
||||
@section absolute_axes_nores Devices without x/y resolution
|
||||
|
||||
An absolute device that does not provide a valid resolution is considered
|
||||
buggy and must be fixed in the kernel. Some touchpad devices that do not
|
||||
provide resolution, those devices are correctly handled within libinput
|
||||
(touchpads are not absolute devices, as mentioned above).
|
||||
|
||||
@section calibration Calibration of absolute devices
|
||||
|
||||
Absolute devices may require calibration to map precisely into the output
|
||||
range required. This is done by setting a transformation matrix, see
|
||||
libinput_device_config_calibration_set_matrix() which is applied to
|
||||
each input coordinate.
|
||||
|
||||
@f[
|
||||
\begin{pmatrix}
|
||||
cos\theta & -sin\theta & xoff \\
|
||||
sin\theta & cos\theta & yoff \\
|
||||
0 & 0 & 1
|
||||
\end{pmatrix} \begin{pmatrix}
|
||||
x \\ y \\ 1
|
||||
\end{pmatrix}
|
||||
@f]
|
||||
|
||||
@f$\theta@f$ is the rotation angle. The offsets @f$xoff@f$ and @f$yoff@f$ are
|
||||
specified in device dimensions, i.e. a value of 1 equals one device width
|
||||
or height. Note that rotation applies to the device's origin, rotation
|
||||
usually requires an offset to move the coordinates back into the original
|
||||
range.
|
||||
|
||||
The most comon matrices are:
|
||||
|
||||
- 90 degree clockwise:
|
||||
@f$
|
||||
\begin{pmatrix}
|
||||
0 & -1 & 1 \\
|
||||
1 & 0 & 0 \\
|
||||
0 & 0 & 1
|
||||
\end{pmatrix}
|
||||
@f$
|
||||
|
||||
- 180 degree clockwise:
|
||||
@f$
|
||||
\begin{pmatrix}
|
||||
-1 & 0 & 1 \\
|
||||
0 & -1 & 1 \\
|
||||
0 & 0 & 1
|
||||
\end{pmatrix}
|
||||
@f$
|
||||
|
||||
- 270 degree clockwise:
|
||||
@f$
|
||||
\begin{pmatrix}
|
||||
0 & 1 & 0 \\
|
||||
-1 & 0 & 1 \\
|
||||
0 & 0 & 1
|
||||
\end{pmatrix}
|
||||
@f$
|
||||
|
||||
- reflection along y axis:
|
||||
@f$
|
||||
\begin{pmatrix}
|
||||
-1 & 0 & 1 \\
|
||||
1 & 0 & 0 \\
|
||||
0 & 0 & 1
|
||||
\end{pmatrix}
|
||||
@f$
|
||||
|
||||
See Wikipedia's
|
||||
<a href="http://en.wikipedia.org/wiki/Transformation_matrix">Transformation
|
||||
Matrix article</a> for more information on the matrix maths.
|
||||
|
||||
See libinput_device_config_calibration_get_default_matrix() for how these
|
||||
matrices must be supplied to libinput.
|
||||
|
||||
@section absolute_axes_nonorm Why x/y coordinates are not normalized
|
||||
|
||||
x/y are not given in @ref motion_normalization "normalized coordinates"
|
||||
([0..1]) for one simple reason: the aspect ratio of virtually all current
|
||||
devices is something other than 1:1. A normalized axes thus is only useful to
|
||||
determine that the stylus is e.g. at 78% from the left, 34% from the top of
|
||||
the device. Without knowing the per-axis resolution, these numbers are
|
||||
meaningless. Worse, calculation based on previous coordinates is simply wrong:
|
||||
a movement from 0/0 to 50%/50% is not a 45% degree line.
|
||||
|
||||
This could be alleviated by providing resolution and information about the
|
||||
aspect ratio to the caller. Which shifts processing and likely errors into the
|
||||
caller for little benefit. Providing the x/y axes in mm from the outset
|
||||
removes these errors.
|
||||
|
||||
*/
|
||||
80
doc/clickpad-softbuttons.dox
Normal file
80
doc/clickpad-softbuttons.dox
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
@page clickpad_softbuttons Clickpad software button behavior
|
||||
|
||||
Clickpad is the name given to touchpads without physical buttons below the
|
||||
touchpad. Instead, the whole touchpad acts as a button and left or right
|
||||
button clicks are distinguished by the location and/or number of fingers on
|
||||
the touchpad. <a href="http://www.synaptics.com/en/clickpad.php">"ClickPad" is
|
||||
a trademark by Synaptics Inc.</a> but for simplicity we refer to any
|
||||
touchpad with the above feature as Clickpad, regardless of the manufacturer.
|
||||
|
||||
A clickpad is always marked with the <a
|
||||
href="https://www.kernel.org/doc/Documentation/input/event-codes.txt">INPUT_PROP_BUTTONPAD</a> property.
|
||||
To perform a right-click on a Clickpad, libinput provides @ref
|
||||
software_buttons and @ref clickfinger.
|
||||
|
||||
In the page below, the term "click" shall refer to a physical button press
|
||||
and/or release of the touchpad, the term "button event" refers to the events
|
||||
generated by libinput and passed to the caller in response to a click.
|
||||
|
||||
@section software_buttons Software button areas
|
||||
|
||||
On most clickpads, this is the default behavior. The bottom of the touchpad
|
||||
is split in the middle to generate left or right button events on click. The
|
||||
height of the button area depends on the hardware but is usually around
|
||||
10mm.
|
||||
|
||||
@dot
|
||||
digraph G {
|
||||
clickpad [
|
||||
shape = "record";
|
||||
label = "{\nMain\nArea\n\n|{LEFT|RIGHT}}";
|
||||
]
|
||||
}
|
||||
@enddot
|
||||
|
||||
Left, right and middle button events can be triggered as follows:
|
||||
- if a finger is in the main area or the left button area, a click generates
|
||||
left button events.
|
||||
- if a finger is in the right area, a click generates right button events.
|
||||
- if there is a finger in both the left and right button area, a click
|
||||
generates middle button events.
|
||||
|
||||
If fingers are down in the main area in addition to fingers in the
|
||||
left or right button area, those fingers are are ignored.
|
||||
A release event always releases the buttons logically down, regardless of
|
||||
the current finger position
|
||||
|
||||
The movement of a finger can alter the button area behavior:
|
||||
- if a finger starts in the main area and moves into the software button
|
||||
area, the software buttons do not apply to that finger
|
||||
- a finger in the software button area does not move the pointer
|
||||
- if a finger moves out out of the button area it will control the pointer
|
||||
if it's the first finger in the main area
|
||||
- once a finger has moved out of the button area, it cannot move back in and
|
||||
trigger a right or middle button event
|
||||
|
||||
@section clickfinger Clickfinger behavior
|
||||
|
||||
This is the default behavior on Apple touchpads.
|
||||
Here, a left, right, middle button event is generated when one, two, or
|
||||
three fingers are held down on the touchpad when a physical click is
|
||||
generated. The location of the fingers does not matter and there are no
|
||||
software-defined button areas.
|
||||
|
||||
The Xorg synaptics driver uses 30% of the touchpad dimensions as threshold,
|
||||
libinput does not have this restriction. If two fingers are on the pad
|
||||
while clicking, that is a two-finger click.
|
||||
|
||||
@section special_clickpads Special Clickpads
|
||||
|
||||
The Lenovo *40 series laptops have a clickpad that provides two software button sections, one at
|
||||
the top and one at the bottom. See @ref t440_support "Lenovo *40 series touchpad support"
|
||||
for details on the top software button.
|
||||
|
||||
Some Clickpads, notably some Cypress ones, perform right button detection in
|
||||
firmware and appear to userspace as if the touchpad had physical buttons.
|
||||
While physically clickpads, these are not handled by the software and
|
||||
treated like traditional touchpads.
|
||||
|
||||
*/
|
||||
39
doc/device-configuration-via-udev.dox
Normal file
39
doc/device-configuration-via-udev.dox
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
@page udev_config Static device configuration via udev
|
||||
|
||||
libinput supports some static configuration through udev properties.
|
||||
These propertiesare read when the device is initially added
|
||||
to libinput's device list, i.e. before the @ref
|
||||
LIBINPUT_EVENT_DEVICE_ADDED event is generated.
|
||||
|
||||
The following udev properties are supported:
|
||||
<dl>
|
||||
<dt>LIBINPUT_CALIBRATION_MATRIX</dt>
|
||||
<dd>Sets the calibration matrix, see
|
||||
libinput_device_config_calibration_get_default_matrix(). If unset,
|
||||
defaults to the identity matrix.</dd>
|
||||
<dt>ID_SEAT</dt>
|
||||
<dd>Assigns the physical seat for this device. See
|
||||
libinput_seat_get_physical_name(). Defaults to "seat0".</dd>
|
||||
<dt>WL_SEAT</dt>
|
||||
<dd>Assigns the logical seat for this device. See
|
||||
libinput_seat_get_logical_name()
|
||||
context. Defaults to "default".</dd>
|
||||
<dt>MOUSE_DPI</dt>
|
||||
<dd>HW resolution and sampling frequency of a relative pointer device.
|
||||
See @ref motion_normalization for details.
|
||||
</dd>
|
||||
<dt>MOUSE_WHEEL_CLICK_ANGLE</dt>
|
||||
<dd>The angle in degrees for each click on a mouse wheel. See
|
||||
libinput_pointer_get_axis_source() for details.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
Below is an example udev rule to assign "seat1" to a device from vendor
|
||||
0x012a with the model ID of 0x034b.
|
||||
@code
|
||||
ACTION=="add|change", KERNEL=="event[0-9]*", ENV{ID_VENDOR_ID}=="012a", \
|
||||
ENV{ID_MODEL_ID}=="034b", ENV{ID_SEAT}="seat1"
|
||||
@endcode
|
||||
|
||||
*/
|
||||
29
doc/dot/seats-sketch-libinput.gv
Normal file
29
doc/dot/seats-sketch-libinput.gv
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
digraph seats_libinput
|
||||
{
|
||||
rankdir="BT";
|
||||
node [
|
||||
shape="box";
|
||||
]
|
||||
|
||||
ctx1 [label="libinput context 1"; URL="\ref libinput"];
|
||||
ctx2 [label="libinput context 2"; URL="\ref libinput"];
|
||||
|
||||
seat0 [ label="seat phys 0 logical A"];
|
||||
seat1 [ label="seat phys 0 logical B"];
|
||||
seat2 [ label="seat phys 1 logical C"];
|
||||
|
||||
dev1 [label="device 'Foo'"];
|
||||
dev2 [label="device 'Bar'"];
|
||||
dev3 [label="device 'Spam'"];
|
||||
dev4 [label="device 'Egg'"];
|
||||
|
||||
ctx1 -> dev1
|
||||
ctx1 -> dev2
|
||||
ctx1 -> dev3
|
||||
ctx2 -> dev4
|
||||
|
||||
dev1 -> seat0
|
||||
dev2 -> seat0
|
||||
dev3 -> seat1
|
||||
dev4 -> seat2
|
||||
}
|
||||
51
doc/dot/seats-sketch.gv
Normal file
51
doc/dot/seats-sketch.gv
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
digraph seats
|
||||
{
|
||||
rankdir="BT";
|
||||
node [
|
||||
shape="box";
|
||||
]
|
||||
|
||||
kernel [label="Kernel"];
|
||||
|
||||
event0 [URL="\ref libinput_event"];
|
||||
event1 [URL="\ref libinput_event"];
|
||||
event2 [URL="\ref libinput_event"];
|
||||
event3 [URL="\ref libinput_event"];
|
||||
|
||||
pseat0 [label="phys seat0"; URL="\ref libinput_seat_get_physical_name"];
|
||||
pseat1 [label="phys seat1"; URL="\ref libinput_seat_get_physical_name"];
|
||||
|
||||
lseatA [label="logical seat A"; URL="\ref libinput_seat_get_logical_name"];
|
||||
lseatB [label="logical seat B"; URL="\ref libinput_seat_get_logical_name"];
|
||||
lseatC [label="logical seat C"; URL="\ref libinput_seat_get_logical_name"];
|
||||
|
||||
ctx1 [label="libinput context 1"; URL="\ref libinput"];
|
||||
ctx2 [label="libinput context 2"; URL="\ref libinput"];
|
||||
|
||||
dev1 [label="device 'Foo'"];
|
||||
dev2 [label="device 'Bar'"];
|
||||
dev3 [label="device 'Spam'"];
|
||||
dev4 [label="device 'Egg'"];
|
||||
|
||||
kernel -> event0
|
||||
kernel -> event1
|
||||
kernel -> event2
|
||||
kernel -> event3
|
||||
|
||||
event0 -> pseat0
|
||||
event1 -> pseat0
|
||||
event2 -> pseat0
|
||||
event3 -> pseat1
|
||||
|
||||
pseat0 -> ctx1
|
||||
pseat1 -> ctx2
|
||||
|
||||
ctx1 -> lseatA
|
||||
ctx1 -> lseatB
|
||||
ctx2 -> lseatC
|
||||
|
||||
lseatA -> dev1
|
||||
lseatA -> dev2
|
||||
lseatB -> dev3
|
||||
lseatC -> dev4
|
||||
}
|
||||
|
|
@ -842,7 +842,8 @@ EXAMPLE_RECURSIVE = NO
|
|||
# that contain images that are to be included in the documentation (see the
|
||||
# \image command).
|
||||
|
||||
IMAGE_PATH =
|
||||
IMAGE_PATH = @top_srcdir@/doc/svg \
|
||||
@top_srcdir@/doc/dot
|
||||
|
||||
# The INPUT_FILTER tag can be used to specify a program that doxygen should
|
||||
# invoke to filter for each input file. Doxygen will invoke the filter program
|
||||
|
|
@ -1421,7 +1422,7 @@ FORMULA_TRANSPARENT = YES
|
|||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
USE_MATHJAX = NO
|
||||
USE_MATHJAX = YES
|
||||
|
||||
# When MathJax is enabled you can set the default output format to be used for
|
||||
# the MathJax output. See the MathJax site (see:
|
||||
|
|
@ -2250,7 +2251,7 @@ DOT_PATH =
|
|||
# command).
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOTFILE_DIRS =
|
||||
DOTFILE_DIRS = @top_srcdir@/doc/dot
|
||||
|
||||
# The MSCFILE_DIRS tag can be used to specify one or more directories that
|
||||
# contain msc files that are included in the documentation (see the \mscfile
|
||||
|
|
|
|||
54
doc/normalization-of-relative-motion.dox
Normal file
54
doc/normalization-of-relative-motion.dox
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
@page motion_normalization Normalization of relative motion
|
||||
|
||||
Most relative input devices generate input in so-called "mickeys". A
|
||||
mickey is in device-specific units that depend on the resolution
|
||||
of the sensor. Most optical mice use sensors with 1000dpi resolution, but
|
||||
some devices range from 100dpi to well above 8000dpi.
|
||||
|
||||
Without a physical reference point, a relative coordinate cannot be
|
||||
interpreted correctly. A delta of 10 mickeys may be a millimeter of
|
||||
physical movement or 10 millimeters, depending on the sensor. This
|
||||
affects pointer acceleration in libinput and interpretation of relative
|
||||
coordinates in callers.
|
||||
|
||||
libinput normalizes all relative input to a physical resolution of
|
||||
1000dpi, the same delta from two different devices thus represents the
|
||||
same physical movement of those two devices (within sensor error
|
||||
margins).
|
||||
|
||||
Devices usually do not advertise their resolution and libinput relies on
|
||||
the udev property <b>MOUSE_DPI</b> for this information. This property is usually
|
||||
set via the <a
|
||||
href="http://cgit.freedesktop.org/systemd/systemd/tree/hwdb/70-mouse.hwdb">udev hwdb</a>.
|
||||
|
||||
The format of the property for single-resolution mice is:
|
||||
@code
|
||||
MOUSE_DPI=resolution@frequency
|
||||
@endcode
|
||||
|
||||
The resolution is in dots per inch, the frequency in Hz.
|
||||
The format of the property for multi-resolution mice may list multiple
|
||||
resolutions and frequencies:
|
||||
@code
|
||||
MOUSE_DPI=r1@f1 *r2@f2 r3@f3
|
||||
@endcode
|
||||
|
||||
The default frequency must be pre-fixed with an asterisk.
|
||||
|
||||
For example, these two properties are valid:
|
||||
@code
|
||||
MOUSE_DPI=800@125
|
||||
MOUSE_DPI=400@125 800@125 *1000@500 5500@500
|
||||
@endcode
|
||||
|
||||
The behavior for a malformed property is undefined.
|
||||
|
||||
If the property is unset, libinput assumes the resolution is 1000dpi.
|
||||
|
||||
Note that HW does not usually provide information about run-time
|
||||
resolution changes, libinput will thus not detect when a resolution
|
||||
changes to the non-default value.
|
||||
|
||||
*/
|
||||
|
||||
52
doc/palm-detection.dox
Normal file
52
doc/palm-detection.dox
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
@page palm_detection Palm detection
|
||||
|
||||
Palm detection tries to identify accidental touches while typing.
|
||||
|
||||
On most laptops typing on the keyboard generates accidental touches on the
|
||||
touchpad with the palm (usually the area below the thumb). This can lead to
|
||||
cursor jumps or accidental clicks.
|
||||
|
||||
Interference from a palm depends on the size of the touchpad and the position
|
||||
of the user's hand. Data from touchpads showed that almost all palm events on a
|
||||
Lenovo T440 happened in the left-most and right-most 5% of the touchpad. The
|
||||
T440 series has one of the largest touchpads, other touchpads are less
|
||||
affected by palm touches.
|
||||
|
||||
@section palm_exclusion_zones Palm exclusion zones
|
||||
|
||||
libinput enables palm detection on the edge of the touchpad. Two exclusion
|
||||
zones are defined on the left and right edge of the touchpad.
|
||||
If a touch starts in the exclusion zone, it is considered a palm and the
|
||||
touch point is ignored. However, for fast cursor movements across the
|
||||
screen, it is common for a finger to start inside an exclusion zone and move
|
||||
rapidly across the touchpad. libinput detects such movements and avoids palm
|
||||
detection on such touch sequences.
|
||||
|
||||
In the diagram below, the exclusion zones are painted red.
|
||||
Touch 'A' starts inside the exclusion zone and moves
|
||||
almost vertically. It is considered a palm and ignored for cursor movement,
|
||||
despite moving out of the exclusion zone.
|
||||
|
||||
Touch 'B' starts inside the exclusion zone but moves horizontally out of the
|
||||
zone. It is considered a valid touch and controls the cursor.
|
||||
|
||||
@image html palm-detection.svg
|
||||
|
||||
@section trackpoint-disabling Palm detection during trackpoint use
|
||||
|
||||
If a device provides a <a
|
||||
href="http://en.wikipedia.org/wiki/Pointing_stick">trackpoint</a>, it is
|
||||
usually located above the touchpad. This increases the likelyhood of
|
||||
accidental touches whenever the trackpoint is used.
|
||||
|
||||
libinput disables the touchpad whenver it detects trackpoint activity for a
|
||||
certain timeout until after trackpoint activity stops. Touches generated
|
||||
during this timeout will not move the pointer, and touches started during
|
||||
this timeout will likewise not move the pointer (allowing for a user to rest
|
||||
the palm on the touchpad while using the trackstick).
|
||||
If the touchpad is disabled, the @ref t440_support "top software buttons"
|
||||
remain enabled.
|
||||
|
||||
|
||||
*/
|
||||
50
doc/scrolling.dox
Normal file
50
doc/scrolling.dox
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
@page scrolling Scrolling
|
||||
|
||||
libinput supports three different types of scrolling behavior.
|
||||
|
||||
@section twofinger_scrolling Two-finger scrolling
|
||||
|
||||
The default on two-finger capable touchpads (almost all modern touchpads are
|
||||
capable of detecting two fingers). Scrolling is triggered by two fingers
|
||||
being placed on the surface of the touchpad, then moving those fingers
|
||||
vertically or horizontally.
|
||||
|
||||
@image html twofinger-scrolling.svg "Vertical and horizontal two-finger scrolling"
|
||||
|
||||
For scrolling to trigger, a built-in distance threshold has to be met but once
|
||||
engaged any movement will scroll. In other words, to start scrolling a
|
||||
sufficiently large movement is required, once scrolling tiny amounts of
|
||||
movements will translate into tiny scroll movements.
|
||||
|
||||
Scrolling in both directions at once is possible by meeting the required
|
||||
distance thresholds to enable each direction separately.
|
||||
|
||||
@section edge_scrolling Edge scrolling
|
||||
|
||||
On some touchpads, edge scrolling is available, triggered by moving a single
|
||||
finger along the right edge (vertical scroll) or bottom edge (horizontal
|
||||
scroll).
|
||||
|
||||
@image html edge-scrolling.svg "Vertical and horizontal edge scrolling"
|
||||
|
||||
Due to the layout of the edges, diagonal scrolling is not possible.
|
||||
|
||||
Edge scrolling conflicts with @ref clickpad_softbuttons and is
|
||||
not usually available on clickpads.
|
||||
|
||||
@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
|
||||
<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
|
||||
button for button scrolling (even when the touchpad is disabled).
|
||||
|
||||
*/
|
||||
73
doc/seats.dox
Normal file
73
doc/seats.dox
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
@page seats Seats
|
||||
|
||||
Each device in libinput is assigned to one seat.
|
||||
A seat has two identifiers, the physical name and the logical name. The
|
||||
physical name is summarized as the list of devices a process on the same
|
||||
physical seat has access to. The logical seat name is the seat name for a
|
||||
logical group of devices. A compositor may use that to create additonal
|
||||
seats as independent device sets. Alternatively, a compositor may limit
|
||||
itself to a single logical seat, leaving a second compositor to manage
|
||||
devices on the other logical seats.
|
||||
|
||||
@section Overview
|
||||
|
||||
Below is an illustration of how physical seats and logical seats interact:
|
||||
|
||||
@dotfile seats-sketch.gv
|
||||
|
||||
The devices "Foo", "Bar" and "Spam" share the same physical seat and are
|
||||
thus available in the same libinput context. Only "Foo" and "Bar" share the
|
||||
same logical seat. The device "Egg" is not available in the libinput context
|
||||
associated with the physical seat 0.
|
||||
|
||||
The above graph is for illustration purposes only. In libinput, a struct
|
||||
@ref libinput_seat comprises both physical seat and logical seat. From a
|
||||
caller's point-of-view the above device layout is presented as:
|
||||
|
||||
@dotfile seats-sketch-libinput.gv
|
||||
|
||||
Thus, devices "Foo" and "Bar" both reference the same struct @ref
|
||||
libinput_seat, all other devices reference their own respective seats.
|
||||
|
||||
@section seats_and_features The effect of seat assignment
|
||||
|
||||
A logical set is interprested as a group of devices that usually belong to a
|
||||
single user that interacts with a computer. Thus, the devices are
|
||||
semantically related. This means for devices within the same logical seat:
|
||||
|
||||
- if the same button is pressed on different devices, the button should only
|
||||
be considered logically pressed once.
|
||||
- if the same button is released on one device, the button should be
|
||||
considered logically down if still down on another device.
|
||||
- if two different buttons or keys are pressed on different devices, the
|
||||
logical state is that of both buttons/keys down.
|
||||
- if a button is pressed on one device and another device moves, this should
|
||||
count as dragging.
|
||||
- if two touches are down on different devices, the logical state is that of
|
||||
two touches down.
|
||||
|
||||
libinput provides functions to aid with the above:
|
||||
libinput_event_pointer_get_seat_button_count(),
|
||||
libinput_event_keyboard_get_seat_key_count(), and
|
||||
libinput_event_touch_get_seat_slot().
|
||||
|
||||
Internally, libinput counts devices within the same logical seat as related.
|
||||
Cross-device features only activate if all required devices are in the same
|
||||
logical seat. For example, libinput will only activate the top software
|
||||
buttons (see @ref t440_support) if both trackstick and touchpad are assigned
|
||||
to the same logical seat.
|
||||
|
||||
|
||||
@section changing_seats Changing seats
|
||||
|
||||
A device may change the logical seat it is assigned to at runtime with
|
||||
libinput_device_set_seat_logical_name(). The physical seat is immutable and
|
||||
may not be changed.
|
||||
|
||||
Changing the logical seat for a device is equivalent to unplugging the
|
||||
device and plugging it back in with the new logical seat. No device state
|
||||
carries over across a logical seat change.
|
||||
|
||||
|
||||
*/
|
||||
292
doc/svg/button-scrolling.svg
Normal file
292
doc/svg/button-scrolling.svg
Normal file
|
|
@ -0,0 +1,292 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.1"
|
||||
width="393"
|
||||
height="438.42642"
|
||||
id="svg2">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
id="path3710"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
id="path3707"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lstart-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
id="path3707-7"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lend-2"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
id="path3710-3"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
</defs>
|
||||
<g
|
||||
transform="translate(-34.54288,-505.04248)"
|
||||
id="layer3"
|
||||
style="display:inline">
|
||||
<rect
|
||||
width="58"
|
||||
height="58"
|
||||
x="386"
|
||||
y="65.208893"
|
||||
transform="translate(-343.95712,527.33359)"
|
||||
id="rect11748"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
width="58"
|
||||
height="58"
|
||||
x="122.04288"
|
||||
y="592.54248"
|
||||
id="rect11778"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
width="58"
|
||||
height="58"
|
||||
x="202.04288"
|
||||
y="592.54248"
|
||||
id="rect11780"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
width="58"
|
||||
height="58"
|
||||
x="282.04288"
|
||||
y="592.54248"
|
||||
id="rect11782"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
width="58"
|
||||
height="58"
|
||||
x="362.04288"
|
||||
y="592.54248"
|
||||
id="rect11784"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
width="58"
|
||||
height="58"
|
||||
x="82.042877"
|
||||
y="512.54248"
|
||||
id="rect11786"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
width="58"
|
||||
height="58"
|
||||
x="162.04288"
|
||||
y="512.54248"
|
||||
id="rect11788"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
width="58"
|
||||
height="58"
|
||||
x="242.04288"
|
||||
y="512.54248"
|
||||
id="rect11790"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
width="58"
|
||||
height="58"
|
||||
x="322.04288"
|
||||
y="512.54248"
|
||||
id="rect11792"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<text
|
||||
x="57.815342"
|
||||
y="633.93506"
|
||||
id="text11796"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
||||
x="57.815342"
|
||||
y="633.93506"
|
||||
id="tspan11798"
|
||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">C</tspan></text>
|
||||
<text
|
||||
x="137.81534"
|
||||
y="633.93506"
|
||||
id="text11800"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
||||
x="137.81534"
|
||||
y="633.93506"
|
||||
id="tspan11802"
|
||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">V</tspan></text>
|
||||
<text
|
||||
x="217.81534"
|
||||
y="633.93506"
|
||||
id="text11804"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
||||
x="217.81534"
|
||||
y="633.93506"
|
||||
id="tspan11806"
|
||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">B</tspan></text>
|
||||
<text
|
||||
x="297.81534"
|
||||
y="633.93506"
|
||||
id="text11808"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
||||
x="297.81534"
|
||||
y="633.93506"
|
||||
id="tspan11810"
|
||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">N</tspan></text>
|
||||
<text
|
||||
x="377.81534"
|
||||
y="633.93506"
|
||||
id="text11812"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
||||
x="377.81534"
|
||||
y="633.93506"
|
||||
id="tspan11814"
|
||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">M</tspan></text>
|
||||
<text
|
||||
x="337.81534"
|
||||
y="553.93506"
|
||||
id="text11816"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
||||
x="337.81534"
|
||||
y="553.93506"
|
||||
id="tspan11818"
|
||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">J</tspan></text>
|
||||
<text
|
||||
x="257.81534"
|
||||
y="553.93506"
|
||||
id="text11820"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
||||
x="257.81534"
|
||||
y="553.93506"
|
||||
id="tspan11822"
|
||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">H</tspan></text>
|
||||
<text
|
||||
x="177.81534"
|
||||
y="553.93506"
|
||||
id="text11824"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
||||
x="177.81534"
|
||||
y="553.93506"
|
||||
id="tspan11826"
|
||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">G</tspan></text>
|
||||
<text
|
||||
x="97.815338"
|
||||
y="553.93506"
|
||||
id="text11828"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Utopia;-inkscape-font-specification:Utopia"><tspan
|
||||
x="97.815338"
|
||||
y="553.93506"
|
||||
id="tspan11830"
|
||||
style="font-size:36px;fill:#ffffff;fill-opacity:1;font-family:Arial;-inkscape-font-specification:Arial">F</tspan></text>
|
||||
<path
|
||||
d="m 590.15063,48.238251 a 12.628045,12.628045 0 1 1 -25.25609,0 12.628045,12.628045 0 1 1 25.25609,0 z"
|
||||
transform="matrix(1.5,0,0,1.5,-635.24402,504.05633)"
|
||||
id="path11832"
|
||||
style="color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#e50000;stroke-width:2.33333325;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<g
|
||||
transform="matrix(0.98314313,0.18283763,-0.18283763,0.98314313,38.34468,-177.34601)"
|
||||
id="g3663-9-5">
|
||||
<path
|
||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
||||
id="path2820-6-6"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 360.32021,827.78041 c -15.74169,-35.7991 -29.44655,-66.92657 -30.45523,-69.17214 -7.08929,-15.78239 -10.8761,-32.88254 -9.6176,-43.43026 1.39575,-11.69796 7.19746,-18.50389 18.22574,-21.38044 5.18218,-1.35169 8.54724,-1.76827 12.41155,-1.53649 4.43642,0.26609 6.95929,0.93715 11.03011,2.93391 3.93491,1.9301 8.0085,5.56248 10.68932,9.53159 3.68818,5.46055 26.56068,50.9623 49.57778,98.62829 16.60192,34.38082 37.06388,77.41994 36.89013,77.59369 -0.13286,0.13286 -69.01932,11.92114 -69.66286,11.92114 -0.27909,0 -12.00972,-26.24842 -29.08894,-65.08929 z"
|
||||
id="path2824-1-1"
|
||||
style="color:#000000;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 334.75785,756.75053 c -7.08929,-15.78239 -10.28437,-26.89033 -9.02587,-37.43805 1.39575,-11.69796 5.8085,-16.73613 16.83678,-19.61268 12.44766,-3.59459 20.03902,-1.91353 27.39013,8.75815 11.42622,25.66382 13.40166,29.05484 15.06365,35.48866 -0.13286,0.13286 -42.89663,15.49027 -44.57776,16.18518 -1.72922,0.71479 -4.94789,-2.09377 -5.68693,-3.38126 z"
|
||||
id="path2824-7-1-4"
|
||||
style="opacity:0.92000002;color:#000000;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-34.54288,-505.04248)"
|
||||
id="layer1"
|
||||
style="display:inline">
|
||||
<rect
|
||||
width="135"
|
||||
height="63"
|
||||
x="55.166245"
|
||||
y="782.95221"
|
||||
id="rect11656"
|
||||
style="color:#000000;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
width="135"
|
||||
height="63"
|
||||
x="258.97995"
|
||||
y="782.95221"
|
||||
id="rect11656-7"
|
||||
style="color:#000000;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<rect
|
||||
width="64.642883"
|
||||
height="68.303299"
|
||||
x="192.25995"
|
||||
y="778.95221"
|
||||
id="rect11656-1"
|
||||
style="color:#000000;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<g
|
||||
transform="matrix(-0.96540637,0.18283763,0.17953908,0.98314313,431.3343,62.30631)"
|
||||
id="g3663-9">
|
||||
<path
|
||||
d="m 359.78441,828.85231 -28.35583,-65.06155 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 47.45034,95.30837 47.45034,95.30837 l -63.38022,25.11033 z"
|
||||
id="path2820-6"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.00914431px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 360.32021,827.78041 c 0,0 -29.44655,-66.92657 -30.45523,-69.17214 -7.08929,-15.78239 -10.8761,-32.88254 -9.6176,-43.43026 1.39575,-11.69796 7.19746,-18.50389 18.22574,-21.38044 5.18218,-1.35169 8.54724,-1.76827 12.41155,-1.53649 4.43642,0.26609 6.95929,0.93715 11.03011,2.93391 3.93491,1.9301 8.0085,5.56248 10.68932,9.53159 3.68818,5.46055 49.57778,98.62829 49.57778,98.62829 0,0 -61.86167,24.42554 -61.86167,24.42554 z"
|
||||
id="path2824-1"
|
||||
style="color:#000000;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.00201829;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 334.75785,756.75053 c -7.08929,-15.78239 -10.28437,-26.89033 -9.02587,-37.43805 1.39575,-11.69796 5.8085,-16.73613 16.83678,-19.61268 12.44766,-3.59459 20.03902,-1.91353 27.39013,8.75815 11.42622,25.66382 13.40166,29.05484 15.06365,35.48866 -0.13286,0.13286 -42.89663,15.49027 -44.57776,16.18518 -1.72922,0.71479 -4.94789,-2.09377 -5.68693,-3.38126 z"
|
||||
id="path2824-7-1"
|
||||
style="opacity:0.92000002;color:#000000;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
<path
|
||||
d="m 232.30267,551.36809 0,46.72376"
|
||||
id="path11849"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart-4);marker-end:url(#Arrow1Lend-2)" />
|
||||
<path
|
||||
d="m 255.66455,574.72997 -46.72376,0"
|
||||
id="path12611"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart-4);marker-end:url(#Arrow1Lend-2)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 17 KiB |
126
doc/svg/edge-scrolling.svg
Normal file
126
doc/svg/edge-scrolling.svg
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.1"
|
||||
width="865.5542"
|
||||
height="341.20889"
|
||||
id="svg2">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
id="path3710"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
id="path3707"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lstart-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
id="path3707-7"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lend-2"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
id="path3710-3"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
</defs>
|
||||
<g
|
||||
transform="translate(343.95712,-527.33359)"
|
||||
id="layer3"
|
||||
style="display:inline">
|
||||
<rect
|
||||
width="386.42856"
|
||||
height="261.42856"
|
||||
x="-340.35712"
|
||||
y="530.93359"
|
||||
id="rect2858-0"
|
||||
style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:7.20000076;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 21.360531,774.95272 0,-196.97975"
|
||||
id="path8036"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lend)" />
|
||||
<g
|
||||
transform="matrix(0.98314313,0.18283763,-0.18283763,0.98314313,-175.46474,-125.7572)"
|
||||
id="g3663-9-5">
|
||||
<path
|
||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
||||
id="path2820-6-6"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 360.32021,827.78041 c -15.74169,-35.7991 -29.44655,-66.92657 -30.45523,-69.17214 -7.08929,-15.78239 -10.8761,-32.88254 -9.6176,-43.43026 1.39575,-11.69796 7.19746,-18.50389 18.22574,-21.38044 5.18218,-1.35169 8.54724,-1.76827 12.41155,-1.53649 4.43642,0.26609 6.95929,0.93715 11.03011,2.93391 3.93491,1.9301 8.0085,5.56248 10.68932,9.53159 3.68818,5.46055 26.56068,50.9623 49.57778,98.62829 16.60192,34.38082 37.06388,77.41994 36.89013,77.59369 -0.13286,0.13286 -69.01932,11.92114 -69.66286,11.92114 -0.27909,0 -12.00972,-26.24842 -29.08894,-65.08929 z"
|
||||
id="path2824-1-1"
|
||||
style="color:#000000;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 334.75785,756.75053 c -7.08929,-15.78239 -10.28437,-26.89033 -9.02587,-37.43805 1.39575,-11.69796 5.8085,-16.73613 16.83678,-19.61268 12.44766,-3.59459 20.03902,-1.91353 27.39013,8.75815 11.42622,25.66382 13.40166,29.05484 15.06365,35.48866 -0.13286,0.13286 -42.89663,15.49027 -44.57776,16.18518 -1.72922,0.71479 -4.94789,-2.09377 -5.68693,-3.38126 z"
|
||||
id="path2824-7-1-4"
|
||||
style="opacity:0.92000002;color:#000000;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(343.95712,-527.33359)"
|
||||
id="layer1"
|
||||
style="display:inline">
|
||||
<rect
|
||||
width="386.42856"
|
||||
height="261.42856"
|
||||
x="131.56854"
|
||||
y="530.93359"
|
||||
id="rect2858"
|
||||
style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:7.20000076;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 455.56456,762.87232 c 0,0 -235.01231,1.01015 -235.01231,1.01015"
|
||||
id="path3702"
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lstart)" />
|
||||
<g
|
||||
transform="matrix(0.98314313,0.18283763,-0.18283763,0.98314313,132.81621,-12.620089)"
|
||||
id="g3663-9">
|
||||
<path
|
||||
d="m 359.78441,828.85231 -28.35583,-65.06155 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 47.45034,95.30837 47.45034,95.30837 l -63.38022,25.11033 z"
|
||||
id="path2820-6"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 360.32021,827.78041 c 0,0 -29.44655,-66.92657 -30.45523,-69.17214 -7.08929,-15.78239 -10.8761,-32.88254 -9.6176,-43.43026 1.39575,-11.69796 7.19746,-18.50389 18.22574,-21.38044 5.18218,-1.35169 8.54724,-1.76827 12.41155,-1.53649 4.43642,0.26609 6.95929,0.93715 11.03011,2.93391 3.93491,1.9301 8.0085,5.56248 10.68932,9.53159 3.68818,5.46055 49.57778,98.62829 49.57778,98.62829 0,0 -61.86167,24.42554 -61.86167,24.42554 z"
|
||||
id="path2824-1"
|
||||
style="color:#000000;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 334.75785,756.75053 c -7.08929,-15.78239 -10.28437,-26.89033 -9.02587,-37.43805 1.39575,-11.69796 5.8085,-16.73613 16.83678,-19.61268 12.44766,-3.59459 20.03902,-1.91353 27.39013,8.75815 11.42622,25.66382 13.40166,29.05484 15.06365,35.48866 -0.13286,0.13286 -42.89663,15.49027 -44.57776,16.18518 -1.72922,0.71479 -4.94789,-2.09377 -5.68693,-3.38126 z"
|
||||
id="path2824-7-1"
|
||||
style="opacity:0.92000002;color:#000000;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7 KiB |
122
doc/svg/palm-detection.svg
Normal file
122
doc/svg/palm-detection.svg
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.1"
|
||||
width="393.62857"
|
||||
height="268.62857"
|
||||
id="svg2">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
id="path3710"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
id="path3707"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lstart-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
id="path3707-7"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lend-2"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
id="path3710-3"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
</defs>
|
||||
<g
|
||||
transform="translate(343.95712,-527.33359)"
|
||||
id="layer3"
|
||||
style="display:inline">
|
||||
<rect
|
||||
width="386.42856"
|
||||
height="261.42856"
|
||||
x="-340.35712"
|
||||
y="530.93359"
|
||||
id="rect2858-0"
|
||||
style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:7.20000076;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<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>
|
||||
<g
|
||||
transform="translate(343.95712,-527.33359)"
|
||||
id="layer1"
|
||||
style="display:inline" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
165
doc/svg/twofinger-scrolling.svg
Normal file
165
doc/svg/twofinger-scrolling.svg
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.1"
|
||||
width="865.5542"
|
||||
height="327.68497"
|
||||
id="svg2">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
id="path3710"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
id="path3707"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lstart-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
id="path3707-7"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow1Lend-2"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
id="path3710-3"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" />
|
||||
</marker>
|
||||
</defs>
|
||||
<g
|
||||
transform="translate(343.95712,-527.33359)"
|
||||
id="layer3"
|
||||
style="display:inline">
|
||||
<g
|
||||
id="g10793">
|
||||
<rect
|
||||
width="386.42856"
|
||||
height="261.42856"
|
||||
x="-340.35712"
|
||||
y="530.93359"
|
||||
id="rect2858-0"
|
||||
style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:7.20000076;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m -142.28418,718.38417 0,-150.51273"
|
||||
id="path8036"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lend)" />
|
||||
<g
|
||||
transform="matrix(0.98196551,0.12493315,-0.14261338,1.1209308,-351.0514,-195.9045)"
|
||||
id="g3663-7">
|
||||
<path
|
||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
||||
id="path2820-9"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.94553083px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 360.32021,827.78041 c -15.74169,-35.7991 -29.44655,-66.92657 -30.45523,-69.17214 -7.08929,-15.78239 -10.8761,-32.88254 -9.6176,-43.43026 1.39575,-11.69796 7.19746,-18.50389 18.22574,-21.38044 5.18218,-1.35169 8.54724,-1.76827 12.41155,-1.53649 4.43642,0.26609 6.95929,0.93715 11.03011,2.93391 3.93491,1.9301 8.0085,5.56248 10.68932,9.53159 3.68818,5.46055 26.56068,50.9623 49.57778,98.62829 16.60192,34.38082 37.06388,77.41994 36.89013,77.59369 -0.13286,0.13286 -69.01932,11.92114 -69.66286,11.92114 -0.27909,0 -12.00972,-26.24842 -29.08894,-65.08929 z"
|
||||
id="path2824-3"
|
||||
style="color:#000000;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.00189106;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 334.75785,756.75053 c -7.08929,-15.78239 -10.28437,-26.89033 -9.02587,-37.43805 1.39575,-11.69796 5.8085,-16.73613 16.83678,-19.61268 12.44766,-3.59459 20.03902,-1.91353 27.39013,8.75815 11.42622,25.66382 13.40166,29.05484 15.06365,35.48866 -0.13286,0.13286 -42.89663,15.49027 -44.57776,16.18518 -1.72922,0.71479 -4.94789,-2.09377 -5.68693,-3.38126 z"
|
||||
id="path2824-7-0"
|
||||
style="opacity:0.92000002;color:#000000;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.98314313,0.18283763,-0.18283763,0.98314313,-400.72876,-98.483075)"
|
||||
id="g3663-9-5">
|
||||
<path
|
||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
||||
id="path2820-6-6"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 360.32021,827.78041 c -15.74169,-35.7991 -29.44655,-66.92657 -30.45523,-69.17214 -7.08929,-15.78239 -10.8761,-32.88254 -9.6176,-43.43026 1.39575,-11.69796 7.19746,-18.50389 18.22574,-21.38044 5.18218,-1.35169 8.54724,-1.76827 12.41155,-1.53649 4.43642,0.26609 6.95929,0.93715 11.03011,2.93391 3.93491,1.9301 8.0085,5.56248 10.68932,9.53159 3.68818,5.46055 26.56068,50.9623 49.57778,98.62829 16.60192,34.38082 37.06388,77.41994 36.89013,77.59369 -0.13286,0.13286 -69.01932,11.92114 -69.66286,11.92114 -0.27909,0 -12.00972,-26.24842 -29.08894,-65.08929 z"
|
||||
id="path2824-1-1"
|
||||
style="color:#000000;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 334.75785,756.75053 c -7.08929,-15.78239 -10.28437,-26.89033 -9.02587,-37.43805 1.39575,-11.69796 5.8085,-16.73613 16.83678,-19.61268 12.44766,-3.59459 20.03902,-1.91353 27.39013,8.75815 11.42622,25.66382 13.40166,29.05484 15.06365,35.48866 -0.13286,0.13286 -42.89663,15.49027 -44.57776,16.18518 -1.72922,0.71479 -4.94789,-2.09377 -5.68693,-3.38126 z"
|
||||
id="path2824-7-1-4"
|
||||
style="opacity:0.92000002;color:#000000;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(343.95712,-527.33359)"
|
||||
id="layer1"
|
||||
style="display:inline">
|
||||
<g
|
||||
transform="translate(42.253088,-4.1631891)"
|
||||
id="g10781">
|
||||
<rect
|
||||
width="386.42856"
|
||||
height="261.42856"
|
||||
x="89.315453"
|
||||
y="535.0968"
|
||||
id="rect2858"
|
||||
style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:7.20000076;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 400.17949,657.93904 c 0,0 -235.01231,1.01015 -235.01231,1.01015"
|
||||
id="path3702"
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lstart)" />
|
||||
<g
|
||||
transform="matrix(0.98196551,0.12493315,-0.14261338,1.1209308,78.621186,-191.74129)"
|
||||
id="g3663">
|
||||
<path
|
||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
||||
id="path2820"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.94553083px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 360.32021,827.78041 c -15.74169,-35.7991 -29.44655,-66.92657 -30.45523,-69.17214 -7.08929,-15.78239 -10.8761,-32.88254 -9.6176,-43.43026 1.39575,-11.69796 7.19746,-18.50389 18.22574,-21.38044 5.18218,-1.35169 8.54724,-1.76827 12.41155,-1.53649 4.43642,0.26609 6.95929,0.93715 11.03011,2.93391 3.93491,1.9301 8.0085,5.56248 10.68932,9.53159 3.68818,5.46055 26.56068,50.9623 49.57778,98.62829 16.60192,34.38082 37.06388,77.41994 36.89013,77.59369 -0.13286,0.13286 -69.01932,11.92114 -69.66286,11.92114 -0.27909,0 -12.00972,-26.24842 -29.08894,-65.08929 z"
|
||||
id="path2824"
|
||||
style="color:#000000;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.00189106;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 334.75785,756.75053 c -7.08929,-15.78239 -10.28437,-26.89033 -9.02587,-37.43805 1.39575,-11.69796 5.8085,-16.73613 16.83678,-19.61268 12.44766,-3.59459 20.03902,-1.91353 27.39013,8.75815 11.42622,25.66382 13.40166,29.05484 15.06365,35.48866 -0.13286,0.13286 -42.89663,15.49027 -44.57776,16.18518 -1.72922,0.71479 -4.94789,-2.09377 -5.68693,-3.38126 z"
|
||||
id="path2824-7"
|
||||
style="opacity:0.92000002;color:#000000;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.98314313,0.18283763,-0.18283763,0.98314313,28.943818,-94.319866)"
|
||||
id="g3663-9">
|
||||
<path
|
||||
d="m 388.57143,893.79076 -57.14285,-130 c 0,0 -30.0247,-58.84827 4.28571,-70.00001 27.07438,-8.79984 37.32196,9.59496 40,14.64286 27.54455,51.91936 84.64285,173.21429 84.64285,173.21429 l -0.71428,0 -71.07143,12.14286 z"
|
||||
id="path2820-6"
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 360.32021,827.78041 c -15.74169,-35.7991 -29.44655,-66.92657 -30.45523,-69.17214 -7.08929,-15.78239 -10.8761,-32.88254 -9.6176,-43.43026 1.39575,-11.69796 7.19746,-18.50389 18.22574,-21.38044 5.18218,-1.35169 8.54724,-1.76827 12.41155,-1.53649 4.43642,0.26609 6.95929,0.93715 11.03011,2.93391 3.93491,1.9301 8.0085,5.56248 10.68932,9.53159 3.68818,5.46055 26.56068,50.9623 49.57778,98.62829 16.60192,34.38082 37.06388,77.41994 36.89013,77.59369 -0.13286,0.13286 -69.01932,11.92114 -69.66286,11.92114 -0.27909,0 -12.00972,-26.24842 -29.08894,-65.08929 z"
|
||||
id="path2824-1"
|
||||
style="color:#000000;fill:#ffccaa;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 334.75785,756.75053 c -7.08929,-15.78239 -10.28437,-26.89033 -9.02587,-37.43805 1.39575,-11.69796 5.8085,-16.73613 16.83678,-19.61268 12.44766,-3.59459 20.03902,-1.91353 27.39013,8.75815 11.42622,25.66382 13.40166,29.05484 15.06365,35.48866 -0.13286,0.13286 -42.89663,15.49027 -44.57776,16.18518 -1.72922,0.71479 -4.94789,-2.09377 -5.68693,-3.38126 z"
|
||||
id="path2824-7-1"
|
||||
style="opacity:0.92000002;color:#000000;fill:#ffe6d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
74
doc/t440-support.dox
Normal file
74
doc/t440-support.dox
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
@page t440_support Lenovo *40 series touchpad support
|
||||
|
||||
The Lenovo *40 series emulates trackstick buttons on the top part of the
|
||||
touchpads.
|
||||
|
||||
@section t440_support_overview Overview
|
||||
|
||||
The Lenovo *40 series introduced a new type of touchpad. Previously, all
|
||||
laptops had a separate set of physical buttons for the
|
||||
<a href="http://en.wikipedia.org/wiki/Pointing_stick">trackstick</a>. This
|
||||
series removed these buttons, relying on a software emulation of the top
|
||||
section of the touchpad. This is visually marked on the trackpad itself,
|
||||
approximately like this:
|
||||
|
||||
@dot
|
||||
digraph G {
|
||||
subgraph cluster_0 {
|
||||
margin="0";
|
||||
|
||||
clickpad [
|
||||
shape = "record";
|
||||
color = "none";
|
||||
label = "{{LLLLLLLLLL|MMMMM|RRRRRRRRR}|\n\n\n\n\n\n\n\n|{LLLLLLLL| |RRRRRRRR}}";
|
||||
]
|
||||
}
|
||||
}
|
||||
@enddot
|
||||
|
||||
This page only covers the top software buttons, the bottom button behavior
|
||||
is covered in @ref clickpad_softbuttons "Clickpad software buttons".
|
||||
|
||||
Clickpads with a top button area are marked with the <a
|
||||
href="https://www.kernel.org/doc/Documentation/input/event-codes.txt">INPUT_PROP_TOPBUTTONPAD</a>
|
||||
property.
|
||||
|
||||
@section t440_support_btn_size Size of the buttons
|
||||
|
||||
The line of the buttons is 5mm from the top edge of the touchpad,
|
||||
measurements of button presses showed that the size of the buttons needs to
|
||||
be approximately 10mm high to work reliable (especially when using the
|
||||
thumb to press the button).
|
||||
|
||||
The width of the left and right buttons is approximately 42% of the
|
||||
touchpad's width, the middle button is centered and should be assigned
|
||||
approximately 16% of the touchpad width.
|
||||
|
||||
@section t440_support_btn_behavior Button behavior
|
||||
|
||||
Movement in the top button area does not generate pointer movement. These
|
||||
buttons are not replacement buttons for the bottom button area but have
|
||||
their own behavior.
|
||||
Semantically attached to the trackstick device, libinput re-routes events
|
||||
from these buttons to appear through the trackstick device. The top button
|
||||
areas work even if the touchpad is disabled but will be disabled when the
|
||||
trackstick device is disabled.
|
||||
|
||||
If the finger starts inside the top area and moves outside the button area
|
||||
the finger is treated as dead and must be lifted to generate future buttons.
|
||||
Likewise, movement into the top button area does not trigger button events, a click
|
||||
has to start inside this area to take effect.
|
||||
|
||||
@section t440_support_identification Kernel support
|
||||
|
||||
The firmware on touchpads providing top software buttons is buggy and
|
||||
announces wrong ranges. <a href="https://lkml.org/lkml/2014/3/7/722">Kernel
|
||||
patches</a> are required; these fixes are available in kernels
|
||||
3.14.1, 3.15 and later but each touchpad needs a separate fix.
|
||||
|
||||
For a complete list of supported touchpads check <a
|
||||
href="http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/input/mouse/synaptics.c">the
|
||||
kernel source</a> (search for "topbuttonpad_pnp_ids").
|
||||
|
||||
*/
|
||||
48
doc/tapping.dox
Normal file
48
doc/tapping.dox
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
@page tapping Tap-to-click behaviour
|
||||
|
||||
"Tapping" or "tap-to-click" is the name given to the behavior where a short
|
||||
finger touch down/up sequence maps into a button click. This is most
|
||||
commonly used on touchpads, but may be available on other devices.
|
||||
|
||||
libinput implements tapping for one, two, and three fingers, where supported
|
||||
by the hardware, and maps those taps into a left, right, and middle button
|
||||
click, respectively. Not all devices support three fingers, libinput will
|
||||
support tapping up to whatever is supported by the hardware. libinput does
|
||||
not support four-finger taps or any tapping with more than four fingers,
|
||||
even though some hardware can distinguish between that many fingers.
|
||||
|
||||
Tapping is **disabled** by default, see [this
|
||||
commit](http://cgit.freedesktop.org/wayland/libinput/commit/?id=2219c12c3aa45b80f235e761e87c17fb9ec70eae)
|
||||
because:
|
||||
- if you don't know that tapping is a thing (or enabled by default), you get
|
||||
spurious button events that make the desktop feel buggy.
|
||||
- if you do know what tapping is and you want it, you usually know where to
|
||||
enable it, or at least you can search for it.
|
||||
|
||||
Tapping can be enabled on a per-device basis. See
|
||||
libinput_device_config_tap_set_enabled() for details.
|
||||
|
||||
@section tapndrag Tap-and-drag
|
||||
|
||||
libinput also supports "tap-and-drag" where a tap immediately followed by a
|
||||
finger down and that finger being held down emulates a button press. Moving
|
||||
the finger around can thus drag the selected item on the screen. Lifting the
|
||||
finger and putting it back down immediately (i.e. within the timeout) will
|
||||
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.
|
||||
|
||||
@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:
|
||||
- the touch down and touch up must happen within an implementation-defined timeout
|
||||
- if a finger moves more than an implementation-defined distance while in contact, it's not a tap
|
||||
- tapping within @ref clickpad_softbuttons "clickpad software buttons" may not trigger an event
|
||||
- a tap not meeting required pressure thresholds can be ignored as accidental touch
|
||||
- a tap exceeding certain pressure thresholds can be ignored (see @ref
|
||||
palm_detection)
|
||||
- a tap on the edges of the touchpad can usually be ignored (see @ref
|
||||
palm_detection)
|
||||
|
||||
*/
|
||||
|
|
@ -38,6 +38,7 @@ libinput_la_CFLAGS = -I$(top_srcdir)/include \
|
|||
$(LIBUDEV_CFLAGS) \
|
||||
$(LIBEVDEV_CFLAGS) \
|
||||
$(GCC_CFLAGS)
|
||||
EXTRA_libinput_la_DEPENDENCIES = $(srcdir)/libinput.sym
|
||||
|
||||
libinput_util_la_SOURCES = \
|
||||
libinput-util.c \
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ tp_edge_scroll_set_state(struct tp_dispatch *tp,
|
|||
{
|
||||
libinput_timer_cancel(&t->scroll.timer);
|
||||
|
||||
t->scroll.state = state;
|
||||
t->scroll.edge_state = state;
|
||||
|
||||
switch (state) {
|
||||
case EDGE_SCROLL_TOUCH_STATE_NONE:
|
||||
|
|
@ -207,7 +207,7 @@ tp_edge_scroll_handle_event(struct tp_dispatch *tp,
|
|||
struct tp_touch *t,
|
||||
enum scroll_event event)
|
||||
{
|
||||
switch (t->scroll.state) {
|
||||
switch (t->scroll.edge_state) {
|
||||
case EDGE_SCROLL_TOUCH_STATE_NONE:
|
||||
tp_edge_scroll_handle_none(tp, t, event);
|
||||
break;
|
||||
|
|
@ -325,7 +325,10 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
if (t->scroll.direction != -1) {
|
||||
/* Send stop scroll event */
|
||||
pointer_notify_axis(device, time,
|
||||
t->scroll.direction, 0.0);
|
||||
AS_MASK(t->scroll.direction),
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
|
||||
0.0, 0.0,
|
||||
0, 0);
|
||||
t->scroll.direction = -1;
|
||||
}
|
||||
continue;
|
||||
|
|
@ -347,7 +350,11 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
if (fabs(*delta) < t->scroll.threshold)
|
||||
continue;
|
||||
|
||||
pointer_notify_axis(device, time, axis, *delta);
|
||||
pointer_notify_axis(device, time,
|
||||
AS_MASK(axis),
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
|
||||
dx, dy,
|
||||
0, 0);
|
||||
t->scroll.direction = axis;
|
||||
|
||||
tp_edge_scroll_handle_event(tp, t, SCROLL_EVENT_POSTED);
|
||||
|
|
@ -365,7 +372,10 @@ tp_edge_scroll_stop_events(struct tp_dispatch *tp, uint64_t time)
|
|||
tp_for_each_touch(tp, t) {
|
||||
if (t->scroll.direction != -1) {
|
||||
pointer_notify_axis(device, time,
|
||||
t->scroll.direction, 0.0);
|
||||
AS_MASK(t->scroll.direction),
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
|
||||
0.0, 0.0,
|
||||
0.0, 0.0);
|
||||
t->scroll.direction = -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -374,5 +384,5 @@ tp_edge_scroll_stop_events(struct tp_dispatch *tp, uint64_t time)
|
|||
int
|
||||
tp_edge_scroll_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
return t->scroll.state == EDGE_SCROLL_TOUCH_STATE_AREA;
|
||||
return t->scroll.edge_state == EDGE_SCROLL_TOUCH_STATE_AREA;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -664,8 +664,9 @@ tp_tap_config_set_enabled(struct libinput_device *device,
|
|||
enum libinput_config_tap_state enabled)
|
||||
{
|
||||
struct evdev_dispatch *dispatch = ((struct evdev_device *) device)->dispatch;
|
||||
struct tp_dispatch *tp = container_of(dispatch, tp, base);
|
||||
struct tp_dispatch *tp = NULL;
|
||||
|
||||
tp = container_of(dispatch, tp, base);
|
||||
tp_tap_enabled_update(tp, tp->tap.suspended,
|
||||
(enabled == LIBINPUT_CONFIG_TAP_ENABLED),
|
||||
libinput_now(device->seat->libinput));
|
||||
|
|
|
|||
|
|
@ -435,7 +435,39 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
|
|||
|
||||
tp_filter_motion(tp, &dx, &dy, NULL, NULL, time);
|
||||
|
||||
evdev_post_scroll(tp->device, time, dx, dy);
|
||||
evdev_post_scroll(tp->device,
|
||||
time,
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
|
||||
dx, dy);
|
||||
tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_ACTIVE;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_twofinger_stop_scroll(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t, *ptr = NULL;
|
||||
int nfingers_down = 0;
|
||||
|
||||
evdev_stop_scroll(tp->device,
|
||||
time,
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
|
||||
|
||||
/* If we were scrolling and now there's exactly 1 active finger,
|
||||
switch back to pointer movement */
|
||||
if (tp->scroll.twofinger_state == TWOFINGER_SCROLL_STATE_ACTIVE) {
|
||||
tp_for_each_touch(tp, t) {
|
||||
if (tp_touch_active(tp, t)) {
|
||||
nfingers_down++;
|
||||
if (ptr == NULL)
|
||||
ptr = t;
|
||||
}
|
||||
}
|
||||
|
||||
if (nfingers_down == 1)
|
||||
tp_set_pointer(tp, ptr);
|
||||
}
|
||||
|
||||
tp->scroll.twofinger_state = TWOFINGER_SCROLL_STATE_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -458,13 +490,14 @@ tp_twofinger_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
nfingers_down++;
|
||||
}
|
||||
|
||||
if (nfingers_down != 2) {
|
||||
evdev_stop_scroll(tp->device, time);
|
||||
return 0;
|
||||
if (nfingers_down == 2) {
|
||||
tp_post_twofinger_scroll(tp, time);
|
||||
return 1;
|
||||
}
|
||||
|
||||
tp_post_twofinger_scroll(tp, time);
|
||||
return 1;
|
||||
tp_twofinger_stop_scroll(tp, time);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -504,7 +537,7 @@ tp_stop_scroll_events(struct tp_dispatch *tp, uint64_t time)
|
|||
case LIBINPUT_CONFIG_SCROLL_NO_SCROLL:
|
||||
break;
|
||||
case LIBINPUT_CONFIG_SCROLL_2FG:
|
||||
evdev_stop_scroll(tp->device, time);
|
||||
tp_twofinger_stop_scroll(tp, time);
|
||||
break;
|
||||
case LIBINPUT_CONFIG_SCROLL_EDGE:
|
||||
tp_edge_scroll_stop_events(tp, time);
|
||||
|
|
@ -818,7 +851,9 @@ tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data)
|
|||
return;
|
||||
|
||||
if (!tp->sendevents.trackpoint_active) {
|
||||
evdev_stop_scroll(tp->device, time);
|
||||
evdev_stop_scroll(tp->device,
|
||||
time,
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
|
||||
tp_tap_suspend(tp, time);
|
||||
tp->sendevents.trackpoint_active = true;
|
||||
}
|
||||
|
|
@ -1275,7 +1310,7 @@ tp_change_to_left_handed(struct evdev_device *device)
|
|||
{
|
||||
struct tp_dispatch *tp = (struct tp_dispatch *)device->dispatch;
|
||||
|
||||
if (device->buttons.want_left_handed == device->buttons.left_handed)
|
||||
if (device->left_handed.want_enabled == device->left_handed.enabled)
|
||||
return;
|
||||
|
||||
if (tp->buttons.state & 0x3) /* BTN_LEFT|BTN_RIGHT */
|
||||
|
|
@ -1284,7 +1319,7 @@ tp_change_to_left_handed(struct evdev_device *device)
|
|||
/* tapping and clickfinger aren't affected by left-handed config,
|
||||
* so checking physical buttons is enough */
|
||||
|
||||
device->buttons.left_handed = device->buttons.want_left_handed;
|
||||
device->left_handed.enabled = device->left_handed.want_enabled;
|
||||
}
|
||||
|
||||
struct model_lookup_t {
|
||||
|
|
|
|||
|
|
@ -117,6 +117,11 @@ enum tp_edge_scroll_touch_state {
|
|||
EDGE_SCROLL_TOUCH_STATE_AREA,
|
||||
};
|
||||
|
||||
enum tp_twofinger_scroll_state {
|
||||
TWOFINGER_SCROLL_STATE_NONE,
|
||||
TWOFINGER_SCROLL_STATE_ACTIVE,
|
||||
};
|
||||
|
||||
struct tp_motion {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
|
|
@ -165,7 +170,7 @@ struct tp_touch {
|
|||
} tap;
|
||||
|
||||
struct {
|
||||
enum tp_edge_scroll_touch_state state;
|
||||
enum tp_edge_scroll_touch_state edge_state;
|
||||
uint32_t edge;
|
||||
int direction;
|
||||
double threshold;
|
||||
|
|
@ -238,6 +243,7 @@ struct tp_dispatch {
|
|||
enum libinput_config_scroll_method method;
|
||||
int32_t right_edge;
|
||||
int32_t bottom_edge;
|
||||
enum tp_twofinger_scroll_state twofinger_state;
|
||||
} scroll;
|
||||
|
||||
enum touchpad_event queued;
|
||||
|
|
|
|||
148
src/evdev.c
148
src/evdev.c
|
|
@ -40,7 +40,7 @@
|
|||
#include "filter.h"
|
||||
#include "libinput-private.h"
|
||||
|
||||
#define DEFAULT_AXIS_STEP_DISTANCE 10
|
||||
#define DEFAULT_WHEEL_CLICK_ANGLE 15
|
||||
#define DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT 200
|
||||
|
||||
enum evdev_key_type {
|
||||
|
|
@ -119,8 +119,8 @@ evdev_pointer_notify_button(struct evdev_device *device,
|
|||
pointer_notify_button(&device->base, time, button, state);
|
||||
|
||||
if (state == LIBINPUT_BUTTON_STATE_RELEASED &&
|
||||
device->buttons.change_to_left_handed)
|
||||
device->buttons.change_to_left_handed(device);
|
||||
device->left_handed.change_to_enabled)
|
||||
device->left_handed.change_to_enabled(device);
|
||||
|
||||
if (state == LIBINPUT_BUTTON_STATE_RELEASED &&
|
||||
device->scroll.change_scroll_method)
|
||||
|
|
@ -222,6 +222,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
|||
hw_is_key_down(device, device->scroll.button)) {
|
||||
if (device->scroll.button_scroll_active)
|
||||
evdev_post_scroll(device, time,
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS,
|
||||
dx_unaccel, dy_unaccel);
|
||||
break;
|
||||
}
|
||||
|
|
@ -394,7 +395,8 @@ evdev_button_scroll_button(struct evdev_device *device,
|
|||
} else {
|
||||
libinput_timer_cancel(&device->scroll.timer);
|
||||
if (device->scroll.button_scroll_active) {
|
||||
evdev_stop_scroll(device, time);
|
||||
evdev_stop_scroll(device, time,
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS);
|
||||
device->scroll.button_scroll_active = false;
|
||||
} else {
|
||||
/* If the button is released quickly enough emit the
|
||||
|
|
@ -537,16 +539,24 @@ evdev_process_absolute_motion(struct evdev_device *device,
|
|||
static void
|
||||
evdev_notify_axis(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum libinput_pointer_axis axis,
|
||||
double value)
|
||||
uint32_t axes,
|
||||
enum libinput_pointer_axis_source source,
|
||||
double x, double y,
|
||||
double x_discrete, double y_discrete)
|
||||
{
|
||||
if (device->scroll.natural_scrolling_enabled)
|
||||
value *= -1;
|
||||
if (device->scroll.natural_scrolling_enabled) {
|
||||
x *= -1;
|
||||
y *= -1;
|
||||
x_discrete *= -1;
|
||||
y_discrete *= -1;
|
||||
}
|
||||
|
||||
pointer_notify_axis(&device->base,
|
||||
time,
|
||||
axis,
|
||||
value);
|
||||
axes,
|
||||
source,
|
||||
x, y,
|
||||
x_discrete, y_discrete);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -571,16 +581,24 @@ evdev_process_relative(struct evdev_device *device,
|
|||
evdev_notify_axis(
|
||||
device,
|
||||
time,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
|
||||
-1 * e->value * DEFAULT_AXIS_STEP_DISTANCE);
|
||||
AS_MASK(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL),
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL,
|
||||
0.0,
|
||||
-1 * e->value * device->scroll.wheel_click_angle,
|
||||
0.0,
|
||||
-1 * e->value);
|
||||
break;
|
||||
case REL_HWHEEL:
|
||||
evdev_flush_pending_event(device, time);
|
||||
evdev_notify_axis(
|
||||
device,
|
||||
time,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
|
||||
e->value * DEFAULT_AXIS_STEP_DISTANCE);
|
||||
AS_MASK(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL),
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL,
|
||||
e->value * device->scroll.wheel_click_angle,
|
||||
0.0,
|
||||
e->value,
|
||||
0.0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -804,13 +822,13 @@ evdev_left_handed_has(struct libinput_device *device)
|
|||
static void
|
||||
evdev_change_to_left_handed(struct evdev_device *device)
|
||||
{
|
||||
if (device->buttons.want_left_handed == device->buttons.left_handed)
|
||||
if (device->left_handed.want_enabled == device->left_handed.enabled)
|
||||
return;
|
||||
|
||||
if (evdev_any_button_down(device))
|
||||
return;
|
||||
|
||||
device->buttons.left_handed = device->buttons.want_left_handed;
|
||||
device->left_handed.enabled = device->left_handed.want_enabled;
|
||||
}
|
||||
|
||||
static enum libinput_config_status
|
||||
|
|
@ -818,9 +836,9 @@ evdev_left_handed_set(struct libinput_device *device, int left_handed)
|
|||
{
|
||||
struct evdev_device *evdev_device = (struct evdev_device *)device;
|
||||
|
||||
evdev_device->buttons.want_left_handed = left_handed ? true : false;
|
||||
evdev_device->left_handed.want_enabled = left_handed ? true : false;
|
||||
|
||||
evdev_device->buttons.change_to_left_handed(evdev_device);
|
||||
evdev_device->left_handed.change_to_enabled(evdev_device);
|
||||
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -832,7 +850,7 @@ evdev_left_handed_get(struct libinput_device *device)
|
|||
|
||||
/* return the wanted configuration, even if it hasn't taken
|
||||
* effect yet! */
|
||||
return evdev_device->buttons.want_left_handed;
|
||||
return evdev_device->left_handed.want_enabled;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -845,14 +863,14 @@ int
|
|||
evdev_init_left_handed(struct evdev_device *device,
|
||||
void (*change_to_left_handed)(struct evdev_device *))
|
||||
{
|
||||
device->buttons.config_left_handed.has = evdev_left_handed_has;
|
||||
device->buttons.config_left_handed.set = evdev_left_handed_set;
|
||||
device->buttons.config_left_handed.get = evdev_left_handed_get;
|
||||
device->buttons.config_left_handed.get_default = evdev_left_handed_get_default;
|
||||
device->base.config.left_handed = &device->buttons.config_left_handed;
|
||||
device->buttons.left_handed = false;
|
||||
device->buttons.want_left_handed = false;
|
||||
device->buttons.change_to_left_handed = change_to_left_handed;
|
||||
device->left_handed.config.has = evdev_left_handed_has;
|
||||
device->left_handed.config.set = evdev_left_handed_set;
|
||||
device->left_handed.config.get = evdev_left_handed_get;
|
||||
device->left_handed.config.get_default = evdev_left_handed_get_default;
|
||||
device->base.config.left_handed = &device->left_handed.config;
|
||||
device->left_handed.enabled = false;
|
||||
device->left_handed.want_enabled = false;
|
||||
device->left_handed.change_to_enabled = change_to_left_handed;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1046,7 +1064,7 @@ fallback_dispatch_create(struct libinput_device *device)
|
|||
|
||||
dispatch->interface = &fallback_interface;
|
||||
|
||||
if (evdev_device->buttons.want_left_handed &&
|
||||
if (evdev_device->left_handed.want_enabled &&
|
||||
evdev_init_left_handed(evdev_device,
|
||||
evdev_change_to_left_handed) == -1) {
|
||||
free(dispatch);
|
||||
|
|
@ -1233,6 +1251,29 @@ evdev_tag_device(struct evdev_device *device)
|
|||
device->udev_device);
|
||||
}
|
||||
|
||||
static inline int
|
||||
evdev_read_wheel_click_prop(struct evdev_device *device)
|
||||
{
|
||||
struct libinput *libinput = device->base.seat->libinput;
|
||||
const char *prop;
|
||||
int angle = DEFAULT_WHEEL_CLICK_ANGLE;
|
||||
|
||||
prop = udev_device_get_property_value(device->udev_device,
|
||||
"MOUSE_WHEEL_CLICK_ANGLE");
|
||||
if (prop) {
|
||||
angle = parse_mouse_wheel_click_angle_property(prop);
|
||||
if (!angle) {
|
||||
log_error(libinput,
|
||||
"Mouse wheel click angle '%s' is present but invalid,"
|
||||
"using %d degrees instead\n",
|
||||
device->devname,
|
||||
DEFAULT_WHEEL_CLICK_ANGLE);
|
||||
angle = DEFAULT_WHEEL_CLICK_ANGLE;
|
||||
}
|
||||
}
|
||||
|
||||
return angle;
|
||||
}
|
||||
static inline int
|
||||
evdev_read_dpi_prop(struct evdev_device *device)
|
||||
{
|
||||
|
|
@ -1444,7 +1485,7 @@ evdev_configure_device(struct evdev_device *device)
|
|||
has_button ? " button" : "");
|
||||
|
||||
/* want left-handed config option */
|
||||
device->buttons.want_left_handed = true;
|
||||
device->left_handed.want_enabled = true;
|
||||
/* want natural-scroll config option */
|
||||
device->scroll.natural_scrolling_enabled = true;
|
||||
}
|
||||
|
|
@ -1570,6 +1611,8 @@ evdev_device_create(struct libinput_seat *seat,
|
|||
device->devname = libevdev_get_name(device->evdev);
|
||||
device->scroll.threshold = 5.0; /* Default may be overridden */
|
||||
device->scroll.direction = 0;
|
||||
device->scroll.wheel_click_angle =
|
||||
evdev_read_wheel_click_prop(device);
|
||||
device->dpi = evdev_read_dpi_prop(device);
|
||||
/* at most 5 SYN_DROPPED log-messages per 30s */
|
||||
ratelimit_init(&device->syn_drop_limit, 30ULL * 1000, 5);
|
||||
|
|
@ -1775,7 +1818,7 @@ evdev_is_scrolling(const struct evdev_device *device,
|
|||
assert(axis == LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL ||
|
||||
axis == LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
||||
|
||||
return (device->scroll.direction & (1 << axis)) != 0;
|
||||
return (device->scroll.direction & AS_MASK(axis)) != 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -1785,12 +1828,13 @@ evdev_start_scrolling(struct evdev_device *device,
|
|||
assert(axis == LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL ||
|
||||
axis == LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
||||
|
||||
device->scroll.direction |= (1 << axis);
|
||||
device->scroll.direction |= AS_MASK(axis);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_post_scroll(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum libinput_pointer_axis_source source,
|
||||
double dx,
|
||||
double dy)
|
||||
{
|
||||
|
|
@ -1835,39 +1879,35 @@ evdev_post_scroll(struct evdev_device *device,
|
|||
/* We use the trigger to enable, but the delta from this event for
|
||||
* the actual scroll movement. Otherwise we get a jump once
|
||||
* scrolling engages */
|
||||
if (dy != 0.0 &&
|
||||
evdev_is_scrolling(device,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) {
|
||||
evdev_notify_axis(device,
|
||||
time,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
|
||||
dy);
|
||||
}
|
||||
if (!evdev_is_scrolling(device,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
|
||||
dy = 0.0;
|
||||
if (!evdev_is_scrolling(device,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
|
||||
dx = 0.0;
|
||||
|
||||
if (dx != 0.0 &&
|
||||
evdev_is_scrolling(device,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) {
|
||||
if (dx != 0.0 || dy != 0.0)
|
||||
evdev_notify_axis(device,
|
||||
time,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
|
||||
dx);
|
||||
}
|
||||
device->scroll.direction,
|
||||
source,
|
||||
dx, dy,
|
||||
0.0, 0.0);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_stop_scroll(struct evdev_device *device, uint64_t time)
|
||||
evdev_stop_scroll(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum libinput_pointer_axis_source source)
|
||||
{
|
||||
/* terminate scrolling with a zero scroll event */
|
||||
if (device->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
|
||||
if (device->scroll.direction != 0)
|
||||
pointer_notify_axis(&device->base,
|
||||
time,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
|
||||
0);
|
||||
if (device->scroll.direction & (1 << LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
|
||||
pointer_notify_axis(&device->base,
|
||||
time,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
|
||||
0);
|
||||
device->scroll.direction,
|
||||
source,
|
||||
0.0, 0.0,
|
||||
0.0, 0.0);
|
||||
|
||||
device->scroll.buildup_horizontal = 0;
|
||||
device->scroll.buildup_vertical = 0;
|
||||
|
|
|
|||
20
src/evdev.h
20
src/evdev.h
|
|
@ -120,6 +120,9 @@ struct evdev_device {
|
|||
/* set during device init if we want natural scrolling,
|
||||
* used at runtime to enable/disable the feature */
|
||||
bool natural_scrolling_enabled;
|
||||
|
||||
/* angle per REL_WHEEL click in degrees */
|
||||
int wheel_click_angle;
|
||||
} scroll;
|
||||
|
||||
enum evdev_event_type pending_event;
|
||||
|
|
@ -142,15 +145,15 @@ struct evdev_device {
|
|||
uint8_t key_count[KEY_CNT];
|
||||
|
||||
struct {
|
||||
struct libinput_device_config_left_handed config_left_handed;
|
||||
struct libinput_device_config_left_handed config;
|
||||
/* left-handed currently enabled */
|
||||
bool left_handed;
|
||||
bool enabled;
|
||||
/* set during device init if we want left_handed config,
|
||||
* used at runtime to delay the effect until buttons are up */
|
||||
bool want_left_handed;
|
||||
bool want_enabled;
|
||||
/* Checks if buttons are down and commits the setting */
|
||||
void (*change_to_left_handed)(struct evdev_device *device);
|
||||
} buttons;
|
||||
void (*change_to_enabled)(struct evdev_device *device);
|
||||
} left_handed;
|
||||
|
||||
int dpi; /* HW resolution */
|
||||
struct ratelimit syn_drop_limit; /* ratelimit for SYN_DROPPED logging */
|
||||
|
|
@ -302,12 +305,15 @@ evdev_init_natural_scroll(struct evdev_device *device);
|
|||
void
|
||||
evdev_post_scroll(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum libinput_pointer_axis_source source,
|
||||
double dx,
|
||||
double dy);
|
||||
|
||||
|
||||
void
|
||||
evdev_stop_scroll(struct evdev_device *device, uint64_t time);
|
||||
evdev_stop_scroll(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum libinput_pointer_axis_source source);
|
||||
|
||||
void
|
||||
evdev_device_remove(struct evdev_device *device);
|
||||
|
|
@ -330,7 +336,7 @@ static inline uint32_t
|
|||
evdev_to_left_handed(struct evdev_device *device,
|
||||
uint32_t button)
|
||||
{
|
||||
if (device->buttons.left_handed) {
|
||||
if (device->left_handed.enabled) {
|
||||
if (button == BTN_LEFT)
|
||||
return BTN_RIGHT;
|
||||
else if (button == BTN_RIGHT)
|
||||
|
|
|
|||
|
|
@ -308,14 +308,6 @@ create_pointer_accelerator_filter(accel_profile_func_t profile)
|
|||
return &filter->base;
|
||||
}
|
||||
|
||||
static inline double
|
||||
calc_penumbral_gradient(double x)
|
||||
{
|
||||
x *= 2.0;
|
||||
x -= 1.0;
|
||||
return 0.5 + (x * sqrt(1.0 - x * x) + asin(x)) / M_PI;
|
||||
}
|
||||
|
||||
double
|
||||
pointer_accel_profile_linear(struct motion_filter *filter,
|
||||
void *data,
|
||||
|
|
|
|||
|
|
@ -291,8 +291,12 @@ pointer_notify_button(struct libinput_device *device,
|
|||
void
|
||||
pointer_notify_axis(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
enum libinput_pointer_axis axis,
|
||||
double value);
|
||||
uint32_t axes,
|
||||
enum libinput_pointer_axis_source source,
|
||||
double x,
|
||||
double y,
|
||||
double x_discrete,
|
||||
double y_discrete);
|
||||
|
||||
void
|
||||
touch_notify_touch_down(struct libinput_device *device,
|
||||
|
|
|
|||
|
|
@ -131,6 +131,9 @@ ratelimit_test(struct ratelimit *r)
|
|||
* use a reasonable default instead. If the property contains multiple DPI
|
||||
* settings but none flagged as default, we return the last because we're
|
||||
* lazy and that's a silly way to set the property anyway.
|
||||
*
|
||||
* @param prop The value of the udev property (without the MOUSE_DPI=)
|
||||
* @return The default dpi value on success, 0 on error
|
||||
*/
|
||||
int
|
||||
parse_mouse_dpi_property(const char *prop)
|
||||
|
|
@ -168,3 +171,33 @@ parse_mouse_dpi_property(const char *prop)
|
|||
}
|
||||
return dpi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to parse the MOUSE_WHEEL_CLICK_ANGLE property from udev.
|
||||
* Property is of the form:
|
||||
* MOUSE_WHEEL_CLICK_ANGLE=<integer>
|
||||
* Where the number indicates the degrees travelled for each click.
|
||||
*
|
||||
* We skip preceding whitespaces and parse the first number seen. If
|
||||
* multiple numbers are specified, we ignore those.
|
||||
*
|
||||
* @param prop The value of the udev property (without the MOUSE_WHEEL_CLICK_ANGLE=)
|
||||
* @return The angle of the wheel (may be negative) or 0 on error.
|
||||
*/
|
||||
int
|
||||
parse_mouse_wheel_click_angle_property(const char *prop)
|
||||
{
|
||||
int angle = 0,
|
||||
nread = 0;
|
||||
|
||||
while(*prop != 0 && *prop == ' ')
|
||||
prop++;
|
||||
|
||||
sscanf(prop, "%d%n", &angle, &nread);
|
||||
if (nread == 0 || angle == 0 || abs(angle) > 360)
|
||||
return 0;
|
||||
if (prop[nread] != ' ' && prop[nread] != '\0')
|
||||
return 0;
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ int list_empty(const struct list *list);
|
|||
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||
#define ARRAY_FOR_EACH(_arr, _elem) \
|
||||
for (size_t _i = 0; _i < ARRAY_LENGTH(_arr) && (_elem = &_arr[_i]); _i++)
|
||||
#define AS_MASK(v) (1 << (v))
|
||||
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
|
@ -321,5 +322,6 @@ void ratelimit_init(struct ratelimit *r, uint64_t ival_ms, unsigned int burst);
|
|||
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);
|
||||
|
||||
#endif /* LIBINPUT_UTIL_H */
|
||||
|
|
|
|||
106
src/libinput.c
106
src/libinput.c
|
|
@ -59,13 +59,15 @@ struct libinput_event_pointer {
|
|||
uint32_t time;
|
||||
double x;
|
||||
double y;
|
||||
double x_discrete;
|
||||
double y_discrete;
|
||||
double dx_unaccel;
|
||||
double dy_unaccel;
|
||||
uint32_t button;
|
||||
uint32_t seat_button_count;
|
||||
enum libinput_button_state state;
|
||||
enum libinput_pointer_axis axis;
|
||||
double value;
|
||||
enum libinput_pointer_axis_source source;
|
||||
uint32_t axes;
|
||||
};
|
||||
|
||||
struct libinput_event_touch {
|
||||
|
|
@ -435,16 +437,69 @@ libinput_event_pointer_get_seat_button_count(
|
|||
return event->seat_button_count;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_pointer_axis
|
||||
libinput_event_pointer_get_axis(struct libinput_event_pointer *event)
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_event_pointer_has_axis(struct libinput_event_pointer *event,
|
||||
enum libinput_pointer_axis axis)
|
||||
{
|
||||
return event->axis;
|
||||
if (event->base.type == LIBINPUT_EVENT_POINTER_AXIS) {
|
||||
switch (axis) {
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
|
||||
return !!(event->axes & AS_MASK(axis));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event)
|
||||
libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event,
|
||||
enum libinput_pointer_axis axis)
|
||||
{
|
||||
return event->value;
|
||||
struct libinput *libinput = event->base.device->seat->libinput;
|
||||
double value = 0;
|
||||
|
||||
if (!libinput_event_pointer_has_axis(event, axis)) {
|
||||
log_bug_client(libinput, "value requested for unset axis\n");
|
||||
} else {
|
||||
switch (axis) {
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
|
||||
value = event->x;
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
|
||||
value = event->y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
libinput_event_pointer_get_axis_value_discrete(struct libinput_event_pointer *event,
|
||||
enum libinput_pointer_axis axis)
|
||||
{
|
||||
struct libinput *libinput = event->base.device->seat->libinput;
|
||||
double value = 0;
|
||||
|
||||
if (!libinput_event_pointer_has_axis(event, axis)) {
|
||||
log_bug_client(libinput, "value requested for unset axis\n");
|
||||
} else {
|
||||
switch (axis) {
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
|
||||
value = event->x_discrete;
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
|
||||
value = event->y_discrete;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_pointer_axis_source
|
||||
libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event)
|
||||
{
|
||||
return event->source;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
|
|
@ -1196,8 +1251,10 @@ pointer_notify_button(struct libinput_device *device,
|
|||
void
|
||||
pointer_notify_axis(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
enum libinput_pointer_axis axis,
|
||||
double value)
|
||||
uint32_t axes,
|
||||
enum libinput_pointer_axis_source source,
|
||||
double x, double y,
|
||||
double x_discrete, double y_discrete)
|
||||
{
|
||||
struct libinput_event_pointer *axis_event;
|
||||
|
||||
|
|
@ -1207,8 +1264,12 @@ pointer_notify_axis(struct libinput_device *device,
|
|||
|
||||
*axis_event = (struct libinput_event_pointer) {
|
||||
.time = time,
|
||||
.axis = axis,
|
||||
.value = value,
|
||||
.x = x,
|
||||
.y = y,
|
||||
.source = source,
|
||||
.axes = axes,
|
||||
.x_discrete = x_discrete,
|
||||
.y_discrete = y_discrete,
|
||||
};
|
||||
|
||||
post_device_event(device, time,
|
||||
|
|
@ -1499,6 +1560,13 @@ libinput_next_event_type(struct libinput *libinput)
|
|||
return event->type;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT void
|
||||
libinput_set_user_data(struct libinput *libinput,
|
||||
void *user_data)
|
||||
{
|
||||
libinput->user_data = user_data;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT void *
|
||||
libinput_get_user_data(struct libinput *libinput)
|
||||
{
|
||||
|
|
@ -1857,7 +1925,7 @@ libinput_device_config_scroll_get_default_natural_scroll_enabled(struct libinput
|
|||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_config_buttons_has_left_handed(struct libinput_device *device)
|
||||
libinput_device_config_left_handed_is_available(struct libinput_device *device)
|
||||
{
|
||||
if (!device->config.left_handed)
|
||||
return 0;
|
||||
|
|
@ -1866,28 +1934,28 @@ libinput_device_config_buttons_has_left_handed(struct libinput_device *device)
|
|||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_status
|
||||
libinput_device_config_buttons_set_left_handed(struct libinput_device *device,
|
||||
int left_handed)
|
||||
libinput_device_config_left_handed_set(struct libinput_device *device,
|
||||
int left_handed)
|
||||
{
|
||||
if (!libinput_device_config_buttons_has_left_handed(device))
|
||||
if (!libinput_device_config_left_handed_is_available(device))
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
|
||||
return device->config.left_handed->set(device, left_handed);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_config_buttons_get_left_handed(struct libinput_device *device)
|
||||
libinput_device_config_left_handed_get(struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_buttons_has_left_handed(device))
|
||||
if (!libinput_device_config_left_handed_is_available(device))
|
||||
return 0;
|
||||
|
||||
return device->config.left_handed->get(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_config_buttons_get_default_left_handed(struct libinput_device *device)
|
||||
libinput_device_config_left_handed_get_default(struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_buttons_has_left_handed(device))
|
||||
if (!libinput_device_config_left_handed_is_available(device))
|
||||
return 0;
|
||||
|
||||
return device->config.left_handed->get_default(device);
|
||||
|
|
|
|||
358
src/libinput.h
358
src/libinput.h
|
|
@ -35,154 +35,6 @@ extern "C" {
|
|||
__attribute__ ((format (printf, _format, _args)))
|
||||
#define LIBINPUT_ATTRIBUTE_DEPRECATED __attribute__ ((deprecated))
|
||||
|
||||
/**
|
||||
* @page tpbuttons Touchpad button behavior
|
||||
*
|
||||
* For touchpad devices without physical buttons, libinput enables an
|
||||
* emulated right button area through either of two methods.
|
||||
*
|
||||
* Software button areas
|
||||
* =====================
|
||||
* On most touchpads, the bottom area of the touchpad is split into a left
|
||||
* and a right-button area. Pressing the touchpad down with a finger in
|
||||
* those areas will generate clicks as shown in the diagram below:
|
||||
*
|
||||
* @code
|
||||
+------------------------+
|
||||
| |
|
||||
| |
|
||||
| LEFT |
|
||||
| |
|
||||
| |
|
||||
+------------------------+
|
||||
| LEFT | RIGHT |
|
||||
+------------------------+
|
||||
* @endcode
|
||||
*
|
||||
* Generally, the touchpad will emulate a right-button click if the finger
|
||||
* was set down in the right button area and did not leave the
|
||||
* right button area before clicking, even if another finger was already
|
||||
* down on the touchpad in another area.
|
||||
* A middle click is generated by clicking the touchpad when one finger is
|
||||
* in the bottom left button area, and one finger is in the botton right
|
||||
* button area.
|
||||
* The exact behavior of the touchpad is implementation-dependent.
|
||||
*
|
||||
* Top software button area
|
||||
* ========================
|
||||
* On selected touchpads, the top area of the touchpad is a separate set of
|
||||
* software buttons split into a left, middle and right button area.
|
||||
* Pressing the touchpad down with a finger in those areas will generate
|
||||
* clicks as shown in the diagram below:
|
||||
*
|
||||
* @code
|
||||
+------------------------+
|
||||
| LEFT | MIDDLE | RIGHT |
|
||||
+------------------------+
|
||||
| |
|
||||
| LEFT |
|
||||
| |
|
||||
+------------------------+
|
||||
| LEFT | RIGHT |
|
||||
+------------------------+
|
||||
* @endcode
|
||||
* This behavior is enabled on the Lenovo *40 series (T440, T540, T240...)
|
||||
* and the Lenovo Helix, Yoga S1 and Carbon X1 2nd.
|
||||
*
|
||||
* Clickfinger
|
||||
* ===========
|
||||
* On Apple touchpads, no button areas are provided. Instead, use a
|
||||
* two-finger click for a right button click, and a three-finger click for a
|
||||
* middle button click.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page udev_config Static device configuration via udev
|
||||
*
|
||||
* libinput supports some static configuration through udev properties.
|
||||
* These propertiesare read when the device is initially added
|
||||
* to libinput's device list, i.e. before the @ref
|
||||
* LIBINPUT_EVENT_DEVICE_ADDED event is generated.
|
||||
*
|
||||
* The following udev properties are supported:
|
||||
* <dl>
|
||||
* <dt>LIBINPUT_CALIBRATION_MATRIX</dt>
|
||||
* <dd>Sets the calibration matrix, see
|
||||
* libinput_device_config_calibration_get_default_matrix(). If unset,
|
||||
* defaults to the identity matrix.</dd>
|
||||
* <dt>ID_SEAT</dt>
|
||||
* <dd>Assigns the physical seat for this device. See
|
||||
* libinput_seat_get_physical_name(). Defaults to "seat0".</dd>
|
||||
* <dt>WL_SEAT</dt>
|
||||
* <dd>Assigns the logical seat for this device. See
|
||||
* libinput_seat_get_logical_name()
|
||||
* context. Defaults to "default".</dd>
|
||||
* <dt>MOUSE_DPI</dt>
|
||||
* <dd>HW resolution and sampling frequency of a relative pointer device.
|
||||
* See @ref motion_normalization for details.
|
||||
* </dd>
|
||||
* </dl>
|
||||
*
|
||||
* Below is an example udev rule to assign "seat1" to a device from vendor
|
||||
* 0x012a with the model ID of 0x034b.
|
||||
* @code
|
||||
* ACTION=="add|change", KERNEL=="event[0-9]*", ENV{ID_VENDOR_ID}=="012a", \
|
||||
* ENV{ID_MODEL_ID}=="034b", ENV{ID_SEAT}="seat1"
|
||||
* @endcode
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page motion_normalization Normalization of relative motion
|
||||
*
|
||||
* Most relative input devices generate input in so-called "mickeys". A
|
||||
* mickey is in device-specific units that depend on the resolution
|
||||
* of the sensor. Most optical mice use sensors with 1000dpi resolution, but
|
||||
* some devices range from 100dpi to well above 8000dpi.
|
||||
*
|
||||
* Without a physical reference point, a relative coordinate cannot be
|
||||
* interpreted correctly. A delta of 10 mickeys may be a millimeter of
|
||||
* physical movement or 10 millimeters, depending on the sensor. This
|
||||
* affects pointer acceleration in libinput and interpretation of relative
|
||||
* coordinates in callers.
|
||||
*
|
||||
* libinput normalizes all relative input to a physical resolution of
|
||||
* 1000dpi, the same delta from two different devices thus represents the
|
||||
* same physical movement of those two devices (within sensor error
|
||||
* margins).
|
||||
*
|
||||
* Devices usually do not advertise their resolution and libinput relies on
|
||||
* the udev property MOUSE_DPI for this information.
|
||||
*
|
||||
* The format of the property for single-resolution mice is:
|
||||
* @code
|
||||
* MOUSE_DPI=resolution@frequency
|
||||
* @endcode
|
||||
*
|
||||
* The resolution is in dots per inch, the frequency in Hz.
|
||||
* The format of the property for multi-resolution mice may list multiple
|
||||
* resolutions and frequencies:
|
||||
* @code
|
||||
* MOUSE_DPI=r1@f1 *r2@f2 r3@f3
|
||||
* @endcode
|
||||
*
|
||||
* The default frequency must be pre-fixed with an asterisk.
|
||||
*
|
||||
* For example, these two properties are valid:
|
||||
* @code
|
||||
* MOUSE_DPI=800@125
|
||||
* MOUSE_DPI=400@125 800@125 *1000@500 5500@500
|
||||
* @endcode
|
||||
*
|
||||
* The behavior for a malformed property is undefined.
|
||||
*
|
||||
* If the property is unset, libinput assumes the resolution is 1000dpi.
|
||||
*
|
||||
* Note that HW does not usually provide information about run-time
|
||||
* resolution changes, libinput will thus not detect when a resolution
|
||||
* changes to the non-default value.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Log priority for internal logging messages.
|
||||
*/
|
||||
|
|
@ -256,6 +108,28 @@ enum libinput_pointer_axis {
|
|||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
*
|
||||
* The source for a libinput_pointer_axis event. See
|
||||
* libinput_event_pointer_get_axis_source() for details.
|
||||
*/
|
||||
enum libinput_pointer_axis_source {
|
||||
/**
|
||||
* The event is caused by the rotation of a wheel.
|
||||
*/
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL = 1,
|
||||
/**
|
||||
* The event is caused by the movement of one or more fingers on a
|
||||
* device.
|
||||
*/
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
|
||||
/**
|
||||
* The event is caused by the motion of some device.
|
||||
*/
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS,
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
*
|
||||
|
|
@ -849,7 +723,7 @@ libinput_event_pointer_get_button_state(struct libinput_event_pointer *event);
|
|||
*
|
||||
* For the button of a @ref LIBINPUT_EVENT_POINTER_BUTTON event, return the
|
||||
* total number of buttons pressed on all devices on the associated seat
|
||||
* after the the event was triggered.
|
||||
* after the event was triggered.
|
||||
*
|
||||
" @note It is an application bug to call this function for events other than
|
||||
* @ref LIBINPUT_EVENT_POINTER_BUTTON. For other events, this function
|
||||
|
|
@ -864,29 +738,31 @@ libinput_event_pointer_get_seat_button_count(
|
|||
/**
|
||||
* @ingroup event_pointer
|
||||
*
|
||||
* Return the axis that triggered this event.
|
||||
* For pointer events that are not of type @ref LIBINPUT_EVENT_POINTER_AXIS,
|
||||
* this function returns 0.
|
||||
* Check if the event has a valid value for the given axis.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* @ref LIBINPUT_EVENT_POINTER_AXIS.
|
||||
* If this function returns non-zero for an axis and
|
||||
* libinput_event_pointer_get_axis_value() returns a value of 0, the event
|
||||
* is a scroll stop event.
|
||||
*
|
||||
* @return the axis triggering this event
|
||||
* @return non-zero if this event contains a value for this axis
|
||||
*/
|
||||
enum libinput_pointer_axis
|
||||
libinput_event_pointer_get_axis(struct libinput_event_pointer *event);
|
||||
int
|
||||
libinput_event_pointer_has_axis(struct libinput_event_pointer *event,
|
||||
enum libinput_pointer_axis axis);
|
||||
|
||||
/**
|
||||
* @ingroup event_pointer
|
||||
*
|
||||
* Return the axis value of the given axis. The interpretation of the value
|
||||
* is dependent on the axis. For the two scrolling axes
|
||||
* depends on the axis. For the two scrolling axes
|
||||
* @ref LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL and
|
||||
* @ref LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, the value of the event is in
|
||||
* relative scroll units, with the positive direction being down or right,
|
||||
* respectively. The dimension of a scroll unit is equal to one unit of
|
||||
* motion in the respective axis, where applicable (e.g. touchpad two-finger
|
||||
* scrolling).
|
||||
* respectively. For the interpretation of the value, see
|
||||
* libinput_event_pointer_get_axis_source().
|
||||
*
|
||||
* If libinput_event_pointer_has_axis() returns 0 for an axis, this function
|
||||
* returns 0 for that axis.
|
||||
*
|
||||
* For pointer events that are not of type @ref LIBINPUT_EVENT_POINTER_AXIS,
|
||||
* this function returns 0.
|
||||
|
|
@ -895,9 +771,70 @@ libinput_event_pointer_get_axis(struct libinput_event_pointer *event);
|
|||
* @ref LIBINPUT_EVENT_POINTER_AXIS.
|
||||
*
|
||||
* @return the axis value of this event
|
||||
*
|
||||
* @see libinput_event_pointer_get_axis_value_discrete
|
||||
*/
|
||||
double
|
||||
libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event);
|
||||
libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event,
|
||||
enum libinput_pointer_axis axis);
|
||||
|
||||
/**
|
||||
* @ingroup event_pointer
|
||||
*
|
||||
* Return the source for a given axis event. Axis events (scroll events) can
|
||||
* be caused by a hardware item such as a scroll wheel or emulated from
|
||||
* other input sources, such as two-finger or edge scrolling on a
|
||||
* touchpad.
|
||||
*
|
||||
* If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_FINGER, libinput
|
||||
* guarantees that a scroll sequence is terminated with a scroll value of 0.
|
||||
* A caller may use this information to decide on whether kinetic scrolling
|
||||
* should be triggered on this scroll sequence.
|
||||
* The coordinate system is identical to the cursor movement, i.e. a
|
||||
* scroll value of 1 represents the equivalent relative motion of 1.
|
||||
*
|
||||
* If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, no terminating
|
||||
* event is guaranteed (though it may happen).
|
||||
* Scrolling is in discrete steps, the value is the angle the wheel moved
|
||||
* in degrees. The default is 15 degrees per wheel click, but some mice may
|
||||
* have differently grained wheels. It is up to the caller how to interpret
|
||||
* such different step sizes.
|
||||
*
|
||||
* If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS, no
|
||||
* terminating event is guaranteed (though it may happen).
|
||||
* The coordinate system is identical to the cursor movement, i.e. a
|
||||
* scroll value of 1 represents the equivalent relative motion of 1.
|
||||
*
|
||||
* For pointer events that are not of type LIBINPUT_EVENT_POINTER_AXIS,
|
||||
* this function returns 0.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* LIBINPUT_EVENT_POINTER_AXIS.
|
||||
*
|
||||
* @return the source for this axis event
|
||||
*/
|
||||
enum libinput_pointer_axis_source
|
||||
libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event);
|
||||
|
||||
/**
|
||||
* @ingroup pointer
|
||||
*
|
||||
* Return the axis value in discrete steps for a given axis event. How a
|
||||
* value translates into a discrete step depends on the source.
|
||||
*
|
||||
* If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, the discrete
|
||||
* value correspond to the number of physical mouse clicks.
|
||||
*
|
||||
* If the source is @ref LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS or @ref
|
||||
* LIBINPUT_POINTER_AXIS_SOURCE_FINGER, the discrete value is always 0.
|
||||
*
|
||||
* @return The discrete value for the given event.
|
||||
*
|
||||
* @see libinput_event_pointer_get_axis_value
|
||||
*/
|
||||
double
|
||||
libinput_event_pointer_get_axis_value_discrete(struct libinput_event_pointer *event,
|
||||
enum libinput_pointer_axis axis);
|
||||
|
||||
/**
|
||||
* @ingroup event_pointer
|
||||
|
|
@ -1472,6 +1409,17 @@ libinput_get_event(struct libinput *libinput);
|
|||
enum libinput_event_type
|
||||
libinput_next_event_type(struct libinput *libinput);
|
||||
|
||||
/**
|
||||
* @ingroup base
|
||||
*
|
||||
* @param libinput A previously initialized libinput context
|
||||
* @param user_data Caller-specific data passed to the various callback
|
||||
* interfaces.
|
||||
*/
|
||||
void
|
||||
libinput_set_user_data(struct libinput *libinput,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @ingroup base
|
||||
*
|
||||
|
|
@ -1609,27 +1557,10 @@ libinput_log_set_handler(struct libinput *libinput,
|
|||
/**
|
||||
* @defgroup seat Initialization and manipulation of seats
|
||||
*
|
||||
* A seat has two identifiers, the physical name and the logical name. The
|
||||
* physical name is summarized as the list of devices a process on the same
|
||||
* physical seat has access to.
|
||||
*
|
||||
* The logical seat name is the seat name for a logical group of devices. A
|
||||
* compositor may use that to create additonal seats as independent device
|
||||
* sets. Alternatively, a compositor may limit itself to a single logical
|
||||
* seat, leaving a second compositor to manage devices on the other logical
|
||||
* seats.
|
||||
*
|
||||
* @code
|
||||
* +---+--------+------------+------------------------+------------+
|
||||
* | | event0 | | | log seat A |
|
||||
* | K +--------+ | +------------+
|
||||
* | e | event1 | phys seat0 | libinput context 1 | |
|
||||
* | r +--------+ | | log seat B |
|
||||
* | n | event2 | | | |
|
||||
* | e +--------+------------+------------------------+------------+
|
||||
* | l | event3 | phys seat1 | libinput context 2 | log seat C |
|
||||
* +---+--------+------------+------------------------+------------+
|
||||
* @endcode
|
||||
* A seat has two identifiers, the physical name and the logical name. A
|
||||
* device is always assigned to exactly one seat. It may change to a
|
||||
* different logical seat but it cannot change physical seats. See @ref
|
||||
* seats for details.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -2371,7 +2302,7 @@ libinput_device_config_accel_is_available(struct libinput_device *device);
|
|||
* this device. The actual pointer acceleration mechanism is
|
||||
* implementation-dependent, as is the number of steps available within the
|
||||
* range. libinput picks the semantically closest acceleration step if the
|
||||
* requested value does not match a discreet setting.
|
||||
* requested value does not match a discrete setting.
|
||||
*
|
||||
* @param device The device to configure
|
||||
* @param speed The normalized speed, in a range of [-1, 1]
|
||||
|
|
@ -2493,33 +2424,32 @@ libinput_device_config_scroll_get_default_natural_scroll_enabled(struct libinput
|
|||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Check if a device has a button configuration that supports left-handed
|
||||
* usage.
|
||||
* Check if a device has a configuration that supports left-handed usage.
|
||||
*
|
||||
* @param device The device to configure
|
||||
* @return Non-zero if the device can be set to left-handed, or zero
|
||||
* otherwise
|
||||
*
|
||||
* @see libinput_device_config_buttons_set_left_handed
|
||||
* @see libinput_device_config_buttons_get_left_handed
|
||||
* @see libinput_device_config_buttons_get_default_left_handed
|
||||
* @see libinput_device_config_left_handed_set
|
||||
* @see libinput_device_config_left_handed_get
|
||||
* @see libinput_device_config_left_handed_get_default
|
||||
*/
|
||||
int
|
||||
libinput_device_config_buttons_has_left_handed(struct libinput_device *device);
|
||||
libinput_device_config_left_handed_is_available(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Set the left-handed configuration of the device. A device in left-handed
|
||||
* mode sends a left button event instead of the right button and vice
|
||||
* versa.
|
||||
* Set the left-handed configuration of the device. For example, a pointing
|
||||
* device may reverse it's buttons and send a right button click when the
|
||||
* left button is pressed, and vice versa.
|
||||
*
|
||||
* The exact button behavior is device-dependent. On a mouse and most
|
||||
* pointing devices, left and right buttons are swapped but the middle
|
||||
* button is unmodified. On a touchpad, physical buttons (if present) are
|
||||
* swapped. On a clickpad, the top and bottom software-emulated buttons are
|
||||
* swapped where present, the main area of the touchpad remains a left
|
||||
* button. Tapping and clickfinger behavior is not affected by this setting.
|
||||
* The exact behavior is device-dependent. On a mouse and most pointing
|
||||
* devices, left and right buttons are swapped but the middle button is
|
||||
* unmodified. On a touchpad, physical buttons (if present) are swapped. On a
|
||||
* clickpad, the top and bottom software-emulated buttons are swapped where
|
||||
* present, the main area of the touchpad remains a left button. Tapping and
|
||||
* clickfinger behavior is not affected by this setting.
|
||||
*
|
||||
* Changing the left-handed configuration of a device may not take effect
|
||||
* until all buttons have been logically released.
|
||||
|
|
@ -2528,13 +2458,13 @@ libinput_device_config_buttons_has_left_handed(struct libinput_device *device);
|
|||
* @param left_handed Zero to disable, non-zero to enable left-handed mode
|
||||
* @return A configuration status code
|
||||
*
|
||||
* @see libinput_device_config_buttons_has_left_handed
|
||||
* @see libinput_device_config_buttons_get_left_handed
|
||||
* @see libinput_device_config_buttons_get_default_left_handed
|
||||
* @see libinput_device_config_left_handed_is_available
|
||||
* @see libinput_device_config_left_handed_get
|
||||
* @see libinput_device_config_left_handed_get_default
|
||||
*/
|
||||
enum libinput_config_status
|
||||
libinput_device_config_buttons_set_left_handed(struct libinput_device *device,
|
||||
int left_handed);
|
||||
libinput_device_config_left_handed_set(struct libinput_device *device,
|
||||
int left_handed);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
|
|
@ -2545,12 +2475,12 @@ libinput_device_config_buttons_set_left_handed(struct libinput_device *device,
|
|||
* @return Zero if the device is in right-handed mode, non-zero if the
|
||||
* device is in left-handed mode
|
||||
*
|
||||
* @see libinput_device_config_buttons_has_left_handed
|
||||
* @see libinput_device_config_buttons_set_left_handed
|
||||
* @see libinput_device_config_buttons_get_default_left_handed
|
||||
* @see libinput_device_config_left_handed_is_available
|
||||
* @see libinput_device_config_left_handed_set
|
||||
* @see libinput_device_config_left_handed_get_default
|
||||
*/
|
||||
int
|
||||
libinput_device_config_buttons_get_left_handed(struct libinput_device *device);
|
||||
libinput_device_config_left_handed_get(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
|
|
@ -2558,15 +2488,15 @@ libinput_device_config_buttons_get_left_handed(struct libinput_device *device);
|
|||
* Get the default left-handed configuration of the device.
|
||||
*
|
||||
* @param device The device to configure
|
||||
* @return Zero if the device is in right-handed mode by default, or non-zero if the
|
||||
* device is in left-handed mode by default
|
||||
* @return Zero if the device is in right-handed mode by default, or non-zero
|
||||
* if the device is in left-handed mode by default
|
||||
*
|
||||
* @see libinput_device_config_buttons_has_left_handed
|
||||
* @see libinput_device_config_buttons_set_left_handed
|
||||
* @see libinput_device_config_buttons_get_left_handed
|
||||
* @see libinput_device_config_left_handed_is_available
|
||||
* @see libinput_device_config_left_handed_set
|
||||
* @see libinput_device_config_left_handed_get
|
||||
*/
|
||||
int
|
||||
libinput_device_config_buttons_get_default_left_handed(struct libinput_device *device);
|
||||
libinput_device_config_left_handed_get_default(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ global:
|
|||
libinput_device_config_accel_get_speed;
|
||||
libinput_device_config_accel_is_available;
|
||||
libinput_device_config_accel_set_speed;
|
||||
libinput_device_config_buttons_get_default_left_handed;
|
||||
libinput_device_config_buttons_get_left_handed;
|
||||
libinput_device_config_buttons_has_left_handed;
|
||||
libinput_device_config_buttons_set_left_handed;
|
||||
libinput_device_config_left_handed_get_default;
|
||||
libinput_device_config_left_handed_get;
|
||||
libinput_device_config_left_handed_is_available;
|
||||
libinput_device_config_left_handed_set;
|
||||
libinput_device_config_calibration_get_default_matrix;
|
||||
libinput_device_config_calibration_get_matrix;
|
||||
libinput_device_config_calibration_has_matrix;
|
||||
|
|
@ -71,7 +71,9 @@ global:
|
|||
libinput_event_pointer_get_absolute_y;
|
||||
libinput_event_pointer_get_absolute_y_transformed;
|
||||
libinput_event_pointer_get_axis;
|
||||
libinput_event_pointer_get_axis_source;
|
||||
libinput_event_pointer_get_axis_value;
|
||||
libinput_event_pointer_get_axis_value_discrete;
|
||||
libinput_event_pointer_get_base_event;
|
||||
libinput_event_pointer_get_button_state;
|
||||
libinput_event_pointer_get_button;
|
||||
|
|
@ -81,6 +83,7 @@ global:
|
|||
libinput_event_pointer_get_dy_unaccelerated;
|
||||
libinput_event_pointer_get_seat_button_count;
|
||||
libinput_event_pointer_get_time;
|
||||
libinput_event_pointer_has_axis;
|
||||
libinput_event_touch_get_base_event;
|
||||
libinput_event_touch_get_seat_slot;
|
||||
libinput_event_touch_get_slot;
|
||||
|
|
@ -108,6 +111,7 @@ global:
|
|||
libinput_seat_ref;
|
||||
libinput_seat_set_user_data;
|
||||
libinput_seat_unref;
|
||||
libinput_set_user_data;
|
||||
libinput_suspend;
|
||||
libinput_udev_assign_seat;
|
||||
libinput_udev_create_context;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@
|
|||
/* This is a build-test only */
|
||||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
main(void) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,10 +33,6 @@ static void litest_mouse_setup(void)
|
|||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static struct litest_device_interface interface = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x3,
|
||||
.vendor = 0x17ef,
|
||||
|
|
@ -58,7 +54,7 @@ struct litest_test_device litest_mouse_device = {
|
|||
.features = LITEST_RELATIVE | LITEST_BUTTON | LITEST_WHEEL,
|
||||
.shortname = "mouse",
|
||||
.setup = litest_mouse_setup,
|
||||
.interface = &interface,
|
||||
.interface = NULL,
|
||||
|
||||
.name = "Lenovo Optical USB Mouse",
|
||||
.id = &input_id,
|
||||
|
|
|
|||
|
|
@ -33,10 +33,6 @@ static void litest_trackpoint_setup(void)
|
|||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static struct litest_device_interface interface = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x11,
|
||||
.vendor = 0x2,
|
||||
|
|
@ -59,7 +55,7 @@ struct litest_test_device litest_trackpoint_device = {
|
|||
.features = LITEST_RELATIVE | LITEST_BUTTON | LITEST_POINTINGSTICK,
|
||||
.shortname = "trackpoint",
|
||||
.setup = litest_trackpoint_setup,
|
||||
.interface = &interface,
|
||||
.interface = NULL,
|
||||
|
||||
.name = "TPPS/2 IBM TrackPoint",
|
||||
.id = &input_id,
|
||||
|
|
|
|||
|
|
@ -1092,11 +1092,11 @@ litest_print_event(struct libinput_event *event)
|
|||
case LIBINPUT_EVENT_POINTER_AXIS:
|
||||
p = libinput_event_get_pointer_event(event);
|
||||
fprintf(stderr,
|
||||
"axis %s value %.2f",
|
||||
libinput_event_pointer_get_axis(p) ==
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL ?
|
||||
"vert" : "horiz",
|
||||
libinput_event_pointer_get_axis_value(p));
|
||||
"vert %.f horiz %.2f",
|
||||
libinput_event_pointer_get_axis_value(p,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL),
|
||||
libinput_event_pointer_get_axis_value(p,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -1307,23 +1307,24 @@ litest_assert_scroll(struct libinput *li,
|
|||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
ck_assert(ptrev != NULL);
|
||||
ck_assert_int_eq(libinput_event_pointer_get_axis(ptrev), axis);
|
||||
|
||||
if (next_event) {
|
||||
/* Normal scroll event, check dir */
|
||||
if (minimum_movement > 0) {
|
||||
ck_assert_int_ge(
|
||||
libinput_event_pointer_get_axis_value(ptrev),
|
||||
libinput_event_pointer_get_axis_value(ptrev,
|
||||
axis),
|
||||
minimum_movement);
|
||||
} else {
|
||||
ck_assert_int_le(
|
||||
libinput_event_pointer_get_axis_value(ptrev),
|
||||
libinput_event_pointer_get_axis_value(ptrev,
|
||||
axis),
|
||||
minimum_movement);
|
||||
}
|
||||
} else {
|
||||
/* Last scroll event, must be 0 */
|
||||
ck_assert_int_eq(
|
||||
libinput_event_pointer_get_axis_value(ptrev),
|
||||
libinput_event_pointer_get_axis_value(ptrev, axis),
|
||||
0);
|
||||
}
|
||||
libinput_event_destroy(event);
|
||||
|
|
@ -1332,6 +1333,27 @@ litest_assert_scroll(struct libinput *li,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
litest_assert_only_typed_events(struct libinput *li,
|
||||
enum libinput_event_type type)
|
||||
{
|
||||
struct libinput_event *event;
|
||||
|
||||
assert(type != LIBINPUT_EVENT_NONE);
|
||||
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
ck_assert_notnull(event);
|
||||
|
||||
while (event) {
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
type);
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
litest_timeout_tap(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -180,6 +180,8 @@ void litest_assert_button_event(struct libinput *li,
|
|||
void litest_assert_scroll(struct libinput *li,
|
||||
enum libinput_pointer_axis axis,
|
||||
int minimum_movement);
|
||||
void litest_assert_only_typed_events(struct libinput *li,
|
||||
enum libinput_event_type type);
|
||||
|
||||
struct libevdev_uinput * litest_create_uinput_device(const char *name,
|
||||
struct input_id *id,
|
||||
|
|
|
|||
36
test/misc.c
36
test/misc.c
|
|
@ -569,7 +569,7 @@ END_TEST
|
|||
|
||||
struct parser_test {
|
||||
char *tag;
|
||||
int expected_dpi;
|
||||
int expected_value;
|
||||
};
|
||||
|
||||
START_TEST(dpi_parser)
|
||||
|
|
@ -597,13 +597,42 @@ START_TEST(dpi_parser)
|
|||
{ "", 0 },
|
||||
{ " ", 0 },
|
||||
{ "* ", 0 },
|
||||
{ NULL }
|
||||
{ NULL, 0 }
|
||||
};
|
||||
int i, dpi;
|
||||
|
||||
for (i = 0; tests[i].tag != NULL; i++) {
|
||||
dpi = parse_mouse_dpi_property(tests[i].tag);
|
||||
ck_assert_int_eq(dpi, tests[i].expected_dpi);
|
||||
ck_assert_int_eq(dpi, tests[i].expected_value);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(wheel_click_parser)
|
||||
{
|
||||
struct parser_test tests[] = {
|
||||
{ "1", 1 },
|
||||
{ "10", 10 },
|
||||
{ "-12", -12 },
|
||||
{ "360", 360 },
|
||||
{ "66 ", 66 },
|
||||
{ " 100 ", 100 },
|
||||
|
||||
{ "0", 0 },
|
||||
{ "-0", 0 },
|
||||
{ "a", 0 },
|
||||
{ "10a", 0 },
|
||||
{ "10-", 0 },
|
||||
{ "sadfasfd", 0 },
|
||||
{ "361", 0 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
int i, angle;
|
||||
|
||||
for (i = 0; tests[i].tag != NULL; i++) {
|
||||
angle = parse_mouse_wheel_click_angle_property(tests[i].tag);
|
||||
ck_assert_int_eq(angle, tests[i].expected_value);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
|
@ -621,6 +650,7 @@ int main (int argc, char **argv) {
|
|||
litest_add_no_device("misc:matrix", matrix_helpers);
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
16
test/path.c
16
test/path.c
|
|
@ -133,6 +133,21 @@ START_TEST(path_create_destroy)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(path_set_user_data)
|
||||
{
|
||||
struct libinput *li;
|
||||
int data1, data2;
|
||||
|
||||
li = libinput_path_create_context(&simple_interface, &data1);
|
||||
ck_assert(li != NULL);
|
||||
ck_assert(libinput_get_user_data(li) == &data1);
|
||||
libinput_set_user_data(li, &data2);
|
||||
ck_assert(libinput_get_user_data(li) == &data2);
|
||||
|
||||
libinput_unref(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(path_added_seat)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -867,6 +882,7 @@ main(int argc, char **argv)
|
|||
litest_add_no_device("path:create", path_create_NULL);
|
||||
litest_add_no_device("path:create", path_create_invalid);
|
||||
litest_add_no_device("path:create", path_create_destroy);
|
||||
litest_add_no_device("path:create", path_set_user_data);
|
||||
litest_add_no_device("path:suspend", path_suspend);
|
||||
litest_add_no_device("path:suspend", path_double_suspend);
|
||||
litest_add_no_device("path:suspend", path_double_resume);
|
||||
|
|
|
|||
|
|
@ -348,14 +348,18 @@ test_wheel_event(struct litest_device *dev, int which, int amount)
|
|||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
enum libinput_pointer_axis axis;
|
||||
|
||||
/* the current evdev implementation scales the scroll wheel events
|
||||
up by a factor 10 */
|
||||
const int scroll_step = 10;
|
||||
up by a factor 15 */
|
||||
const int scroll_step = 15;
|
||||
int expected = amount * scroll_step;
|
||||
int discrete = amount;
|
||||
|
||||
if (libinput_device_config_scroll_get_natural_scroll_enabled(dev->libinput_device))
|
||||
if (libinput_device_config_scroll_get_natural_scroll_enabled(dev->libinput_device)) {
|
||||
expected *= -1;
|
||||
discrete *= -1;
|
||||
}
|
||||
|
||||
/* mouse scroll wheels are 'upside down' */
|
||||
if (which == REL_WHEEL)
|
||||
|
|
@ -372,11 +376,17 @@ test_wheel_event(struct litest_device *dev, int which, int amount)
|
|||
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
ck_assert(ptrev != NULL);
|
||||
ck_assert_int_eq(libinput_event_pointer_get_axis(ptrev),
|
||||
which == REL_WHEEL ?
|
||||
|
||||
axis = (which == REL_WHEEL) ?
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL :
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
|
||||
ck_assert_int_eq(libinput_event_pointer_get_axis_value(ptrev), expected);
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
|
||||
|
||||
ck_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);
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
|
|
@ -567,13 +577,13 @@ START_TEST(pointer_left_handed_defaults)
|
|||
struct libinput_device *d = dev->libinput_device;
|
||||
int rc;
|
||||
|
||||
rc = libinput_device_config_buttons_has_left_handed(d);
|
||||
rc = libinput_device_config_left_handed_is_available(d);
|
||||
ck_assert_int_ne(rc, 0);
|
||||
|
||||
rc = libinput_device_config_buttons_get_left_handed(d);
|
||||
rc = libinput_device_config_left_handed_get(d);
|
||||
ck_assert_int_eq(rc, 0);
|
||||
|
||||
rc = libinput_device_config_buttons_get_default_left_handed(d);
|
||||
rc = libinput_device_config_left_handed_get_default(d);
|
||||
ck_assert_int_eq(rc, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
|
@ -585,7 +595,7 @@ START_TEST(pointer_left_handed)
|
|||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
status = libinput_device_config_left_handed_set(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
|
@ -635,7 +645,7 @@ START_TEST(pointer_left_handed_during_click)
|
|||
libinput_dispatch(li);
|
||||
|
||||
/* Change while button is down, expect correct release event */
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
status = libinput_device_config_left_handed_set(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
|
|
@ -660,7 +670,7 @@ START_TEST(pointer_left_handed_during_click_multiple_buttons)
|
|||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
status = libinput_device_config_left_handed_set(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
/* No left-handed until all buttons were down */
|
||||
|
|
|
|||
|
|
@ -408,16 +408,16 @@ START_TEST(touch_no_left_handed)
|
|||
enum libinput_config_status status;
|
||||
int rc;
|
||||
|
||||
rc = libinput_device_config_buttons_has_left_handed(d);
|
||||
rc = libinput_device_config_left_handed_is_available(d);
|
||||
ck_assert_int_eq(rc, 0);
|
||||
|
||||
rc = libinput_device_config_buttons_get_left_handed(d);
|
||||
rc = libinput_device_config_left_handed_get(d);
|
||||
ck_assert_int_eq(rc, 0);
|
||||
|
||||
rc = libinput_device_config_buttons_get_default_left_handed(d);
|
||||
rc = libinput_device_config_left_handed_get_default(d);
|
||||
ck_assert_int_eq(rc, 0);
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 0);
|
||||
status = libinput_device_config_left_handed_set(d, 0);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
|
||||
}
|
||||
END_TEST
|
||||
|
|
|
|||
342
test/touchpad.c
342
test/touchpad.c
|
|
@ -121,7 +121,6 @@ START_TEST(touchpad_1fg_tap_n_drag)
|
|||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
|
||||
libinput_device_config_tap_set_enabled(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
|
|
@ -140,27 +139,15 @@ START_TEST(touchpad_1fg_tap_n_drag)
|
|||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
libinput_dispatch(li);
|
||||
while (libinput_next_event_type(li) == LIBINPUT_EVENT_POINTER_MOTION) {
|
||||
event = libinput_get_event(li);
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
ck_assert_int_eq(libinput_next_event_type(li), LIBINPUT_EVENT_NONE);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
/* lift finger, set down again, should continue dragging */
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 80, 80, 5, 40);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
while (libinput_next_event_type(li) == LIBINPUT_EVENT_POINTER_MOTION) {
|
||||
event = libinput_get_event(li);
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
ck_assert_int_eq(libinput_next_event_type(li), LIBINPUT_EVENT_NONE);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
litest_timeout_tap();
|
||||
|
||||
|
|
@ -204,29 +191,23 @@ START_TEST(touchpad_2fg_tap_n_drag)
|
|||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
|
||||
libinput_device_config_tap_set_enabled(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_down(dev, 0, 30, 70);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_down(dev, 1, 60, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 80, 80, 5, 40);
|
||||
litest_touch_down(dev, 0, 30, 70);
|
||||
litest_touch_down(dev, 1, 80, 70);
|
||||
litest_touch_move_to(dev, 0, 30, 70, 30, 30, 5, 40);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
while (libinput_next_event_type(li) == LIBINPUT_EVENT_POINTER_MOTION) {
|
||||
event = libinput_get_event(li);
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
litest_assert_empty_queue(li);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
|
|
@ -243,29 +224,23 @@ START_TEST(touchpad_2fg_tap_n_drag_3fg_btntool)
|
|||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
|
||||
libinput_device_config_tap_set_enabled(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_down(dev, 0, 30, 70);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_down(dev, 1, 60, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 80, 80, 5, 40);
|
||||
litest_touch_down(dev, 0, 30, 70);
|
||||
litest_touch_down(dev, 1, 80, 90);
|
||||
litest_touch_move_to(dev, 0, 30, 70, 30, 30, 5, 40);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
while (libinput_next_event_type(li) == LIBINPUT_EVENT_POINTER_MOTION) {
|
||||
event = libinput_get_event(li);
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
litest_assert_empty_queue(li);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
/* Putting down a third finger should end the drag */
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 1);
|
||||
|
|
@ -591,7 +566,6 @@ START_TEST(touchpad_1fg_tap_n_drag_click)
|
|||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
|
||||
libinput_device_config_tap_set_enabled(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
|
|
@ -608,15 +582,7 @@ START_TEST(touchpad_1fg_tap_n_drag_click)
|
|||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
ck_assert_int_eq(libinput_next_event_type(li),
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
while (libinput_next_event_type(li) == LIBINPUT_EVENT_POINTER_MOTION) {
|
||||
event = libinput_get_event(li);
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
|
@ -873,7 +839,6 @@ START_TEST(clickpad_click_n_drag)
|
|||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
|
|
@ -893,14 +858,7 @@ START_TEST(clickpad_click_n_drag)
|
|||
litest_touch_move_to(dev, 1, 70, 70, 80, 50, 5, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
|
||||
libinput_dispatch(li);
|
||||
ck_assert_int_eq(libinput_next_event_type(li),
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
do {
|
||||
event = libinput_get_event(li);
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
} while (libinput_next_event_type(li) == LIBINPUT_EVENT_POINTER_MOTION);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
|
@ -924,7 +882,7 @@ START_TEST(clickpad_softbutton_left)
|
|||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
|
@ -932,7 +890,7 @@ START_TEST(clickpad_softbutton_left)
|
|||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
|
|
@ -1481,18 +1439,19 @@ START_TEST(touchpad_2fg_scroll_slow_distance)
|
|||
|
||||
/* last event is value 0, tested elsewhere */
|
||||
while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE) {
|
||||
double axisval;
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
|
||||
ck_assert_int_eq(libinput_event_pointer_get_axis(ptrev),
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
||||
ck_assert(libinput_event_pointer_get_axis_value(ptrev) > 0.0);
|
||||
axisval = libinput_event_pointer_get_axis_value(ptrev,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
||||
ck_assert(axisval > 0.0);
|
||||
|
||||
/* this is to verify we test the right thing, if the value
|
||||
is greater than scroll.threshold we triggered the wrong
|
||||
condition */
|
||||
ck_assert(libinput_event_pointer_get_axis_value(ptrev) < 5.0);
|
||||
ck_assert(axisval < 5.0);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
event = libinput_get_event(li);
|
||||
|
|
@ -1503,6 +1462,67 @@ START_TEST(touchpad_2fg_scroll_slow_distance)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_2fg_scroll_source)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
test_2fg_scroll(dev, 0, 20, 0);
|
||||
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_POINTER_AXIS, -1);
|
||||
|
||||
while ((event = libinput_get_event(li))) {
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
ck_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev),
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_2fg_scroll_return_to_motion)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* start with motion */
|
||||
litest_touch_down(dev, 0, 70, 70);
|
||||
litest_touch_move_to(dev, 0, 70, 70, 47, 50, 10, 0);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
/* 2fg scroll */
|
||||
litest_touch_down(dev, 1, 53, 50);
|
||||
litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0);
|
||||
litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
litest_touch_move_to(dev, 0, 47, 70, 47, 50, 10, 0);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
/* back to 2fg scroll, lifting the other finger */
|
||||
litest_touch_down(dev, 1, 50, 50);
|
||||
litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0);
|
||||
litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
/* move with second finger */
|
||||
litest_touch_move_to(dev, 1, 53, 70, 53, 50, 10, 0);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
litest_touch_up(dev, 1);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_scroll_natural_defaults)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -1549,6 +1569,154 @@ START_TEST(touchpad_scroll_natural)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_edge_scroll)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 99, 20);
|
||||
litest_touch_move_to(dev, 0, 99, 20, 99, 80, 10, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 10);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_touch_down(dev, 0, 99, 80);
|
||||
litest_touch_move_to(dev, 0, 99, 80, 99, 20, 10, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -10);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_touch_down(dev, 0, 20, 99);
|
||||
litest_touch_move_to(dev, 0, 20, 99, 70, 99, 10, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 10);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_touch_down(dev, 0, 70, 99);
|
||||
litest_touch_move_to(dev, 0, 70, 99, 20, 99, 10, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -10);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_edge_scroll_slow_distance)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 99, 20);
|
||||
litest_touch_move_to(dev, 0, 99, 20, 99, 80, 60, 10);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert_notnull(event);
|
||||
|
||||
while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE) {
|
||||
double axisval;
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
|
||||
axisval = libinput_event_pointer_get_axis_value(ptrev,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
||||
ck_assert(axisval > 0.0);
|
||||
|
||||
/* this is to verify we test the right thing, if the value
|
||||
is greater than scroll.threshold we triggered the wrong
|
||||
condition */
|
||||
ck_assert(axisval < 5.0);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
event = libinput_get_event(li);
|
||||
}
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_edge_scroll_no_motion)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 99, 20);
|
||||
litest_touch_move_to(dev, 0, 99, 20, 99, 60, 10, 0);
|
||||
/* moving outside -> no motion event */
|
||||
litest_touch_move_to(dev, 0, 99, 60, 20, 80, 10, 0);
|
||||
/* moving down outside edge once scrolling had started -> scroll */
|
||||
litest_touch_move_to(dev, 0, 20, 80, 40, 99, 10, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 5);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_edge_scroll_no_edge_after_motion)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* moving into the edge zone must not trigger scroll events */
|
||||
litest_touch_down(dev, 0, 20, 20);
|
||||
litest_touch_move_to(dev, 0, 20, 20, 99, 20, 10, 0);
|
||||
litest_touch_move_to(dev, 0, 99, 20, 99, 80, 10, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_edge_scroll_source)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 99, 20);
|
||||
litest_touch_move_to(dev, 0, 99, 20, 99, 80, 10, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_POINTER_AXIS, -1);
|
||||
|
||||
while ((event = libinput_get_event(li))) {
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
ck_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev),
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_is_available)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -1697,8 +1865,6 @@ START_TEST(touchpad_palm_detect_palm_becomes_pointer)
|
|||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *ev;
|
||||
enum libinput_event_type type;
|
||||
|
||||
if (!touchpad_has_palm_detect_size(dev))
|
||||
return;
|
||||
|
|
@ -1711,15 +1877,7 @@ START_TEST(touchpad_palm_detect_palm_becomes_pointer)
|
|||
|
||||
libinput_dispatch(li);
|
||||
|
||||
ev = libinput_get_event(li);
|
||||
ck_assert_notnull(ev);
|
||||
do {
|
||||
type = libinput_event_get_type(ev);
|
||||
ck_assert_int_eq(type, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
libinput_event_destroy(ev);
|
||||
ev = libinput_get_event(li);
|
||||
} while (ev);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
|
|
@ -1729,8 +1887,6 @@ START_TEST(touchpad_palm_detect_no_palm_moving_into_edges)
|
|||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *ev;
|
||||
enum libinput_event_type type;
|
||||
|
||||
if (!touchpad_has_palm_detect_size(dev))
|
||||
return;
|
||||
|
|
@ -1746,16 +1902,7 @@ START_TEST(touchpad_palm_detect_no_palm_moving_into_edges)
|
|||
litest_touch_move_to(dev, 0, 99, 50, 99, 90, 5, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
type = libinput_next_event_type(li);
|
||||
do {
|
||||
|
||||
ck_assert_int_eq(type, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
ev = libinput_get_event(li);
|
||||
libinput_event_destroy(ev);
|
||||
|
||||
type = libinput_next_event_type(li);
|
||||
libinput_dispatch(li);
|
||||
} while (type != LIBINPUT_EVENT_NONE);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
|
@ -1770,7 +1917,7 @@ START_TEST(touchpad_left_handed)
|
|||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
status = libinput_device_config_left_handed_set(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
|
@ -1815,7 +1962,7 @@ START_TEST(touchpad_left_handed_clickpad)
|
|||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
status = libinput_device_config_left_handed_set(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
|
@ -1866,7 +2013,7 @@ START_TEST(touchpad_left_handed_clickfinger)
|
|||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
status = libinput_device_config_left_handed_set(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
|
@ -1909,7 +2056,7 @@ START_TEST(touchpad_left_handed_tapping)
|
|||
|
||||
libinput_device_config_tap_set_enabled(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
status = libinput_device_config_left_handed_set(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
|
@ -1940,7 +2087,7 @@ START_TEST(touchpad_left_handed_tapping_2fg)
|
|||
|
||||
libinput_device_config_tap_set_enabled(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
status = libinput_device_config_left_handed_set(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
|
@ -1976,7 +2123,7 @@ START_TEST(touchpad_left_handed_delayed)
|
|||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
status = libinput_device_config_left_handed_set(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
|
|
@ -1993,7 +2140,7 @@ START_TEST(touchpad_left_handed_delayed)
|
|||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 0);
|
||||
status = libinput_device_config_left_handed_set(d, 0);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_button_click(dev, BTN_RIGHT, 0);
|
||||
|
|
@ -2026,7 +2173,7 @@ START_TEST(touchpad_left_handed_clickpad_delayed)
|
|||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
status = libinput_device_config_left_handed_set(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
|
|
@ -2045,7 +2192,7 @@ START_TEST(touchpad_left_handed_clickpad_delayed)
|
|||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 0);
|
||||
status = libinput_device_config_left_handed_set(d, 0);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
|
|
@ -2122,9 +2269,16 @@ int main(int argc, char **argv) {
|
|||
|
||||
litest_add("touchpad:scroll", touchpad_2fg_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:scroll", touchpad_2fg_scroll_slow_distance, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:scroll", touchpad_2fg_scroll_return_to_motion, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:scroll", touchpad_2fg_scroll_source, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:scroll", touchpad_scroll_natural_defaults, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_scroll_natural_enable_config, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_scroll_natural, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll, LITEST_TOUCHPAD|LITEST_SINGLE_TOUCH, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_no_motion, LITEST_TOUCHPAD|LITEST_SINGLE_TOUCH, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_no_edge_after_motion, LITEST_TOUCHPAD|LITEST_SINGLE_TOUCH, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_slow_distance, LITEST_TOUCHPAD|LITEST_SINGLE_TOUCH, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_edge_scroll_source, LITEST_TOUCHPAD|LITEST_SINGLE_TOUCH, LITEST_ANY);
|
||||
|
||||
litest_add("touchpad:palm", touchpad_palm_detect_at_edge, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:palm", touchpad_palm_detect_at_bottom_corners, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
|
|
|
|||
|
|
@ -107,11 +107,35 @@ START_TEST(trackpoint_middlebutton_noscroll)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(trackpoint_scroll_source)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_button_scroll(dev, BTN_MIDDLE, 0, 6);
|
||||
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_POINTER_AXIS, -1);
|
||||
|
||||
while ((event = libinput_get_event(li))) {
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
|
||||
ck_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev),
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
21
test/udev.c
21
test/udev.c
|
|
@ -129,6 +129,26 @@ START_TEST(udev_create_empty_seat)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(udev_set_user_data)
|
||||
{
|
||||
struct libinput *li;
|
||||
struct udev *udev;
|
||||
int data1, data2;
|
||||
|
||||
udev = udev_new();
|
||||
ck_assert(udev != NULL);
|
||||
|
||||
li = libinput_udev_create_context(&simple_interface, &data1, udev);
|
||||
ck_assert(li != NULL);
|
||||
ck_assert(libinput_get_user_data(li) == &data1);
|
||||
libinput_set_user_data(li, &data2);
|
||||
ck_assert(libinput_get_user_data(li) == &data2);
|
||||
|
||||
libinput_unref(li);
|
||||
udev_unref(udev);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/**
|
||||
* This test only works if there's at least one device in the system that is
|
||||
* assigned the default seat. Should cover the 99% case.
|
||||
|
|
@ -488,6 +508,7 @@ main(int argc, char **argv)
|
|||
litest_add_no_device("udev:create", udev_create_NULL);
|
||||
litest_add_no_device("udev:create", udev_create_seat0);
|
||||
litest_add_no_device("udev:create", udev_create_empty_seat);
|
||||
litest_add_no_device("udev:create", udev_set_user_data);
|
||||
|
||||
litest_add_no_device("udev:seat", udev_added_seat_default);
|
||||
litest_add_no_device("udev:seat", udev_change_seat);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,16 @@
|
|||
noinst_PROGRAMS = event-debug
|
||||
noinst_LTLIBRARIES = libshared.la
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/src
|
||||
|
||||
|
||||
libshared_la_SOURCES = \
|
||||
shared.c \
|
||||
shared.h
|
||||
|
||||
event_debug_SOURCES = event-debug.c
|
||||
event_debug_LDADD = ../src/libinput.la $(LIBUDEV_LIBS)
|
||||
event_debug_LDADD = ../src/libinput.la libshared.la $(LIBUDEV_LIBS)
|
||||
event_debug_LDFLAGS = -no-install
|
||||
event_debug_CFLAGS = $(LIBUDEV_CFLAGS)
|
||||
|
||||
|
|
@ -12,7 +18,7 @@ if BUILD_EVENTGUI
|
|||
noinst_PROGRAMS += event-gui
|
||||
|
||||
event_gui_SOURCES = event-gui.c
|
||||
event_gui_LDADD = ../src/libinput.la $(CAIRO_LIBS) $(GTK_LIBS) $(LIBUDEV_LIBS)
|
||||
event_gui_LDADD = ../src/libinput.la libshared.la $(CAIRO_LIBS) $(GTK_LIBS) $(LIBUDEV_LIBS)
|
||||
event_gui_CFLAGS = $(CAIRO_CFLAGS) $(GTK_CFLAGS) $(LIBUDEV_CFLAGS)
|
||||
event_gui_LDFLAGS = -no-install
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <poll.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
|
@ -33,85 +32,16 @@
|
|||
#include <libudev.h>
|
||||
#include "linux/input.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/signalfd.h>
|
||||
|
||||
#include <libinput.h>
|
||||
|
||||
static enum {
|
||||
MODE_UDEV,
|
||||
MODE_DEVICE,
|
||||
} mode = MODE_UDEV;
|
||||
static const char *device;
|
||||
static const char *seat = "seat0";
|
||||
static struct udev *udev;
|
||||
#include "shared.h"
|
||||
|
||||
uint32_t start_time;
|
||||
static const uint32_t screen_width = 100;
|
||||
static const uint32_t screen_height = 100;
|
||||
static int verbose = 0;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage: %s [--verbose] [--udev [<seat>]|--device /dev/input/event0]\n"
|
||||
"--verbose ....... Print debugging output.\n"
|
||||
"--udev <seat>.... Use udev device discovery (default).\n"
|
||||
" Specifying a seat ID is optional.\n"
|
||||
"--device /path/to/device .... open the given device only\n",
|
||||
program_invocation_short_name);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_args(int argc, char **argv)
|
||||
{
|
||||
while (1) {
|
||||
int c;
|
||||
int option_index = 0;
|
||||
static struct option opts[] = {
|
||||
{ "device", 1, 0, 'd' },
|
||||
{ "udev", 0, 0, 'u' },
|
||||
{ "help", 0, 0, 'h' },
|
||||
{ "verbose", 0, 0, 'v'},
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "h", opts, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch(c) {
|
||||
case 'h': /* --help */
|
||||
usage();
|
||||
exit(0);
|
||||
case 'd': /* --device */
|
||||
mode = MODE_DEVICE;
|
||||
if (!optarg) {
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
device = optarg;
|
||||
break;
|
||||
case 'u': /* --udev */
|
||||
mode = MODE_UDEV;
|
||||
if (optarg)
|
||||
seat = optarg;
|
||||
break;
|
||||
case 'v': /* --verbose */
|
||||
verbose = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
struct tools_options options;
|
||||
static unsigned int stop = 0;
|
||||
|
||||
static int
|
||||
open_restricted(const char *path, int flags, void *user_data)
|
||||
|
|
@ -131,70 +61,6 @@ static const struct libinput_interface interface = {
|
|||
.close_restricted = close_restricted,
|
||||
};
|
||||
|
||||
static void
|
||||
log_handler(struct libinput *li,
|
||||
enum libinput_log_priority priority,
|
||||
const char *format,
|
||||
va_list args)
|
||||
{
|
||||
vprintf(format, args);
|
||||
}
|
||||
|
||||
static int
|
||||
open_udev(struct libinput **li)
|
||||
{
|
||||
udev = udev_new();
|
||||
if (!udev) {
|
||||
fprintf(stderr, "Failed to initialize udev\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
*li = libinput_udev_create_context(&interface, NULL, udev);
|
||||
if (!*li) {
|
||||
fprintf(stderr, "Failed to initialize context from udev\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
libinput_log_set_handler(*li, log_handler);
|
||||
libinput_log_set_priority(*li, LIBINPUT_LOG_PRIORITY_DEBUG);
|
||||
}
|
||||
|
||||
if (libinput_udev_assign_seat(*li, seat)) {
|
||||
fprintf(stderr, "Failed to set seat\n");
|
||||
libinput_unref(*li);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
open_device(struct libinput **li, const char *path)
|
||||
{
|
||||
struct libinput_device *device;
|
||||
|
||||
*li = libinput_path_create_context(&interface, NULL);
|
||||
if (!*li) {
|
||||
fprintf(stderr, "Failed to initialize context from %s\n", path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
libinput_log_set_handler(*li, log_handler);
|
||||
libinput_log_set_priority(*li, LIBINPUT_LOG_PRIORITY_DEBUG);
|
||||
}
|
||||
|
||||
device = libinput_path_add_device(*li, path);
|
||||
if (!device) {
|
||||
fprintf(stderr, "Failed to initialized device %s\n", path);
|
||||
libinput_unref(*li);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
print_event_header(struct libinput_event *ev)
|
||||
{
|
||||
|
|
@ -271,17 +137,28 @@ print_device_notify(struct libinput_event *ev)
|
|||
double w, h;
|
||||
uint32_t scroll_methods;
|
||||
|
||||
printf("%-30s %s %s",
|
||||
printf("%-33s %5s %7s",
|
||||
libinput_device_get_name(dev),
|
||||
libinput_seat_get_physical_name(seat),
|
||||
libinput_seat_get_logical_name(seat));
|
||||
|
||||
printf(" cap:");
|
||||
if (libinput_device_has_capability(dev,
|
||||
LIBINPUT_DEVICE_CAP_KEYBOARD))
|
||||
printf("k");
|
||||
if (libinput_device_has_capability(dev,
|
||||
LIBINPUT_DEVICE_CAP_POINTER))
|
||||
printf("p");
|
||||
if (libinput_device_has_capability(dev,
|
||||
LIBINPUT_DEVICE_CAP_TOUCH))
|
||||
printf("t");
|
||||
|
||||
if (libinput_device_get_size(dev, &w, &h) == 0)
|
||||
printf("\tsize %.2f/%.2fmm", w, h);
|
||||
|
||||
if (libinput_device_config_tap_get_finger_count((dev)))
|
||||
printf(" tap");
|
||||
if (libinput_device_config_buttons_has_left_handed((dev)))
|
||||
if (libinput_device_config_left_handed_is_available((dev)))
|
||||
printf(" left");
|
||||
if (libinput_device_config_scroll_has_natural_scroll((dev)))
|
||||
printf(" scroll-nat");
|
||||
|
|
@ -375,24 +252,18 @@ static void
|
|||
print_pointer_axis_event(struct libinput_event *ev)
|
||||
{
|
||||
struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
|
||||
enum libinput_pointer_axis axis = libinput_event_pointer_get_axis(p);
|
||||
const char *ax;
|
||||
double val;
|
||||
|
||||
switch (axis) {
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
|
||||
ax = "vscroll";
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
|
||||
ax = "hscroll";
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
double v = 0, h = 0;
|
||||
|
||||
if (libinput_event_pointer_has_axis(p,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
|
||||
v = libinput_event_pointer_get_axis_value(p,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
||||
if (libinput_event_pointer_has_axis(p,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
|
||||
h = libinput_event_pointer_get_axis_value(p,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
|
||||
print_event_time(libinput_event_pointer_get_time(p));
|
||||
val = libinput_event_pointer_get_axis_value(p);
|
||||
printf("%s %.2f\n", ax, val);
|
||||
printf("vert %.2f horiz %.2f\n", v, h);
|
||||
}
|
||||
|
||||
static const char*
|
||||
|
|
@ -532,6 +403,8 @@ handle_and_print_events(struct libinput *li)
|
|||
case LIBINPUT_EVENT_DEVICE_ADDED:
|
||||
case LIBINPUT_EVENT_DEVICE_REMOVED:
|
||||
print_device_notify(ev);
|
||||
tools_device_apply_config(libinput_event_get_device(ev),
|
||||
&options);
|
||||
break;
|
||||
case LIBINPUT_EVENT_KEYBOARD_KEY:
|
||||
print_key_event(ev);
|
||||
|
|
@ -584,27 +457,30 @@ handle_and_print_events(struct libinput *li)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
sighandler(int signal, siginfo_t *siginfo, void *userdata)
|
||||
{
|
||||
stop = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
mainloop(struct libinput *li)
|
||||
{
|
||||
struct pollfd fds[2];
|
||||
sigset_t mask;
|
||||
struct pollfd fds;
|
||||
struct sigaction act;
|
||||
|
||||
fds[0].fd = libinput_get_fd(li);
|
||||
fds[0].events = POLLIN;
|
||||
fds[0].revents = 0;
|
||||
fds.fd = libinput_get_fd(li);
|
||||
fds.events = POLLIN;
|
||||
fds.revents = 0;
|
||||
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGINT);
|
||||
memset(&act, 0, sizeof(act));
|
||||
act.sa_sigaction = sighandler;
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
|
||||
fds[1].fd = signalfd(-1, &mask, SFD_NONBLOCK);
|
||||
fds[1].events = POLLIN;
|
||||
fds[1].revents = 0;
|
||||
|
||||
if (fds[1].fd == -1 ||
|
||||
sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
|
||||
if (sigaction(SIGINT, &act, NULL) == -1) {
|
||||
fprintf(stderr, "Failed to set up signal handling (%s)\n",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle already-pending device added events */
|
||||
|
|
@ -612,14 +488,8 @@ mainloop(struct libinput *li)
|
|||
fprintf(stderr, "Expected device added events on startup but got none. "
|
||||
"Maybe you don't have the right permissions?\n");
|
||||
|
||||
while (poll(fds, 2, -1) > -1) {
|
||||
if (fds[1].revents)
|
||||
break;
|
||||
|
||||
while (!stop && poll(&fds, 1, -1) > -1)
|
||||
handle_and_print_events(li);
|
||||
}
|
||||
|
||||
close(fds[1].fd);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -628,17 +498,14 @@ main(int argc, char **argv)
|
|||
struct libinput *li;
|
||||
struct timespec tp;
|
||||
|
||||
if (parse_args(argc, argv))
|
||||
tools_init_options(&options);
|
||||
|
||||
if (tools_parse_args(argc, argv, &options))
|
||||
return 1;
|
||||
|
||||
if (mode == MODE_UDEV) {
|
||||
if (open_udev(&li))
|
||||
return 1;
|
||||
} else if (mode == MODE_DEVICE) {
|
||||
if (open_device(&li, device))
|
||||
return 1;
|
||||
} else
|
||||
abort();
|
||||
li = tools_open_backend(&options, NULL, &interface);
|
||||
if (!li)
|
||||
return 1;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
start_time = tp.tv_sec * 1000 + tp.tv_nsec / 1000000;
|
||||
|
|
@ -646,8 +513,6 @@ main(int argc, char **argv)
|
|||
mainloop(li);
|
||||
|
||||
libinput_unref(li);
|
||||
if (udev)
|
||||
udev_unref(udev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#include <cairo.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -40,8 +39,12 @@
|
|||
#include <libinput.h>
|
||||
#include <libinput-util.h>
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
#define clip(val_, min_, max_) min((max_), max((min_), (val_)))
|
||||
|
||||
struct tools_options options;
|
||||
|
||||
struct touch {
|
||||
int active;
|
||||
int x, y;
|
||||
|
|
@ -95,12 +98,6 @@ msg(const char *fmt, ...)
|
|||
va_end(args);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("%s [path/to/device]\n", program_invocation_short_name);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
draw(GtkWidget *widget, cairo_t *cr, gpointer data)
|
||||
{
|
||||
|
|
@ -361,20 +358,20 @@ static void
|
|||
handle_event_axis(struct libinput_event *ev, struct window *w)
|
||||
{
|
||||
struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
|
||||
enum libinput_pointer_axis axis = libinput_event_pointer_get_axis(p);
|
||||
double v = libinput_event_pointer_get_axis_value(p);
|
||||
double v, h;
|
||||
|
||||
switch (axis) {
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
|
||||
v = libinput_event_pointer_get_axis_value(p,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
||||
h = libinput_event_pointer_get_axis_value(p,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
|
||||
|
||||
if (v != 0.0) {
|
||||
w->vy += (int)v;
|
||||
w->vy = clip(w->vy, 0, w->height);
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
|
||||
}
|
||||
if (h != 0.0) {
|
||||
w->hx += (int)v;
|
||||
w->hx = clip(w->hx, 0, w->width);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -495,35 +492,6 @@ sockets_init(struct libinput *li)
|
|||
g_io_add_watch(c, G_IO_IN, handle_event_libinput, li);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_opts(int argc, char *argv[])
|
||||
{
|
||||
while (1) {
|
||||
static struct option long_options[] = {
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
};
|
||||
|
||||
int option_index = 0;
|
||||
int c;
|
||||
|
||||
c = getopt_long(argc, argv, "h", long_options,
|
||||
&option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch(c) {
|
||||
case 'h':
|
||||
usage();
|
||||
return 0;
|
||||
default:
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
open_restricted(const char *path, int flags, void *user_data)
|
||||
{
|
||||
|
|
@ -551,16 +519,18 @@ main(int argc, char *argv[])
|
|||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
if (parse_opts(argc, argv) != 0)
|
||||
tools_init_options(&options);
|
||||
|
||||
if (tools_parse_args(argc, argv, &options) != 0)
|
||||
return 1;
|
||||
|
||||
udev = udev_new();
|
||||
if (!udev)
|
||||
error("Failed to initialize udev\n");
|
||||
|
||||
li = libinput_udev_create_context(&interface, &w, udev);
|
||||
if (!li || libinput_udev_assign_seat(li, "seat0") != 0)
|
||||
error("Failed to initialize context from udev\n");
|
||||
li = tools_open_backend(&options, &w, &interface);
|
||||
if (!li)
|
||||
return 1;
|
||||
|
||||
window_init(&w);
|
||||
sockets_init(li);
|
||||
|
|
|
|||
266
tools/shared.c
Normal file
266
tools/shared.c
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libudev.h>
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
enum options {
|
||||
OPT_DEVICE,
|
||||
OPT_UDEV,
|
||||
OPT_HELP,
|
||||
OPT_VERBOSE,
|
||||
OPT_TAP_ENABLE,
|
||||
OPT_TAP_DISABLE,
|
||||
OPT_NATURAL_SCROLL_ENABLE,
|
||||
OPT_NATURAL_SCROLL_DISABLE,
|
||||
OPT_LEFT_HANDED_ENABLE,
|
||||
OPT_LEFT_HANDED_DISABLE,
|
||||
};
|
||||
|
||||
static void
|
||||
log_handler(struct libinput *li,
|
||||
enum libinput_log_priority priority,
|
||||
const char *format,
|
||||
va_list args)
|
||||
{
|
||||
vprintf(format, args);
|
||||
}
|
||||
|
||||
void
|
||||
tools_usage()
|
||||
{
|
||||
printf("Usage: %s [options] [--udev [<seat>]|--device /dev/input/event0]\n"
|
||||
"--udev <seat>.... Use udev device discovery (default).\n"
|
||||
" Specifying a seat ID is optional.\n"
|
||||
"--device /path/to/device .... open the given device only\n"
|
||||
"\n"
|
||||
"Features:\n"
|
||||
"--enable-tap\n"
|
||||
"--disable-tap.... enable/disable tapping\n"
|
||||
"--enable-natural-scrolling\n"
|
||||
"--disable-natural-scrolling.... enable/disable natural scrolling\n"
|
||||
"--enable-left-handed\n"
|
||||
"--disable-left-handed.... enable/disable left-handed button configuration\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"
|
||||
"\n"
|
||||
"Other options:\n"
|
||||
"--verbose ....... Print debugging output.\n"
|
||||
"--help .......... Print this help.\n",
|
||||
program_invocation_short_name);
|
||||
}
|
||||
|
||||
void
|
||||
tools_init_options(struct tools_options *options)
|
||||
{
|
||||
memset(options, 0, sizeof(*options));
|
||||
options->tapping = -1;
|
||||
options->natural_scroll = -1;
|
||||
options->left_handed = -1;
|
||||
options->backend = BACKEND_UDEV;
|
||||
options->seat = "seat0";
|
||||
}
|
||||
|
||||
int
|
||||
tools_parse_args(int argc, char **argv, struct tools_options *options)
|
||||
{
|
||||
while (1) {
|
||||
int c;
|
||||
int option_index = 0;
|
||||
static struct option opts[] = {
|
||||
{ "device", 1, 0, OPT_DEVICE },
|
||||
{ "udev", 0, 0, OPT_UDEV },
|
||||
{ "help", 0, 0, OPT_HELP },
|
||||
{ "verbose", 0, 0, OPT_VERBOSE },
|
||||
{ "enable-tap", 0, 0, OPT_TAP_ENABLE },
|
||||
{ "disable-tap", 0, 0, OPT_TAP_DISABLE },
|
||||
{ "enable-natural-scrolling", 0, 0, OPT_NATURAL_SCROLL_ENABLE },
|
||||
{ "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 },
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "h", opts, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch(c) {
|
||||
case 'h': /* --help */
|
||||
case OPT_HELP:
|
||||
tools_usage();
|
||||
exit(0);
|
||||
case OPT_DEVICE: /* --device */
|
||||
options->backend = BACKEND_DEVICE;
|
||||
if (!optarg) {
|
||||
tools_usage();
|
||||
return 1;
|
||||
}
|
||||
options->device = optarg;
|
||||
break;
|
||||
case OPT_UDEV: /* --udev */
|
||||
options->backend = BACKEND_UDEV;
|
||||
if (optarg)
|
||||
options->seat = optarg;
|
||||
break;
|
||||
case OPT_VERBOSE: /* --verbose */
|
||||
options->verbose = 1;
|
||||
break;
|
||||
case OPT_TAP_ENABLE:
|
||||
options->tapping = 1;
|
||||
break;
|
||||
case OPT_TAP_DISABLE:
|
||||
options->tapping = 0;
|
||||
break;
|
||||
case OPT_NATURAL_SCROLL_ENABLE:
|
||||
options->natural_scroll = 1;
|
||||
break;
|
||||
case OPT_NATURAL_SCROLL_DISABLE:
|
||||
options->natural_scroll = 0;
|
||||
break;
|
||||
case OPT_LEFT_HANDED_ENABLE:
|
||||
options->left_handed = 1;
|
||||
break;
|
||||
case OPT_LEFT_HANDED_DISABLE:
|
||||
options->left_handed = 0;
|
||||
break;
|
||||
default:
|
||||
tools_usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
tools_usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct libinput *
|
||||
open_udev(const struct libinput_interface *interface,
|
||||
void *userdata,
|
||||
const char *seat,
|
||||
int verbose)
|
||||
{
|
||||
struct libinput *li;
|
||||
struct udev *udev = udev_new();
|
||||
|
||||
if (!udev) {
|
||||
fprintf(stderr, "Failed to initialize udev\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
li = libinput_udev_create_context(interface, userdata, udev);
|
||||
if (!li) {
|
||||
fprintf(stderr, "Failed to initialize context from udev\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
libinput_log_set_handler(li, log_handler);
|
||||
libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG);
|
||||
}
|
||||
|
||||
if (libinput_udev_assign_seat(li, seat)) {
|
||||
fprintf(stderr, "Failed to set seat\n");
|
||||
libinput_unref(li);
|
||||
li = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
udev_unref(udev);
|
||||
return li;
|
||||
}
|
||||
|
||||
static struct libinput *
|
||||
open_device(const struct libinput_interface *interface,
|
||||
void *userdata,
|
||||
const char *path,
|
||||
int verbose)
|
||||
{
|
||||
struct libinput_device *device;
|
||||
struct libinput *li;
|
||||
|
||||
li = libinput_path_create_context(interface, userdata);
|
||||
if (!li) {
|
||||
fprintf(stderr, "Failed to initialize context from %s\n", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
libinput_log_set_handler(li, log_handler);
|
||||
libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG);
|
||||
}
|
||||
|
||||
device = libinput_path_add_device(li, path);
|
||||
if (!device) {
|
||||
fprintf(stderr, "Failed to initialized device %s\n", path);
|
||||
libinput_unref(li);
|
||||
li = NULL;
|
||||
}
|
||||
|
||||
return li;
|
||||
}
|
||||
|
||||
struct libinput *
|
||||
tools_open_backend(struct tools_options *options,
|
||||
void *userdata,
|
||||
const struct libinput_interface *interface)
|
||||
{
|
||||
struct libinput *li = NULL;
|
||||
|
||||
if (options->backend == BACKEND_UDEV) {
|
||||
li = open_udev(interface, userdata, options->seat, options->verbose);
|
||||
} else if (options->backend == BACKEND_DEVICE) {
|
||||
li = open_device(interface, userdata, options->device, options->verbose);
|
||||
} else
|
||||
abort();
|
||||
|
||||
return li;
|
||||
}
|
||||
|
||||
void
|
||||
tools_device_apply_config(struct libinput_device *device,
|
||||
struct tools_options *options)
|
||||
{
|
||||
if (options->tapping != -1)
|
||||
libinput_device_config_tap_set_enabled(device, options->tapping);
|
||||
if (options->natural_scroll != -1)
|
||||
libinput_device_config_scroll_set_natural_scroll_enabled(device,
|
||||
options->natural_scroll);
|
||||
if (options->left_handed != -1)
|
||||
libinput_device_config_left_handed_set(device, options->left_handed);
|
||||
}
|
||||
53
tools/shared.h
Normal file
53
tools/shared.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _SHARED_H_
|
||||
#define _SHARED_H_
|
||||
|
||||
#include <libinput.h>
|
||||
|
||||
enum tools_backend {
|
||||
BACKEND_DEVICE,
|
||||
BACKEND_UDEV
|
||||
};
|
||||
|
||||
struct tools_options {
|
||||
enum tools_backend backend;
|
||||
const char *device; /* if backend is BACKEND_DEVICE */
|
||||
const char *seat; /* if backend is BACKEND_UDEV */
|
||||
|
||||
int verbose;
|
||||
int tapping;
|
||||
int natural_scroll;
|
||||
int left_handed;
|
||||
};
|
||||
|
||||
void tools_init_options(struct tools_options *options);
|
||||
int tools_parse_args(int argc, char **argv, struct tools_options *options);
|
||||
struct libinput* tools_open_backend(struct tools_options *options,
|
||||
void *userdata,
|
||||
const struct libinput_interface *interface);
|
||||
void tools_device_apply_config(struct libinput_device *device,
|
||||
struct tools_options *options);
|
||||
void tools_usage();
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Reference in a new issue