Compare commits

...

40 Commits

Author SHA1 Message Date
Peter Hutterer
c67f191d5b xf86-input-libinput 0.28.0
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2018-07-11 11:06:59 +10:00
Peter Hutterer
1978a2555b Minor whitespace fix
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2018-07-11 10:59:20 +10:00
Peter Hutterer
0909a1a765 draglock: fix memory overwrite during draglock parsing
Passing in the size of the array but using it as "number of elements" inside
the function. Rename a bunch of arguments to avoid this.

https://bugs.freedesktop.org/show_bug.cgi?id=107166

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2018-07-10 11:17:50 +10:00
Peter Hutterer
20bb8d6b9f Revert "Implement the custom acceleration curve options"
Custom pointer acceleration curves were reverted in libinput, so no point
having this code here.

This reverts commit d84e0035d1.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2018-05-23 08:14:23 +10:00
Peter Hutterer
1e88664d95 Use the libinput touch count to init the right number of touches
Initial version by Johannes Pointner <h4nn35.work@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2018-05-02 13:59:00 +10:00
Peter Hutterer
d84e0035d1 Implement the custom acceleration curve options
One new property, and the existing accel profile gets extended to keep one
extra value. The new property libinput Accel Curve Points is a list of pairs
of points to be added to the acceleration curve.

libinput only supports adding points to the curve so we simply declare the
behavior as undefined when the curve is set multiple times. Also helps to
identify those that bother to read the man page before playing with random
driver values.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2018-04-20 14:04:25 +10:00
Peter Hutterer
6c75acfcdf Use xf86SetStrOption to check for string options
This one shows up in the log and marks it as used.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2018-04-20 13:34:23 +10:00
Peter Hutterer
eaf847be16 man: whitespace fixes in man page
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2018-04-17 15:11:12 +10:00
Peter Hutterer
d319092d55 man: fix formatting issue caused by invalid tag
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2018-04-17 13:52:33 +10:00
Peter Hutterer
18cc042e68 xf86-input-libinput 0.27.1
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2018-04-10 09:19:52 +10:00
Evangelos Foutras
0db82219bb Fix "left handed" property not set on all pointers
Remove conditional that prevents the LIBINPUT_PROP_LEFT_HANDED{,DEFAULT}
properties from being set on all pointer devices (only the first got it).
This appears to be a debugging left-over accidentally merged in
6d3bd4544a.

https://bugs.freedesktop.org/show_bug.cgi?id=105667

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2018-03-22 10:59:01 +10:00
Peter Hutterer
f93bc148d4 xf86-input-libinput 0.27.0
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2018-03-20 11:23:57 +10:00
Peter Hutterer
0d4b50fd6e man: note that we don't do /dev/input/by-id or /dev/input/by-path
For logind-setups we need to match the path libinput wants to open with the
Option Device path that the device has so we know when to return the
server-fd. This doesn't work for by-id or by-path because libinput resolves
those (through udev) to the actual eventX node so our paths look different
when they are the same device.

This could be fixed but since this is easy enough to work around with a
InputClass section and rather a niche case, it's not really worth the effort.

https://bugs.freedesktop.org/show_bug.cgi?id=105562

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Adam Jackson <ajax@redhat.com>
2018-03-20 10:48:04 +10:00
Peter Hutterer
9d9f59fd4c Apply the capabilities checks on subdevices when applying the config
Properties are initialized on the correct devices only but on resume we'd just
blindly apply the config from our device. Depending on the resume order, this
would mean we'd apply a previously set config with a default config.

Example:
* pointer device with keyboard subdevice
* pointer device exports natural scrolling, keyboard device does not and
  remains at default (off)
* client enables natural scrolling on the pointer device
* VT switch away, VT switch back
* pointer device gets enabled first, enables natural scrolling on the
  libinput device
* keyboard device gets enabled second, resets to the default value

Reported-by: Yuxuan Shui <yshuiv7@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Tested-by: Yuxuan Shui <yshuiv7@gmail.com>
2018-02-21 09:53:12 +10:00
Peter Hutterer
7353481490 Split LibinputDeviceApplyConfig into helper functions
No functional changes
2018-02-02 14:25:44 +10:00
Peter Hutterer
6d3bd4544a Move the subdevice capabilities check into the properties
87f9fe3a6fafe60134c6's intention was to not create properties that a subdevice
doesn't have configuration options for (i.e. if you have a pointer+keyboard
device, don't expose tapping configuration on the keyboard subdevice).

The result was messy, the checker function had a confusing triple-negation and
some properties weren't checked - e.g. left-handed was allowed for touch/tablet
but not for pointer, dwt was allowed for any device.

