commit xf86-input-libinput for openSUSE:Factory
Hello community, here is the log from the commit of package xf86-input-libinput for openSUSE:Factory checked in at 2017-02-26 17:01:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/xf86-input-libinput (Old) and /work/SRC/openSUSE:Factory/.xf86-input-libinput.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "xf86-input-libinput" Changes: -------- --- /work/SRC/openSUSE:Factory/xf86-input-libinput/xf86-input-libinput.changes 2016-12-14 10:48:40.679541443 +0100 +++ /work/SRC/openSUSE:Factory/.xf86-input-libinput.new/xf86-input-libinput.changes 2017-02-26 17:01:15.816643477 +0100 @@ -1,0 +2,12 @@ +Mon Feb 20 21:37:53 UTC 2017 - zaitor@opensuse.org + +- Update to version 0.24.0: + + Tablets now support a configurable pressure curve. + + Tablets now have a 'area ratio' setting to be able to match the + tablet aspect ratio with that of the screen. + + The mouse wheel's click angle now (correctly) affects how fast + the scroll wheel triggers. In particular, if you have a wheel + with a very small click angle, it won't trigger for every click + anymore. + +------------------------------------------------------------------- Old: ---- xf86-input-libinput-0.23.0.tar.bz2 xf86-input-libinput-0.23.0.tar.bz2.sig New: ---- xf86-input-libinput-0.24.0.tar.bz2 xf86-input-libinput-0.24.0.tar.bz2.sig ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ xf86-input-libinput.spec ++++++ --- /var/tmp/diff_new_pack.tgzsF2/_old 2017-02-26 17:01:16.204584633 +0100 +++ /var/tmp/diff_new_pack.tgzsF2/_new 2017-02-26 17:01:16.204584633 +0100 @@ -1,7 +1,7 @@ # # spec file for package xf86-input-libinput # -# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: xf86-input-libinput -Version: 0.23.0 +Version: 0.24.0 Release: 0 Summary: Libinput driver for the Xorg X server License: MIT ++++++ xf86-input-libinput-0.23.0.tar.bz2 -> xf86-input-libinput-0.24.0.tar.bz2 ++++++ ++++ 1677 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/xf86-input-libinput-0.23.0/ChangeLog new/xf86-input-libinput-0.24.0/ChangeLog --- old/xf86-input-libinput-0.23.0/ChangeLog 2016-12-12 06:00:47.000000000 +0100 +++ new/xf86-input-libinput-0.24.0/ChangeLog 2017-02-09 07:17:09.000000000 +0100 @@ -1,3 +1,156 @@ +commit 2eb5a2f0c08747df44eba6faff95cc9ce24b78ed +Author: Peter Hutterer <peter.hutterer@who-t.net> +Date: Thu Feb 9 16:16:34 2017 +1000 + + xf86-input-libinput 0.24.0 + + Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> + +commit 19ceef972e76bc491438198659748786d9457668 +Author: Peter Hutterer <peter.hutterer@who-t.net> +Date: Fri Jan 27 10:24:08 2017 +1000 + + Drop unnecessary function declaration + + Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> + +commit 07f30ea049303739bf6006d23ac924971a19d778 +Author: Mihail Konev <k.mvc@ya.ru> +Date: Thu Jan 26 14:00:21 2017 +1000 + + autogen: add default patch prefix + + Signed-off-by: Mihail Konev <k.mvc@ya.ru> + +commit 6187ed0450e68aaf727779ad61b50b0b70a1122e +Author: Emil Velikov <emil.l.velikov@gmail.com> +Date: Mon Mar 9 12:00:52 2015 +0000 + + 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> + +commit 974ab6b62bd2af97e1556314df28fe9f3b816e54 +Author: Peter Hutterer <peter.hutterer@who-t.net> +Date: Fri Oct 28 11:20:22 2016 +1000 + + 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> + +commit 5d0470738125243c98f7a8cc40d62f53604a8051 +Author: Peter Hutterer <peter.hutterer@who-t.net> +Date: Mon Oct 24 14:41:51 2016 +1000 + + 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> + +commit f65a5c50224efc34414f44c86700e15392b7039b +Author: Peter Hutterer <peter.hutterer@who-t.net> +Date: Wed Oct 26 11:57:49 2016 +1000 + + Add a bezier curve implementation + + Needed for the wacom stylus pressure curve + + Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> + +commit 0dad7408fac3b69c4b6ab7705f39f790d7ba20c2 +Author: Peter Hutterer <peter.hutterer@who-t.net> +Date: Mon Nov 28 14:09:06 2016 +1000 + + 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> + +commit ea02578a4e888d9908eb6bed6dcb858f78acb8bb +Author: Peter Hutterer <peter.hutterer@who-t.net> +Date: Tue Nov 29 08:31:32 2016 +1000 + + 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> + +commit 2ceb2e1b18b6f971706230d16a2a5665d87aabd4 +Author: Peter Hutterer <peter.hutterer@who-t.net> +Date: Tue Nov 29 09:21:24 2016 +1000 + + 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> + +commit f47f78eb0bd9fba455f01c8c6dead3bd75242b2b +Author: Peter Hutterer <peter.hutterer@who-t.net> +Date: Tue Dec 20 15:36:55 2016 +1000 + + 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> + commit 1c3ce3ce3c315213511735db1b0fdd74ca8442d0 Author: Peter Hutterer <peter.hutterer@who-t.net> Date: Mon Dec 12 14:54:00 2016 +1000 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/xf86-input-libinput-0.23.0/configure.ac new/xf86-input-libinput-0.24.0/configure.ac --- old/xf86-input-libinput-0.23.0/configure.ac 2016-12-12 05:53:55.000000000 +0100 +++ new/xf86-input-libinput-0.24.0/configure.ac 2017-02-09 07:17:00.000000000 +0100 @@ -23,7 +23,7 @@ # Initialize Autoconf AC_PREREQ([2.60]) AC_INIT([xf86-input-libinput], - [0.23.0], + [0.24.0], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [xf86-input-libinput]) AC_CONFIG_SRCDIR([Makefile.am]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/xf86-input-libinput-0.23.0/include/libinput-properties.h new/xf86-input-libinput-0.24.0/include/libinput-properties.h --- old/xf86-input-libinput-0.23.0/include/libinput-properties.h 2016-11-28 04:25:03.000000000 +0100 +++ new/xf86-input-libinput-0.24.0/include/libinput-properties.h 2017-02-09 07:17:00.000000000 +0100 @@ -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_ */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/xf86-input-libinput-0.23.0/man/libinput.man new/xf86-input-libinput-0.24.0/man/libinput.man --- old/xf86-input-libinput-0.23.0/man/libinput.man 2016-11-28 04:25:03.000000000 +0100 +++ new/xf86-input-libinput-0.24.0/man/libinput.man 2017-02-09 07:17:00.000000000 +0100 @@ -155,6 +155,20 @@ 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 @@ -252,6 +266,16 @@ "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 +.TP7 +.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 +337,42 @@ .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 AUTHORS Peter Hutterer .SH "SEE ALSO" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/xf86-input-libinput-0.23.0/src/Makefile.am new/xf86-input-libinput-0.24.0/src/Makefile.am --- old/xf86-input-libinput-0.23.0/src/Makefile.am 2016-11-14 04:27:06.000000000 +0100 +++ new/xf86-input-libinput-0.24.0/src/Makefile.am 2017-02-09 07:17:00.000000000 +0100 @@ -30,10 +30,11 @@ @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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/xf86-input-libinput-0.23.0/src/bezier.c new/xf86-input-libinput-0.24.0/src/bezier.c --- old/xf86-input-libinput-0.23.0/src/bezier.c 1970-01-01 01:00:00.000000000 +0100 +++ new/xf86-input-libinput-0.24.0/src/bezier.c 2017-02-09 07:17:00.000000000 +0100 @@ -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; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/xf86-input-libinput-0.23.0/src/bezier.h new/xf86-input-libinput-0.24.0/src/bezier.h --- old/xf86-input-libinput-0.23.0/src/bezier.h 1970-01-01 01:00:00.000000000 +0100 +++ new/xf86-input-libinput-0.24.0/src/bezier.h 2017-02-09 07:17:00.000000000 +0100 @@ -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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/xf86-input-libinput-0.23.0/src/xf86libinput.c new/xf86-input-libinput-0.24.0/src/xf86libinput.c --- old/xf86-input-libinput-0.23.0/src/xf86libinput.c 2016-12-05 05:26:14.000000000 +0100 +++ new/xf86-input-libinput-0.24.0/src/xf86libinput.c 2017-02-09 07:17:00.000000000 +0100 @@ -42,6 +42,7 @@ #include <X11/Xatom.h> +#include "bezier.h" #include "draglock.h" #include "libinput-properties.h" @@ -126,6 +127,9 @@ struct { int vdist; int hdist; + + double vdist_fraction; + double hdist_fraction; } scroll; struct { @@ -162,6 +166,10 @@ BOOL horiz_scrolling_enabled; float rotation_angle; + struct bezier_control_point pressurecurve[4]; + struct ratio { + int x, y; + } area; } options; struct draglock draglock; @@ -172,6 +180,17 @@ struct libinput_tablet_tool *tablet_tool; bool allow_mode_group_updates; + + /* Pre-calculated pressure curve. + In the 0...TABLET_AXIS_MAX range */ + struct { + int *values; + size_t sz; + } pressurecurve; + + struct scale_factor { + double x, y; + } area_scale_factor; }; enum event_handling { @@ -382,6 +401,59 @@ return shared_device->enabled_count > 0; } +static inline bool +xf86libinput_set_pressurecurve(struct xf86libinput *driver_data, + const struct bezier_control_point controls[4]) +{ + if (memcmp(controls, bezier_defaults, sizeof(bezier_defaults)) == 0) { + free(driver_data->pressurecurve.values); + driver_data->pressurecurve.values = NULL; + return true; + } + + if (!driver_data->pressurecurve.values) { + int *vals = calloc(TABLET_PRESSURE_AXIS_MAX + 1, sizeof(int)); + if (!vals) + return false; + + driver_data->pressurecurve.values = vals; + driver_data->pressurecurve.sz = TABLET_PRESSURE_AXIS_MAX + 1; + } + + return cubic_bezier(controls, + driver_data->pressurecurve.values, + driver_data->pressurecurve.sz); +} + +static inline void +xf86libinput_set_area_ratio(struct xf86libinput *driver_data, + const struct ratio *ratio) +{ + double f; + double w, h; + + if (libinput_device_get_size(driver_data->shared_device->device, &w, &h) != 0) + return; + + driver_data->options.area = *ratio; + + if (ratio->y == 0) { + driver_data->area_scale_factor.x = 1.0; + driver_data->area_scale_factor.y = 1.0; + return; + } + + f = 1.0 * (ratio->x * h)/(ratio->y * w); + + if (f <= 1.0) { + driver_data->area_scale_factor.x = 1.0/f; + driver_data->area_scale_factor.y = 1.0; + } else { + driver_data->area_scale_factor.x = 1.0; + driver_data->area_scale_factor.y = f; + } +} + static int LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, BOOL checkonly); @@ -785,6 +857,9 @@ struct xf86libinput *driver_data = pInfo->private; struct libinput_device *ldevice = driver_data->shared_device->device; + if (!device->enabled) + return; + while (bits[i].xbit) { if (ctrl->leds & bits[i].xbit) leds |= bits[i].code; @@ -1320,6 +1395,92 @@ xf86PostKeyboardEvent(dev, key, is_press); } +/* + * The scroll fraction is the value we divide the scroll dist with to + * accommodate for wheels with a small click angle. On these devices, + * multiple clicks of small angle accumulate to the XI 2.1 scroll distance. + * This gives us smooth scrolling on those wheels for small movements, the + * legacy button events are generated whenever the full distance is reached. + * e.g. a 2 degree click angle requires 8 clicks before a legacy event is + * sent, but each of those clicks will send XI2.1 smooth scroll data for + * compatible clients. + */ +static inline double +get_scroll_fraction(struct xf86libinput *driver_data, + struct libinput_event_pointer *event, + enum libinput_pointer_axis axis) +{ + double *fraction; + double f; + double angle; + int discrete; + + switch (axis) { + case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: + fraction = &driver_data->scroll.hdist_fraction; + break; + case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: + fraction = &driver_data->scroll.vdist_fraction; + break; + default: + return 0.0; + } + + if (*fraction != 0.0) + return *fraction; + + /* Calculate the angle per single scroll event */ + angle = libinput_event_pointer_get_axis_value(event, axis); + discrete = libinput_event_pointer_get_axis_value_discrete(event, axis); + angle /= discrete; + + /* We only do magic for click angles smaller than 10 degrees */ + if (angle >= 10) { + *fraction = 1.0; + return 1.0; + } + + /* Figure out something that gets close to 15 degrees (the general + * wheel default) with a number of clicks. This formula gives us + * between 12 and and 20 degrees for the range of 1-10. See + * https://bugs.freedesktop.org/attachment.cgi?id=128256 for a + * graph. + */ + f = round(15.0/angle); + + *fraction = f; + + return f; +} + +static inline bool +calculate_axis_value(struct xf86libinput *driver_data, + enum libinput_pointer_axis axis, + struct libinput_event_pointer *event, + double *value_out) +{ + enum libinput_pointer_axis_source source; + double value; + + if (!libinput_event_pointer_has_axis(event, axis)) + return false; + + source = libinput_event_pointer_get_axis_source(event); + if (source == LIBINPUT_POINTER_AXIS_SOURCE_WHEEL) { + double scroll_fraction; + + value = libinput_event_pointer_get_axis_value_discrete(event, axis); + scroll_fraction = get_scroll_fraction(driver_data, event, axis); + value *= driver_data->scroll.vdist/scroll_fraction; + } else { + value = libinput_event_pointer_get_axis_value(event, axis); + } + + *value_out = value; + + return true; +} + static void xf86libinput_handle_axis(InputInfoPtr pInfo, struct libinput_event_pointer *event) { @@ -1327,7 +1488,6 @@ struct xf86libinput *driver_data = pInfo->private; ValuatorMask *mask = driver_data->valuators; double value; - enum libinput_pointer_axis axis; enum libinput_pointer_axis_source source; if ((driver_data->capabilities & CAP_POINTER) == 0) @@ -1345,30 +1505,20 @@ return; } - axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; - if (libinput_event_pointer_has_axis(event, axis)) { - if (source == LIBINPUT_POINTER_AXIS_SOURCE_WHEEL) { - value = libinput_event_pointer_get_axis_value_discrete(event, axis); - value *= driver_data->scroll.vdist; - } else { - value = libinput_event_pointer_get_axis_value(event, axis); - } + if (calculate_axis_value(driver_data, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + event, + &value)) valuator_mask_set_double(mask, 3, value); - } if (!driver_data->options.horiz_scrolling_enabled) goto out; - axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL; - if (libinput_event_pointer_has_axis(event, axis)) { - if (source == LIBINPUT_POINTER_AXIS_SOURCE_WHEEL) { - value = libinput_event_pointer_get_axis_value_discrete(event, axis); - value *= driver_data->scroll.hdist; - } else { - value = libinput_event_pointer_get_axis_value(event, axis); - } + if (calculate_axis_value(driver_data, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + event, + &value)) valuator_mask_set_double(mask, 2, value); - } out: xf86PostMotionEventM(dev, Relative, mask); @@ -1603,6 +1753,26 @@ return EVENT_HANDLED; } +static void +xf86libinput_apply_area(InputInfoPtr pInfo, double *x, double *y) +{ + struct xf86libinput *driver_data = pInfo->private; + const struct scale_factor *f = &driver_data->area_scale_factor; + double sx, sy; + + if (driver_data->options.area.x == 0) + return; + + /* In left-handed mode, libinput already gives us transformed + * coordinates, so we can clip the same way. */ + + sx = min(*x * f->x, TABLET_AXIS_MAX); + sy = min(*y * f->y, TABLET_AXIS_MAX); + + *x = sx; + *y = sy; +} + static enum event_handling xf86libinput_handle_tablet_axis(InputInfoPtr pInfo, struct libinput_event_tablet_tool *event) @@ -1612,22 +1782,25 @@ ValuatorMask *mask = driver_data->valuators; struct libinput_tablet_tool *tool; double value; + double x, y; if (xf86libinput_tool_queue_event(event)) return EVENT_QUEUED; - value = libinput_event_tablet_tool_get_x_transformed(event, - TABLET_AXIS_MAX); - valuator_mask_set_double(mask, 0, value); - value = libinput_event_tablet_tool_get_y_transformed(event, - TABLET_AXIS_MAX); - valuator_mask_set_double(mask, 1, value); + x = libinput_event_tablet_tool_get_x_transformed(event, + TABLET_AXIS_MAX); + y = libinput_event_tablet_tool_get_y_transformed(event, + TABLET_AXIS_MAX); + xf86libinput_apply_area(pInfo, &x, &y); + valuator_mask_set_double(mask, 0, x); + valuator_mask_set_double(mask, 1, y); tool = libinput_event_tablet_tool_get_tool(event); if (libinput_tablet_tool_has_pressure(tool)) { - value = libinput_event_tablet_tool_get_pressure(event); - value *= TABLET_PRESSURE_AXIS_MAX; + value = TABLET_PRESSURE_AXIS_MAX * libinput_event_tablet_tool_get_pressure(event); + if (driver_data->pressurecurve.values) + value = driver_data->pressurecurve.values[(int)value]; valuator_mask_set_double(mask, 2, value); } @@ -2060,13 +2233,7 @@ .close_restricted = close_restricted, }; -static void -xf86libinput_log_handler(struct libinput *libinput, - enum libinput_log_priority priority, - const char *format, - va_list args) - _X_ATTRIBUTE_PRINTF(3, 0); - +_X_ATTRIBUTE_PRINTF(3, 0) static void xf86libinput_log_handler(struct libinput *libinput, enum libinput_log_priority priority, @@ -2609,6 +2776,111 @@ } static void +xf86libinput_parse_pressurecurve_option(InputInfoPtr pInfo, + struct xf86libinput *driver_data, + struct bezier_control_point pcurve[4]) +{ + struct bezier_control_point controls[4] = { + { 0.0, 0.0 }, + { 0.0, 0.0 }, + { 1.0, 1.0 }, + { 1.0, 1.0 }, + }; + float points[8]; + char *str; + int rc = 0; + int test_bezier[64]; + struct libinput_tablet_tool *tool = driver_data->tablet_tool; + + if ((driver_data->capabilities & CAP_TABLET_TOOL) == 0) + return; + + if (!tool || !libinput_tablet_tool_has_pressure(tool)) + return; + + str = xf86SetStrOption(pInfo->options, + "TabletToolPressureCurve", + NULL); + if (!str) + goto out; + + rc = sscanf(str, "%f/%f %f/%f %f/%f %f/%f", + &points[0], &points[1], &points[2], &points[3], + &points[4], &points[5], &points[6], &points[7]); + if (rc != 8) + goto out; + + for (int i = 0; i < 4; i++) { + if (points[i] < 0.0 || points[i] > 1.0) + goto out; + } + + controls[0].x = points[0]; + controls[0].y = points[1]; + controls[1].x = points[2]; + controls[1].y = points[3]; + controls[2].x = points[4]; + controls[2].y = points[5]; + controls[3].x = points[6]; + controls[3].y = points[7]; + + if (!cubic_bezier(controls, test_bezier, ARRAY_SIZE(test_bezier))) { + memcpy(controls, bezier_defaults, sizeof(controls)); + goto out; + } + + rc = 0; +out: + if (rc != 0) + xf86IDrvMsg(pInfo, X_ERROR, "Invalid pressure curve: %s\n", str); + free(str); + memcpy(pcurve, controls, sizeof(controls)); + xf86libinput_set_pressurecurve(driver_data, controls); +} + +static inline bool +want_area_handling(struct xf86libinput *driver_data) +{ + struct libinput_device *device = driver_data->shared_device->device; + + if ((driver_data->capabilities & CAP_TABLET_TOOL) == 0) + return false; + + /* If we have a calibration matrix, it's a built-in tablet and we + * don't need to set the area ratio on those */ + return !libinput_device_config_calibration_has_matrix(device); +} + +static void +xf86libinput_parse_tablet_area_option(InputInfoPtr pInfo, + struct xf86libinput *driver_data, + struct ratio *area_out) +{ + char *str; + int rc; + struct ratio area; + + if (!want_area_handling(driver_data)) + return; + + str = xf86SetStrOption(pInfo->options, + "TabletToolAreaRatio", + NULL); + if (!str || strcmp(str, "default") == 0) + goto out; + + rc = sscanf(str, "%d:%d", &area.x, &area.y); + if (rc != 2 || area.x <= 0 || area.y <= 0) { + xf86IDrvMsg(pInfo, X_ERROR, "Invalid tablet tool area ratio: %s\n", str); + } else { + *area_out = area; + } + +out: + free(str); +} + +static void xf86libinput_parse_options(InputInfoPtr pInfo, struct xf86libinput *driver_data, struct libinput_device *device) @@ -2641,6 +2913,13 @@ xf86libinput_parse_draglock_option(pInfo, driver_data); options->horiz_scrolling_enabled = xf86libinput_parse_horiz_scroll_option(pInfo); } + + xf86libinput_parse_pressurecurve_option(pInfo, + driver_data, + options->pressurecurve); + xf86libinput_parse_tablet_area_option(pInfo, + driver_data, + &options->area); } static const char* @@ -2928,13 +3207,19 @@ pInfo->private = driver_data; driver_data->pInfo = pInfo; - driver_data->scroll.vdist = 15; - driver_data->scroll.hdist = 15; driver_data->path = path; driver_data->shared_device = shared_device; xorg_list_append(&driver_data->shared_device_link, &shared_device->device_list); + /* Scroll dist value matters for source finger/continuous. For those + * devices libinput provides pixel-like data, changing this will + * affect touchpad scroll speed. For wheels it doesn't matter as + * we're using the discrete value only. + */ + driver_data->scroll.vdist = 15; + driver_data->scroll.hdist = 15; + if (!is_subdevice) { if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER)) driver_data->capabilities |= CAP_POINTER; @@ -3093,6 +3378,8 @@ /* driver properties */ static Atom prop_draglock; static Atom prop_horiz_scroll; +static Atom prop_pressurecurve; +static Atom prop_area_ratio; /* general properties */ static Atom prop_float; @@ -3843,6 +4130,108 @@ return Success; } +static inline int +LibinputSetPropertyPressureCurve(DeviceIntPtr dev, + Atom atom, + XIPropertyValuePtr val, + BOOL checkonly) +{ + InputInfoPtr pInfo = dev->public.devicePrivate; + struct xf86libinput *driver_data = pInfo->private; + float *vals; + struct bezier_control_point controls[4]; + + if (val->format != 32 || val->size != 8 || val->type != prop_float) + return BadMatch; + + vals = val->data; + controls[0].x = vals[0]; + controls[0].y = vals[1]; + controls[1].x = vals[2]; + controls[1].y = vals[3]; + controls[2].x = vals[4]; + controls[2].y = vals[5]; + controls[3].x = vals[6]; + controls[3].y = vals[7]; + + if (checkonly) { + int test_bezier[64]; + + for (int i = 0; i < val->size; i++) { + if (vals[i] < 0.0 || vals[i] > 1.0) + return BadValue; + } + + if (!xf86libinput_check_device (dev, atom)) + return BadMatch; + + if (!cubic_bezier(controls, test_bezier, ARRAY_SIZE(test_bezier))) + return BadValue; + } else { + xf86libinput_set_pressurecurve(driver_data, controls); + memcpy(driver_data->options.pressurecurve, controls, + sizeof(controls)); + } + + return Success; +} + +static inline int +LibinputSetPropertyAreaRatio(DeviceIntPtr dev, + Atom atom, + XIPropertyValuePtr val, + BOOL checkonly) +{ + InputInfoPtr pInfo = dev->public.devicePrivate; + struct xf86libinput *driver_data = pInfo->private; + uint32_t *vals; + struct ratio area = { 0, 0 }; + + if (val->format != 32 || val->size != 2 || val->type != XA_CARDINAL) + return BadMatch; + + vals = val->data; + area.x = vals[0]; + area.y = vals[1]; + + if (checkonly) { + if (area.x < 0 || area.y < 0) + return BadValue; + + if ((area.x != 0 && area.y == 0) || + (area.x == 0 && area.y != 0)) + return BadValue; + + if (!xf86libinput_check_device (dev, atom)) + return BadMatch; + } else { + struct xf86libinput *other; + + xf86libinput_set_area_ratio(driver_data, &area); + + xorg_list_for_each_entry(other, + &driver_data->shared_device->device_list, + shared_device_link) { + DeviceIntPtr other_device = other->pInfo->dev; + + if (other->options.area.x == area.x && + other->options.area.y == area.y) + continue; + + XIChangeDeviceProperty(other_device, + atom, + val->type, + val->format, + PropModeReplace, + val->size, + val->data, + TRUE); + } + } + + return Success; +} + static int LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, BOOL checkonly) @@ -3895,6 +4284,10 @@ } else if (atom == prop_rotation_angle) rc = LibinputSetPropertyRotationAngle(dev, atom, val, checkonly); + else if (atom == prop_pressurecurve) + rc = LibinputSetPropertyPressureCurve(dev, atom, val, checkonly); + else if (atom == prop_area_ratio) + rc = LibinputSetPropertyAreaRatio(dev, atom, val, checkonly); else if (atom == prop_device || atom == prop_product_id || atom == prop_tap_default || atom == prop_tap_drag_default || @@ -4720,6 +5113,54 @@ } static void +LibinputInitPressureCurveProperty(DeviceIntPtr dev, + struct xf86libinput *driver_data) +{ + const struct bezier_control_point *curve = driver_data->options.pressurecurve; + struct libinput_tablet_tool *tool = driver_data->tablet_tool; + float data[8]; + + if ((driver_data->capabilities & CAP_TABLET_TOOL) == 0) + return; + + if (!tool || !libinput_tablet_tool_has_pressure(tool)) + return; + + data[0] = curve[0].x; + data[1] = curve[0].y; + data[2] = curve[1].x; + data[3] = curve[1].y; + data[4] = curve[2].x; + data[5] = curve[2].y; + data[6] = curve[3].x; + data[7] = curve[3].y; + + prop_pressurecurve = LibinputMakeProperty(dev, + LIBINPUT_PROP_TABLET_TOOL_PRESSURECURVE, + prop_float, 32, + 8, data); +} + +static void +LibinputInitTabletAreaRatioProperty(DeviceIntPtr dev, + struct xf86libinput *driver_data) +{ + const struct ratio *ratio = &driver_data->options.area; + uint32_t data[2]; + + if (!want_area_handling(driver_data)) + return; + + data[0] = ratio->x; + data[1] = ratio->y; + + prop_area_ratio = LibinputMakeProperty(dev, + LIBINPUT_PROP_TABLET_TOOL_AREA_RATIO, + XA_CARDINAL, 32, + 2, data); +} + +static void LibinputInitProperty(DeviceIntPtr dev) { InputInfoPtr pInfo = dev->public.devicePrivate; @@ -4775,4 +5216,6 @@ LibinputInitDragLockProperty(dev, driver_data); LibinputInitHorizScrollProperty(dev, driver_data); + LibinputInitPressureCurveProperty(dev, driver_data); + LibinputInitTabletAreaRatioProperty(dev, driver_data); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/xf86-input-libinput-0.23.0/test/Makefile.am new/xf86-input-libinput-0.24.0/test/Makefile.am --- old/xf86-input-libinput-0.23.0/test/Makefile.am 2016-11-14 04:27:06.000000000 +0100 +++ new/xf86-input-libinput-0.24.0/test/Makefile.am 2017-02-09 07:17:00.000000000 +0100 @@ -3,11 +3,14 @@ -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) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/xf86-input-libinput-0.23.0/test/test-bezier.c new/xf86-input-libinput-0.24.0/test/test-bezier.c --- old/xf86-input-libinput-0.23.0/test/test-bezier.c 1970-01-01 01:00:00.000000000 +0100 +++ new/xf86-input-libinput-0.24.0/test/test-bezier.c 2017-02-09 07:17:00.000000000 +0100 @@ -0,0 +1,199 @@ +/* + * 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); + + 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; +}
participants (1)
-
root@hilbertn.suse.de