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 - [email protected]
+
+- 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 <[email protected]>
+Date:   Thu Feb 9 16:16:34 2017 +1000
+
+    xf86-input-libinput 0.24.0
+    
+    Signed-off-by: Peter Hutterer <[email protected]>
+
+commit 19ceef972e76bc491438198659748786d9457668
+Author: Peter Hutterer <[email protected]>
+Date:   Fri Jan 27 10:24:08 2017 +1000
+
+    Drop unnecessary function declaration
+    
+    Signed-off-by: Peter Hutterer <[email protected]>
+
+commit 07f30ea049303739bf6006d23ac924971a19d778
+Author: Mihail Konev <[email protected]>
+Date:   Thu Jan 26 14:00:21 2017 +1000
+
+    autogen: add default patch prefix
+    
+    Signed-off-by: Mihail Konev <[email protected]>
+
+commit 6187ed0450e68aaf727779ad61b50b0b70a1122e
+Author: Emil Velikov <[email protected]>
+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 <[email protected]>
+    Reviewed-by: Peter Hutterer <[email protected]>
+    Signed-off-by: Peter Hutterer <[email protected]>
+
+commit 974ab6b62bd2af97e1556314df28fe9f3b816e54
+Author: Peter Hutterer <[email protected]>
+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 <[email protected]>
+    Reviewed-by: Jason Gerecke <[email protected]>
+
+commit 5d0470738125243c98f7a8cc40d62f53604a8051
+Author: Peter Hutterer <[email protected]>
+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 <[email protected]>
+
+commit f65a5c50224efc34414f44c86700e15392b7039b
+Author: Peter Hutterer <[email protected]>
+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 <[email protected]>
+
+commit 0dad7408fac3b69c4b6ab7705f39f790d7ba20c2
+Author: Peter Hutterer <[email protected]>
+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 <[email protected]>
+    Reviewed-by: Hans de Goede <[email protected]>
+
+commit ea02578a4e888d9908eb6bed6dcb858f78acb8bb
+Author: Peter Hutterer <[email protected]>
+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 <[email protected]>
+    Reviewed-by: Hans de Goede <[email protected]>
+
+commit 2ceb2e1b18b6f971706230d16a2a5665d87aabd4
+Author: Peter Hutterer <[email protected]>
+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 <[email protected]>
+    Reviewed-by: Hans de Goede <[email protected]>
+
+commit f47f78eb0bd9fba455f01c8c6dead3bd75242b2b
+Author: Peter Hutterer <[email protected]>
+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 <[email protected]>
+    Reviewed-by: Hans de Goede <[email protected]>
+
 commit 1c3ce3ce3c315213511735db1b0fdd74ca8442d0
 Author: Peter Hutterer <[email protected]>
 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;
+}



Reply via email to