Fix this by moving the check into the property init function directly and
inverting the helper function to be easier to read.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2018-02-02 14:25:31 +10:00
Peter Hutterer
2be6487de4 xf86-input-libinput 0.26.0
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-09-15 11:26:54 +10:00
Peter Hutterer
6ce3d0249d Post a motion event before a tablet button down
Not all clients update the pointer position correctly from the button events
(for historical reasons) so we need to send a motion event before the button
event that represents a tip state change.

https://bugs.freedesktop.org/show_bug.cgi?id=101588

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-08-17 15:20:29 +10:00
Peter Hutterer
87f9fe3a6f Only initialize properties that match capabilities on a subdevice
If a device is split into multiple subdevices, usually pointer+keyboard, we
initialized properties matching the libinput device on both devices. This
results in the keyboard having e.g. a Accel Speed or Left Handed settings even
though it cannot send any events of that type.

Filter by capabilities on the subdevice so we only get those properties that
match the subdevice's capabilities.

https://bugs.freedesktop.org/show_bug.cgi?id=100900

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-05-29 08:15:20 +10:00
Peter Hutterer
0c657e0dcf Update copyright years
because why not

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-05-18 14:03:06 +10:00
Niklas Haas
ac3574958f man: add missing documentation for Accel Profile
This seems to have been simply missing from 0163482e.

cf. https://bugs.freedesktop.org/show_bug.cgi?id=101017

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-05-15 11:41:46 +10:00
Martin Kepplinger
8772a593b4 Fix config comment description to match the config
Since the config matches on tablets too, update the describing comment
accordingly.

Signed-off-by: Martin Kepplinger <martin.kepplinger@ginzinger.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-05-08 10:33:58 +10:00
Peter Hutterer
a80773a488 xf86-input-libinput 0.25.1
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-05-05 13:43:23 +10:00
Peter Hutterer
8bc694595d Post a motion event after proximity events
This patch splits the meat of xf86libinput_handle_tablet_axis into a helper
function xf86libinput_post_tablet_motion(), to be called right after we send
the proximity in event.

Clients that don't handle proximity (e.g. all XI2 clients) don't see the
coordinates we send along with the proximity events. And, for historical
reasons, they may not look at the coordinates in button events. So a device
that comes into proximity and immediately sends a tip down button event
doesn't send a motion event, causing the client to think the tip down was at
whatever the last known position was (before previous prox-out).

The practical effect is that when a user tries to draw a few dots, they end up
being connected to each other.

https://bugzilla.redhat.com/show_bug.cgi?id=1433755

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-03-22 11:14:15 +10:00
Peter Hutterer
153a7fc62f xf86-input-libinput 0.25.0
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-03-09 15:58:39 +10:00
Peter Hutterer
72fb6d304e test: fix a test failure on ppc64(le) and aarch64
Caused by different results in -O0 vs -O2. The resulting array differs only
slightly but the initial sequence has one extra zero. That triggers our
assert, no other compiler flag seem to be affecting this.

Compiled with -O0:
Breakpoint 1, test_nonzero_x_linear () at test-bezier.c:157
157			assert(bezier[x] > bezier[x-1]);
(gdb) p bezier
$6 = {0 <repeats 409 times>, 1, 2, 4, 5, 7, 9, 10, 12, 14, 15, 17, 19, 21, 22,

Compiled with -O2:
(gdb) p bezier
$1 = {0 <repeats 410 times>, 1, 3, 5, 7, 9, 10, 12, 14, 15, 17, 19, 20, 22,

Printing of the temporary numbers in the decasteljau function shows that a few
of them are off by one, e.g.
    408.530612/0.836735 with O0, but
    409.510204/0.836735 with O2
Note: these are not rounding errors caused by the code, the cast to int
happens afterwards.

Hack around this by allowing for one extra zero before we check that the rest
of the curve is ascending again.

https://bugs.freedesktop.org/show_bug.cgi?id=99992

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-02-28 15:27:33 +10:00
Peter Hutterer
aae2c8ad9a Open sysfs files directly instead of going through the server
Only use-case here are pad mode LEDs that now live in /sys/class/leds. Asking
the server to open them is pointless, the server only knows how to open Option
"Device". And since the LEDs are in sysfs we should have access to them
anyway, so no need for jumping through or hula-ing hoops.

xf86CloseSerial() works as intended as it's a slim wrapper around close(), so
we only have to worry about the open() path here.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-02-27 09:34:36 +10:00
Peter Hutterer
dafc296f2d Add streq() macro, replace strcmp instances with it
And why isn't this a thing in glibc yet

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Eric Engestrom <eric.engestrom@imgtec.com>
2017-02-27 09:34:36 +10:00
Peter Hutterer
7c90f06d56 Update pad modes in a workproc, not during the input thread
Updating the property directly causes us to send events from the input thread
which has some "interesting" side effects like messing up the reply order or
just crashing the server.

Schedule a work proc instead and update it whenever the server is back in the
main thread.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-02-27 09:34:36 +10:00
Peter Hutterer
2eb5a2f0c0 xf86-input-libinput 0.24.0
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-02-09 16:16:34 +10:00
Peter Hutterer
19ceef972e Drop unnecessary function declaration
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-01-27 12:14:29 +10:00
Mihail Konev
07f30ea049 autogen: add default patch prefix
Signed-off-by: Mihail Konev <k.mvc@ya.ru>
2017-01-26 14:00:21 +10:00
Emil Velikov
6187ed0450 autogen.sh: use quoted string variables
Place quotes around the $srcdir, $ORIGDIR and $0 variables to prevent
fall-outs, when they contain space.

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-01-26 11:26:20 +10:00
Peter Hutterer
974ab6b62b Add tablet tool area ratio property
By default, the X server maps the tablet axes to the available screen area.
When a tablet is mapped to the screen but has a different aspect ratio than
the screen, input data is skewed. Expose an area ratio property to map the
a subsection of the available tablet area into the desired ratio.

Differences to the wacom driver: there the x/y min/max values must be
specified manually and in device coordinates. For this driver we merely
provide the area ratio (e.g. 4:3) and let the driver work out the rest.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Jason Gerecke <jason.gerecke@wacom.com>
2017-01-12 14:53:41 +10:00
Peter Hutterer
5d04707381 Implement stylus pressure curve support
Takes a 4-point cubic bezier curve as input and maps the pressure coordinates
to the values outlined by this curve. This is an extension of the current
implementation in the xf86-input-wacom driver which only allows the two center
control points to be modified.

Over the years a few users have noted that the wacom driver's pressure curve
makes it impossible to cap the pressure at a given value. Given our bezier
implementation here, it's effectively a freebie to add configurability of the
first and last control points. We do require all control points' x coordinates
to be in ascending order.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-01-04 09:57:57 +10:00
Peter Hutterer
f65a5c5022 Add a bezier curve implementation
Needed for the wacom stylus pressure curve

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2017-01-03 17:31:42 +10:00
Peter Hutterer
0dad7408fa Calculate the required scroll distance based on the angle
For a mouse with a click angle of 15 degrees things are unchanged. For devices
with angles less than 10, the current code scrolled way too fast. Because the
angle wasn't used anywhere, each tick would count as full scroll wheel event,
a slight movement of the wheel would thus scroll as much as a large movement
on a normal mouse.

Fix this by taking the actual click angle of the device into account. We
calculate some multiple of the angle that's close enough to the default 15
degrees of the wheel and then require that many click events to hit the full
scroll distance. For example, a mouse with a click angle of 3 degrees now
requires 5 clicks to trigger a full legacy scroll button event.

XI2.1 clients get the intermediate events (i.e. in this case five times
one-fifth of the scroll distance) and can thus scroll smoothly, or more
specifically in smaller events than usual.

https://bugs.freedesktop.org/show_bug.cgi?id=92772

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2017-01-03 15:16:21 +10:00
Peter Hutterer
ea02578a4e Move axis value calculation into a helper function
The only difference here is the axis number.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2017-01-03 15:16:21 +10:00
Peter Hutterer
2ceb2e1b18 Add a comment regarding scroll dist default values
Changed this during development because I forgot that the value actually
matters (for touchpads anyway).

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2017-01-03 15:16:21 +10:00
Peter Hutterer
f47f78eb0b Ignore LED updates for disabled devices
If an XKB AccessX timeout is set and a VT switch is triggered, the
AccessXTimeoutExpire function may be called after the device has already been
disabled. This can cause a null-pointer dereference as our shared libinput
device may have been released by then.

In the legacy drivers this would've simply caused a write to an invalid fd
(-1), not a crash. Here we need to be more careful.

https://bugs.freedesktop.org/show_bug.cgi?id=98464

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2016-12-21 07:58:26 +10:00
13 changed files with 1378 additions and 104 deletions

View File

@@ -1,14 +1,17 @@
#! /bin/sh
srcdir=`dirname $0`
srcdir=`dirname "$0"`
test -z "$srcdir" && srcdir=.
ORIGDIR=`pwd`
cd $srcdir
cd "$srcdir"
autoreconf -v --install || exit 1
cd $ORIGDIR || exit $?
cd "$ORIGDIR" || exit $?
git config --local --get format.subjectPrefix >/dev/null 2>&1 ||
git config --local format.subjectPrefix "PATCH xf86-input-libinput"
if test -z "$NOCONFIGURE"; then
exec $srcdir/configure "$@"
exec "$srcdir"/configure "$@"
fi

View File

@@ -1,4 +1,4 @@
# Match on all types of devices but tablet devices and joysticks
# Match on all types of devices but joysticks
Section "InputClass"
Identifier "libinput pointer catchall"
MatchIsPointer "on"

View File

@@ -23,7 +23,7 @@
# Initialize Autoconf
AC_PREREQ([2.60])
AC_INIT([xf86-input-libinput],
[0.23.0],
[0.28.0],
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
[xf86-input-libinput])
AC_CONFIG_SRCDIR([Makefile.am])
@@ -47,6 +47,23 @@ XORG_DEFAULT_OPTIONS
PKG_CHECK_MODULES(XORG, [xorg-server >= 1.10] xproto [inputproto >= 2.2])
PKG_CHECK_MODULES(LIBINPUT, [libinput >= 1.4.901])
OLD_LIBS=$LIBS
OLD_CFLAGS=$CFLAGS
LIBS="$LIBS $LIBINPUT_LIBS"
CFLAGS="$CFLAGS $LIBINPUT_CFLAGS"
AC_MSG_CHECKING([if libinput_device_touch_get_touch_count is available])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[#include <libinput.h>]],
[[libinput_device_touch_get_touch_count(NULL)]])],
[AC_MSG_RESULT([yes])
AC_DEFINE(HAVE_LIBINPUT_TOUCH_COUNT, [1],
[libinput_device_touch_get_touch_count() is available])
[libinput_have_touch_count=yes]],
[AC_MSG_RESULT([no])
[libinput_have_touch_count=no]])
LIBS=$OLD_LIBS
CFLAGS=$OLD_CFLAGS
# Define a configure option for an alternate input module directory
AC_ARG_WITH(xorg-module-dir,
AC_HELP_STRING([--with-xorg-module-dir=DIR],

View File

@@ -183,4 +183,14 @@
/* Device rotation: FLOAT, 1 value, 32 bit, read-only */
#define LIBINPUT_PROP_ROTATION_ANGLE_DEFAULT "libinput Rotation Angle Default"
/* Tablet tool pressure curve: float, 8 values, 32 bit
* Value range is [0.0, 1.0], the values specify the x/y of the four
* control points for a cubic bezier curve.
* Default value: 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0
*/
#define LIBINPUT_PROP_TABLET_TOOL_PRESSURECURVE "libinput Tablet Tool Pressurecurve"
/* Tablet tool area ratio: CARD32, 2 values, w and h */
#define LIBINPUT_PROP_TABLET_TOOL_AREA_RATIO "libinput Tablet Tool Area Ratio"
#endif /* _LIBINPUT_PROPERTIES_H_ */

View File

@@ -15,11 +15,11 @@ libinput \- libinput-based X.Org input driver
.SH NOTE
This is the man page for the X input driver. If you are looking for the
library documentation, go to
library documentation, go to
.BI http://wayland.freedesktop.org/libinput/doc/
.SH DESCRIPTION
.B libinput
.B libinput
is an __xservername__ input driver based on libinput. It
therefore supports all input devices that libinput can handle, including
most mice, keyboards, tablets and touchscreens.
@@ -37,7 +37,7 @@ Please refer to __xconfigfile__(__filemansuffix__) for general configuration
details and for options that can be used with all input drivers. This
section only covers configuration details specific to this driver.
.PP
The following driver
The following driver
.B Options
are supported:
.TP 7
@@ -155,6 +155,20 @@ default scroll option for this device is used.
Sets the send events mode to disabled, enabled, or "disable when an external
mouse is connected".
.TP 7
.BI "Option \*qTabletToolPressureCurve\*q \*q" "x0/y0 x1/y1 x2/y2 x3/y3" \*q
Set the pressure curve for a tablet stylus to the bezier formed by the four
points. The respective x/y coordinate must be in the [0.0, 1.0] range. For
more information see section
.B TABLET STYLUS PRESSURE CURVE.
.TP 7
.BI "Option \*qTabletToolAreaRatio\*q \*q" "w:h" \*q
Sets the area ratio for a tablet tool. The area always starts at the
origin (0/0) and expands to the largest available area with the specified
aspect ratio. Events outside this area are cropped to the area. The special
value "default" is used for the default mapping (i.e. the device-native
mapping). For more information see section
.B TABLET TOOL AREA RATIO.
.TP 7
.BI "Option \*qTapping\*q \*q" bool \*q
Enables or disables tap-to-click behavior.
.TP 7
@@ -189,6 +203,14 @@ on the device. The following properties are provided by the
.B libinput
driver.
.TP 7
.BI "libinput Accel Profiles Available"
2 boolean values (8 bit, 0 or 1), in order "adaptive", "flat".
Indicates which acceleration profiles are available on this device.
.TP 7
.BI "libinput Accel Profile Enabled"
2 boolean values (8 bit, 0 or 1), in order "adaptive", "flat".
Indicates which acceleration profile is currently enabled on this device.
.TP 7
.BI "libinput Accel Speed"
1 32-bit float value, defines the pointer speed. Value range -1, 1
.TP 7
@@ -252,6 +274,16 @@ on this device.
"disabled-on-external-mouse". Indicates which send-event modes is currently
enabled on this device.
.TP 7
.BI "libinput Tablet Tool Pressurecurve"
4 32-bit float values [0.0 to 1.0]. See section
.B TABLET TOOL PRESSURE CURVE
.TP 7
.BI "libinput Tablet Tool Area Ratio"
2 32-bit values, corresponding to width and height. Special value 0, 0
resets to the default ratio. See section
.B TABLET TOOL AREA RATIO
for more information.
.TP 7
.BI "libinput Tapping Enabled"
1 boolean value (8 bit, 0 or 1). 1 enables tapping
.TP 7
@@ -313,6 +345,48 @@ and only the target button events are sent.
.TP
This feature is provided by this driver, not by libinput.
.SH TABLET TOOL PRESSURECURVE
The pressure curve affects how stylus pressure is reported. By default, the
hardware pressure is reported as-is. By setting a pressure curve, the feel
of the stylus can be adjusted to be more like e.g. a pencil or a brush.
.PP
The pressure curve is a cubic Bezier curve, drawn within a normalized range
of 0.0 to 1.0 between the four points provided. This normalized range is
applied to the tablet's pressure input so that the highest pressure maps to
1.0. The points must have increasing x coordinates, if x0 is larger than 0.0
all pressure values lower than x0 are equivalent to y0. If x3 is less than
1.0, all pressure values higher than x3 are equivalent to y3.
The input for a linear curve (default) is "0.0/0.0 0.0/0.0 1.0/1.0 1.0/1.0";
a slightly
depressed curve (firmer) might be "0.0/0.0 0.05/0.0 1.0/0.95 1.0/1.0"; a slightly raised
curve (softer) might be "0.0/0.0 0.0/0.05 0.95/1.0 1.0/1.0".
.TP
This feature is provided by this driver, not by libinput.
.SH TABLET TOOL AREA RATIO
By default, a tablet tool can access the whole sensor area and the tablet
area is mapped to the available screen area. For external tablets like
the Wacom Intuos series, the height:width ratio of the tablet may be
different to that of the monitor, causing the skew of input data.
.PP
To avoid this skew of input data, an area ratio may be set to match the
ratio of the screen device. For example, a ratio of 4:3 will reduce the
available area of the tablet to the largest available area with a ratio of
4:3. Events within this area will scale to the tablet's announced axis
range, the area ratio is thus transparent to the X server. Any events
outside this area will send events equal to the maximum value of that axis.
The area always starts at the device's origin in it's current rotation, i.e.
it takes left-handed-ness into account.
.TP
This feature is provided by this driver, not by libinput.
.SH BUGS
This driver does not work with \fBOption \*qDevice\*q\fR set to an event
node in \fI/dev/input/by-id\fR and \fI/dev/input/by-path\fR. This can be
usually be worked by using \fBSection \*qInputClass\*q\fR with an
appropriate \fBMatch*\fR statement in the __xconfigfile__(__filemansuffix__).
.SH AUTHORS
Peter Hutterer
.SH "SEE ALSO"

View File

@@ -30,10 +30,11 @@ AM_CPPFLAGS =-I$(top_srcdir)/include $(LIBINPUT_CFLAGS)
@DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la
@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
@DRIVER_NAME@_drv_la_LIBADD = $(LIBINPUT_LIBS) libdraglock.la
@DRIVER_NAME@_drv_la_LIBADD = $(LIBINPUT_LIBS) libdraglock.la libbezier.la -lm
@DRIVER_NAME@_drv_ladir = @inputdir@
@DRIVER_NAME@_drv_la_SOURCES = xf86libinput.c
noinst_LTLIBRARIES = libdraglock.la
noinst_LTLIBRARIES = libdraglock.la libbezier.la
libdraglock_la_SOURCES = draglock.c draglock.h
libbezier_la_SOURCES = bezier.c bezier.h

177
src/bezier.c Normal file
View File

@@ -0,0 +1,177 @@
/*
* Copyright © 2016 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 Red Hat
* not be used in advertising or publicity pertaining to distribution
* of the software without specific, written prior permission. Red
* Hat makes no representations about the suitability of this software
* for any purpose. It is provided "as is" without express or implied
* warranty.
*
* THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL THE AUTHORS 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include "bezier.h"
const struct bezier_control_point bezier_defaults[4] = {
{ 0.0, 0.0 },
{ 0.0, 0.0 },
{ 1.0, 1.0 },
{ 1.0, 1.0 },
};
struct point {
int x, y;
};
/**
* de Casteljau's algorithm. See this page here
* https://pomax.github.io/bezierinfo/#extended
*
* To play with bezier curve shapes, I used
* http://cubic-bezier.com/
*/
static struct point
decasteljau(const struct point *controls,
size_t ncontrols,
double t)
{
struct point new_controls[ncontrols];
if (ncontrols == 1)
return controls[0];
for (int i = 0; i < ncontrols - 1; i++) {
new_controls[i].x = (1.0 - t) * controls[i].x + t * controls[i + 1].x;
new_controls[i].y = (1.0 - t) * controls[i].y + t * controls[i + 1].y;
}
return decasteljau(new_controls, ncontrols - 1, t);
}
/**
* Given a Bézier curve defined by the control points, reduce the curve to
* one with ncurve_points.
*/
static void
flatten_curve(const struct point *controls,
size_t ncontrols,
struct point *curve,
size_t ncurve_points)
{
ncurve_points--; /* make sure we end up with 100/100 as last point */
for (int i = 0; i <= ncurve_points; i++) {
double t = 1.0 * i/ncurve_points;
struct point p;
p = decasteljau(controls, ncontrols, t);
curve[i] = p;
}
}
/**
* Calculate line through a and b, set curve[x] for each x between
* [a.x, b.x].
*
* Note: pcurve must be at least b.x size.
*/
static void
line_between(struct point a, struct point b,
struct point *curve, size_t curve_sz)
{
double slope;
double offset;
assert(b.x < curve_sz);
if (a.x == b.x) {
curve[a.x].x = a.x;
curve[a.x].y = a.y;
return;
}
slope = (double)(b.y - a.y)/(b.x - a.x);
offset = a.y - slope * a.x;
for (int x = a.x; x <= b.x; x++) {
struct point p;
p.x = x;
p.y = slope * x + offset;
curve[x] = p;
}
}
bool
cubic_bezier(const struct bezier_control_point controls[4],
int *bezier_out,
size_t bezier_sz)
{
const int nsegments = 50;
const int range = bezier_sz - 1;
struct point curve[nsegments];
struct point bezier[bezier_sz];
struct point zero = { 0, 0 },
max = { range, range};
/* Scale control points into the [0, bezier_sz) range */
struct point ctrls[4];
for (int i = 0; i < 4; i++) {
if (controls[i].x < 0.0 || controls[i].x > 1.0 ||
controls[i].y < 0.0 || controls[i].y > 1.0)
return false;
ctrls[i].x = controls[i].x * range;
ctrls[i].y = controls[i].y * range;
}
for (int i = 0; i < 3; i++) {
if (ctrls[i].x > ctrls[i+1].x)
return false;
}
/* Reduce curve to nsegments, because this isn't a drawing program */
flatten_curve(ctrls, 4, curve, nsegments);
/* we now have nsegments points in curve that represent the bezier
curve (already in the [0, bezier_sz) range). Run through the
points and draw a straight line between each point and voila, we
have our curve.
If the first control points (x0/y0) is not at x == 0 or the last
control point (x3/y3) is not at the max value, draw a line
between from 0/0 to x0/y0 and from x3/y3 to xmax/y3.
*/
line_between(zero, curve[0], bezier, bezier_sz);
for (int i = 0; i < nsegments - 1; i++)
line_between(curve[i], curve[i+1], bezier, bezier_sz);
if (curve[nsegments - 1].x < max.x)
line_between(curve[nsegments - 1], max, bezier, bezier_sz);
for (int i = 0; i < bezier_sz; i++)
bezier_out[i] = bezier[i].y;
return true;
}

69
src/bezier.h Normal file
View File

@@ -0,0 +1,69 @@
/*
* Copyright © 2016 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 Red Hat
* not be used in advertising or publicity pertaining to distribution
* of the software without specific, written prior permission. Red
* Hat makes no representations about the suitability of this software
* for any purpose. It is provided "as is" without express or implied
* warranty.
*
* THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL THE AUTHORS 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef BEZIER_H
#define BEZIER_H
#include <stdlib.h>
#include <stdbool.h>
struct bezier_control_point {
double x, y;
};
extern const struct bezier_control_point bezier_defaults[4];
/**
* Given four control points in the range [(0.0/0.0), (1.0/1.0)]
* construct a Bézier curve.
*
* ^
*1.0 | c2 ______ c3
* | _/
* | /
* |c1 /
* | /
* | /
* |/_________________>
* c0 1.0
*
* This function requires that c[i].x <= c[i+1].x
*
* The curve is mapped into a canvas size [0, bezier_sz)². For each x
* coordiante in [0, bezier_sz), the matching y coordinate is thus
* bezier[x].
*
* In other words, if you have a range [0,2048) input possible values,
* the output is a list of 2048 points in a [0, 2048) range.
*
* @return true on success, false otherwise
*/
bool
cubic_bezier(const struct bezier_control_point controls[4],
int *bezier,
size_t bezier_sz);
#endif

View File

@@ -116,7 +116,7 @@ draglock_get_meta(const struct draglock *dl)
}
size_t
draglock_get_pairs(const struct draglock *dl, int *array, size_t sz)
draglock_get_pairs(const struct draglock *dl, int *array, size_t nelem)
{
unsigned int i;
size_t last = 0;
@@ -131,8 +131,8 @@ draglock_get_pairs(const struct draglock *dl, int *array, size_t sz)
}
/* size N array with a[0] == 0, the rest ordered by button number */
memset(array, 0, sz * sizeof(array[0]));
for (i = 0; i < sz && i < ARRAY_SIZE(dl->lock_pair); i++) {
memset(array, 0, nelem * sizeof(array[0]));
for (i = 0; i < nelem && i < ARRAY_SIZE(dl->lock_pair); i++) {
array[i] = dl->lock_pair[i];
if (array[i] != 0 && i > last)
last = i;
@@ -153,20 +153,20 @@ draglock_set_meta(struct draglock *dl, int meta_button)
}
int
draglock_set_pairs(struct draglock *dl, const int *array, size_t sz)
draglock_set_pairs(struct draglock *dl, const int *array, size_t nelem)
{
unsigned int i;
if (sz == 0 || array[0] != 0)
if (nelem == 0 || array[0] != 0)
return 1;
for (i = 0; i < sz; i++) {
for (i = 0; i < nelem; i++) {
if (array[i] < 0 || array[i] >= DRAGLOCK_MAX_BUTTONS)
return 1;
}
dl->mode = DRAGLOCK_DISABLED;
for (i = 0; i < sz; i++) {
for (i = 0; i < nelem; i++) {
dl->lock_pair[i] = array[i];
if (dl->lock_pair[i])
dl->mode = DRAGLOCK_PAIRS;

View File

@@ -107,13 +107,13 @@ draglock_get_meta(const struct draglock *dl);
* @note Button numbers start at 1, array[0] is always 0.
*
* @param[in|out] array Caller-allocated array to hold the button mappings.
* @param[in] sz Maximum number of elements in array
* @param[in] nelem Maximum number of elements in array
*
* @return The number of valid elements in array or 0 if the current mode is
* not DRAGLOCK_PAIRS
*/
size_t
draglock_get_pairs(const struct draglock *dl, int *array, size_t sz);
draglock_get_pairs(const struct draglock *dl, int *array, size_t nelem);
/**
* Set the drag lock config to the DRAGLOCK_META mode, with the given
@@ -140,7 +140,7 @@ draglock_set_meta(struct draglock *dl, int meta_button);
* @return 0 on successor nonzero otherwise
*/
int
draglock_set_pairs(struct draglock *dl, const int *array, size_t sz);
draglock_set_pairs(struct draglock *dl, const int *array, size_t nelem);
/**
* Process the given button event through the drag lock state machine.

File diff suppressed because it is too large Load Diff

View File

@@ -3,11 +3,14 @@ AM_CPPFLAGS = $(XORG_CFLAGS) \
-I$(top_srcdir)/include \
-I$(top_srcdir)/src
tests = test-draglock
tests = test-draglock test-bezier
noinst_PROGRAMS = $(tests)
test_draglock_SOURCES = test-draglock.c
test_draglock_LDADD = ../src/libdraglock.la
test_bezier_SOURCES = test-bezier.c
test_bezier_LDADD = ../src/libbezier.la -lm
TESTS = $(tests)

206
test/test-bezier.c Normal file
View File

@@ -0,0 +1,206 @@
/*
* Copyright © 2016 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 Red Hat
* not be used in advertising or publicity pertaining to distribution
* of the software without specific, written prior permission. Red
* Hat makes no representations about the suitability of this software
* for any purpose. It is provided "as is" without express or implied
* warranty.
*
* THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "bezier.h"
#include <assert.h>
#include <string.h>
#include <stdio.h>
static inline void
print_curve(int *bezier, size_t size)
{
/* look at it with gnuplot, "plot 'output-file.txt'" */
for (int i = 0; i < size; i++)
printf("%d %d\n", i, bezier[i]);
}
static void
test_linear(void)
{
const int size = 2048;
int bezier[size];
struct bezier_control_point controls[] = {
{ 0.0, 0.0 },
{ 0.0, 0.0 },
{ 1.0, 1.0 },
{ 1.0, 1.0 }
};
cubic_bezier(controls, bezier, size);
assert(bezier[0] == 0);
assert(bezier[size - 1] == size - 1);
for (int x = 1; x < size; x++)
assert(bezier[x] == x);
}
/* Center point pulled down towards X axis */
static void
test_flattened(void)
{
const int size = 2048;
int bezier[size];
struct bezier_control_point controls[] = {
{ 0.0, 0.0 },
{ 0.1, 0.0 },
{ 1.0, 0.9 },
{ 1.0, 1.0 }
};
cubic_bezier(controls, bezier, size);
assert(bezier[0] == 0);
assert(bezier[size - 1] == size - 1);
for (int x = 1; x < size - 1; x++) {
assert(bezier[x] < x);
}
}
/* Center point pulled up from X axis */
static void
test_raised(void)
{
const int size = 2048;
int bezier[size];
struct bezier_control_point controls[] = {
{ 0.0, 0.0 },
{ 0.1, 0.4 },
{ 0.4, 1.0 },
{ 1.0, 1.0 }
};
cubic_bezier(controls, bezier, size);
assert(bezier[0] == 0);
assert(bezier[size - 1] == size - 1);
for (int x = 1; x < size; x++)
assert(bezier[x] >= x);
for (int x = 10; x < size - 10; x++)
assert(bezier[x] > x);
}
static void
test_windy(void)
{
const int size = 2048;
int bezier[size];
struct bezier_control_point controls[] = {
{ 0.0, 0.0 },
{ 0.0, 0.3 },
{ 1.0, 0.7 },
{ 1.0, 1.0 }
};
cubic_bezier(controls, bezier, size);
assert(bezier[0] == 0);
assert(bezier[size - 1] == size - 1);
for (int x = 1; x < size/2 - 20; x++)
assert(bezier[x] > x);
for (int x = size/2 + 20; x < size - 1; x++)
assert(bezier[x] < x);
}
static void
test_nonzero_x_linear(void)
{
const int size = 2048;
int bezier[size];
int x;
struct bezier_control_point controls[] = {
{ 0.2, 0.0 },
{ 0.2, 0.0 },
{ 0.8, 1.0 },
{ 0.8, 1.0 }
};
cubic_bezier(controls, bezier, size);
x = 0;
do {
assert(bezier[x] == 0);
} while (++x < size * 0.2 - 1);
/* ppc64le, ppc64, aarch64 have different math results at -O2,
resulting in one extra zero at the beginning of the array.
some other numbers are different too but within the error
margin (#99992) */
if (bezier[x] == 0)
x++;
do {
assert(bezier[x] > bezier[x-1]);
} while (++x < size * 0.8 - 1);
do {
assert(bezier[x] == size - 1);
} while (++x < size);
}
static void
test_nonzero_y_linear(void)
{
const int size = 2048;
int bezier[size];
struct bezier_control_point controls[] = {
{ 0.0, 0.2 },
{ 0.0, 0.2 },
{ 1.0, 0.8 },
{ 1.0, 0.8 }
};
cubic_bezier(controls, bezier, size);
assert(bezier[0] == (int)(size * 0.2));
for (int x = 1; x < size; x++) {
assert(bezier[x - 1] <= bezier[x]);
assert(bezier[x] >= (int)(size * 0.2));
}
}
int
main(int argc, char **argv)
{
test_linear();
test_flattened();
test_raised();
test_windy();
test_nonzero_x_linear();
test_nonzero_y_linear();
return 0;
}