README.txt | 14 configure.ac | 33 debian/changelog | 22 debian/libinput10.symbols | 4 debian/patches/0001-libinput-add-orientation-and-size-of-touch-point-and.patch | 1601 ++++++++++ debian/patches/0002-extend-tools-to-print-and-display-touch-event-proper.patch | 141 debian/patches/0003-Fix-premature-flushing-of-evdev-event-on-mx4-touchsc.patch | 171 + debian/patches/0004-Keep-stanza-for-new-symbols-on-version-0.22.0.patch | 61 debian/patches/fix-premature-flushing-of-evdev-event-on-mx4.patch | 164 - debian/patches/series | 6 debian/patches/touch-point-orientation-size.patch | 1587 --------- debian/upstream/signing-key.asc | 24 debian/watch | 2 doc/Makefile.am | 3 doc/building.dox | 100 doc/contributing.dox | 18 doc/libinput.doxygen.in | 1 doc/middle-button-emulation.dox | 34 doc/page-hierarchy.dox | 6 doc/pointer-acceleration.dox | 25 doc/reporting-bugs.dox | 113 doc/tablet-support.dox | 13 doc/test-suite.dox | 21 src/evdev-mt-touchpad-buttons.c | 113 src/evdev-mt-touchpad-edge-scroll.c | 21 src/evdev-mt-touchpad-gestures.c | 5 src/evdev-mt-touchpad-tap.c | 82 src/evdev-mt-touchpad.c | 280 + src/evdev-mt-touchpad.h | 27 src/evdev-tablet-pad.c | 1 src/evdev-tablet.c | 94 src/evdev-tablet.h | 5 src/evdev.c | 1232 ++++--- src/evdev.h | 156 src/libinput-private.h | 26 src/libinput-uninstalled.pc.in | 10 src/libinput-util.c | 34 src/libinput-util.h | 17 src/libinput.c | 47 src/libinput.h | 105 src/libinput.sym | 6 test/Makefile.am | 109 test/device.c | 129 test/gestures.c | 4 test/keyboard.c | 2 test/litest-device-mouse-wheel-click-angle.c | 3 test/litest-device-mouse-wheel-click-count.c | 77 test/litest-device-synaptics.c | 4 test/litest-device-wacom-cintiq-13hdt-finger.c | 10 test/litest-device-wacom-cintiq-13hdt-pad.c | 3 test/litest-device-wacom-cintiq-13hdt-pen.c | 10 test/litest-device-wacom-intuos-finger.c | 10 test/litest-device-wacom-intuos-tablet.c | 10 test/litest-device-wacom-intuos5-pad.c | 1 test/litest.c | 588 ++- test/litest.h | 43 test/log.c | 4 test/misc.c | 37 test/pad.c | 2 test/path.c | 14 test/pointer.c | 62 test/tablet.c | 367 ++ test/touch.c | 2 test/touchpad-buttons.c | 2 test/touchpad-tap.c | 290 + test/touchpad.c | 439 ++ test/trackball.c | 2 test/trackpoint.c | 2 test/udev.c | 14 tools/event-debug.c | 12 tools/event-gui.c | 2 tools/shared.c | 22 tools/shared.h | 1 udev/90-libinput-model-quirks.hwdb | 9 udev/Makefile.am | 16 udev/libinput-device-group.c | 64 udev/parse_hwdb.py | 178 + 77 files changed, 5973 insertions(+), 2996 deletions(-)
New commits: commit ff567def94f21b75c216ae7ecf2d252d02e512ee Author: Timo Aaltonen <tjaal...@debian.org> Date: Tue Nov 22 15:48:29 2016 +0200 updload to zesty diff --git a/debian/changelog b/debian/changelog index 2c1c2d4..a96109c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,10 +1,10 @@ -libinput (1.5.1-1ubuntu1) UNRELEASED; urgency=medium +libinput (1.5.1-1ubuntu1) zesty; urgency=medium * Merge from Debian. * Split, rename & refresh patches for touch point orientation and event flushing on MX4. - -- Timo Aaltonen <tjaal...@debian.org> Tue, 22 Nov 2016 15:41:10 +0200 + -- Timo Aaltonen <tjaal...@debian.org> Tue, 22 Nov 2016 15:48:09 +0200 libinput (1.5.1-1) unstable; urgency=medium commit 8788dc2f6c254422da919be4121f1f028021a30a Author: Timo Aaltonen <tjaal...@debian.org> Date: Tue Nov 22 15:48:06 2016 +0200 update changelog diff --git a/debian/changelog b/debian/changelog index 482a542..2c1c2d4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,11 +1,4 @@ -libinput (1.5.1-1) unstable; urgency=medium - - * New upstream release. - * watch: Let uscan verify tarball signatures. - - -- Timo Aaltonen <tjaal...@debian.org> Fri, 18 Nov 2016 15:58:09 +0200 - -libinput (1.5.0-1ubuntu1) UNRELEASED; urgency=medium +libinput (1.5.1-1ubuntu1) UNRELEASED; urgency=medium * Merge from Debian. * Split, rename & refresh patches for touch point orientation and @@ -13,6 +6,13 @@ libinput (1.5.0-1ubuntu1) UNRELEASED; urgency=medium -- Timo Aaltonen <tjaal...@debian.org> Tue, 22 Nov 2016 15:41:10 +0200 +libinput (1.5.1-1) unstable; urgency=medium + + * New upstream release. + * watch: Let uscan verify tarball signatures. + + -- Timo Aaltonen <tjaal...@debian.org> Fri, 18 Nov 2016 15:58:09 +0200 + libinput (1.5.0-1) unstable; urgency=medium * New upstream release. commit 418b33c635613c7251ad5c00554844b33e4a5315 Author: Timo Aaltonen <tjaal...@debian.org> Date: Tue Nov 22 15:42:01 2016 +0200 split and update patches diff --git a/debian/changelog b/debian/changelog index 1fcdd8f..f01483f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +libinput (1.5.0-1ubuntu1) UNRELEASED; urgency=medium + + * Merge from Debian. + * Split, rename & refresh patches for touch point orientation and + event flushing on MX4. + + -- Timo Aaltonen <tjaal...@debian.org> Tue, 22 Nov 2016 15:41:10 +0200 + libinput (1.5.0-1) unstable; urgency=medium * New upstream release. diff --git a/debian/patches/0001-libinput-add-orientation-and-size-of-touch-point-and.patch b/debian/patches/0001-libinput-add-orientation-and-size-of-touch-point-and.patch new file mode 100644 index 0000000..e31ebc8 --- /dev/null +++ b/debian/patches/0001-libinput-add-orientation-and-size-of-touch-point-and.patch @@ -0,0 +1,1601 @@ +From a50c0a226d769fade483104c95fb55ebba6ca0de Mon Sep 17 00:00:00 2001 +From: Andreas Pokorny <andreas.poko...@canonical.com> +Date: Mon, 2 Nov 2015 16:13:40 +0100 +Subject: [PATCH libinput 1/4] libinput: add orientation and size of touch + point and pressure to the API + +This change adds four new properties to touch events: +* major: diameter of the touch ellipse along the major axis +* minor: diameter perpendicular to major axis +* pressure: a pressure value mapped into the range [0, 1] +* orientation: the angle between major and the x axis [0, 360] + +Those values are optionally supported by multi-touch drivers, so default values +are used if the information is missing. The existance of each of the properties +can be queried at the event using another set of libinput_event_touch_has_* +functions. + +Explanation of those values was added to the touch screen page. + +Signed-off-by: Andreas Pokorny <andreas.poko...@canonical.com> +--- + doc/Makefile.am | 2 + + doc/page-hierarchy.dox | 1 + + doc/svg/touchscreen-touch-event-properties.svg | 347 +++++++++++++++++++++++++ + doc/touch-event-properties.dox | 42 +++ + src/evdev.c | 169 +++++++++++- + src/evdev.h | 25 ++ + src/libinput-private.h | 13 +- + src/libinput.c | 212 ++++++++++++++- + src/libinput.h | 222 ++++++++++++++++ + src/libinput.sym | 13 + + test/touch.c | 242 +++++++++++++++++ + 11 files changed, 1278 insertions(+), 10 deletions(-) + create mode 100644 doc/svg/touchscreen-touch-event-properties.svg + create mode 100644 doc/touch-event-properties.dox + +diff --git a/doc/Makefile.am b/doc/Makefile.am +index 698a316..5a346fc 100644 +--- a/doc/Makefile.am ++++ b/doc/Makefile.am +@@ -28,6 +28,7 @@ header_files = \ + $(srcdir)/test-suite.dox \ + $(srcdir)/tools.dox \ + $(srcdir)/touchpad-jumping-cursors.dox \ ++ $(srcdir)/touch-event-properties.dox \ + $(srcdir)/touchpads.dox + + diagram_files = \ +@@ -62,6 +63,7 @@ diagram_files = \ + $(srcdir)/svg/thumb-detection.svg \ + $(srcdir)/svg/top-software-buttons.svg \ + $(srcdir)/svg/touchscreen-gestures.svg \ ++ $(srcdir)/svg/touchscreen-touch-event-properties.svg \ + $(srcdir)/svg/twofinger-scrolling.svg + + style_files = \ +diff --git a/doc/page-hierarchy.dox b/doc/page-hierarchy.dox +index 6f1a4bc..3beb04f 100644 +--- a/doc/page-hierarchy.dox ++++ b/doc/page-hierarchy.dox +@@ -13,6 +13,7 @@ + @page touchscreens Touchscreens + + - @subpage absolute_axes ++- @subpage touch_event_properties + + @page pointers Mice, Trackballs, etc. + +diff --git a/doc/svg/touchscreen-touch-event-properties.svg b/doc/svg/touchscreen-touch-event-properties.svg +new file mode 100644 +index 0000000..b728f40 +--- /dev/null ++++ b/doc/svg/touchscreen-touch-event-properties.svg +@@ -0,0 +1,347 @@ ++<?xml version="1.0" encoding="UTF-8" standalone="no"?> ++<!-- Created with Inkscape (http://www.inkscape.org/) --> ++ ++<svg ++ xmlns:dc="http://purl.org/dc/elements/1.1/" ++ xmlns:cc="http://creativecommons.org/ns#" ++ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" ++ xmlns:svg="http://www.w3.org/2000/svg" ++ xmlns="http://www.w3.org/2000/svg" ++ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" ++ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" ++ width="81.778557mm" ++ height="107.62305mm" ++ viewBox="0 0 289.76655 381.34154" ++ id="svg2" ++ version="1.1" ++ inkscape:version="0.91 r13725" ++ sodipodi:docname="touchscreen-touch-event-properties.svg"> ++ <defs ++ id="defs4"> ++ <marker ++ inkscape:stockid="DotL" ++ orient="auto" ++ refY="0" ++ refX="0" ++ id="DotL" ++ style="overflow:visible" ++ inkscape:isstock="true"> ++ <path ++ id="path4259" ++ d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z" ++ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1" ++ transform="matrix(0.8,0,0,0.8,5.92,0.8)" ++ inkscape:connector-curvature="0" /> ++ </marker> ++ <marker ++ inkscape:stockid="CurveOut" ++ orient="auto" ++ refY="0" ++ refX="0" ++ id="CurveOut" ++ style="overflow:visible" ++ inkscape:isstock="true"> ++ <path ++ id="path4385" ++ d="m -5.4129913,-5.0456926 c 2.76,0 4.99999999,2.24 4.99999999,5.00000002 0,2.75999998 -2.23999999,4.99999998 -4.99999999,4.99999998" ++ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1" ++ transform="scale(0.6,0.6)" ++ inkscape:connector-curvature="0" /> ++ </marker> ++ <marker ++ inkscape:stockid="StopL" ++ orient="auto" ++ refY="0" ++ refX="0" ++ id="StopL" ++ style="overflow:visible" ++ inkscape:isstock="true"> ++ <path ++ id="path4367" ++ d="M 0,5.65 0,-5.65" ++ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1" ++ transform="scale(0.8,0.8)" ++ inkscape:connector-curvature="0" /> ++ </marker> ++ <marker ++ style="overflow:visible" ++ id="DistanceStart" ++ refX="0" ++ refY="0" ++ orient="auto" ++ inkscape:stockid="DistanceStart" ++ inkscape:isstock="true"> ++ <g ++ id="g2300" ++ style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-opacity:1"> ++ <path ++ style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.14999998;stroke-linecap:square;stroke-opacity:1" ++ d="M 0,0 2,0" ++ id="path2306" ++ inkscape:connector-curvature="0" /> ++ <path ++ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-opacity:1" ++ d="M 0,0 13,4 9,0 13,-4 0,0 Z" ++ id="path2302" ++ inkscape:connector-curvature="0" /> ++ <path ++ style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-opacity:1" ++ d="M 0,-4 0,40" ++ id="path2304" ++ inkscape:connector-curvature="0" /> ++ </g> ++ </marker> ++ <marker ++ inkscape:stockid="Arrow2Mend" ++ orient="auto" ++ refY="0" ++ refX="0" ++ id="Arrow2Mend" ++ style="overflow:visible" ++ inkscape:isstock="true"> ++ <path ++ id="path4225" ++ style="fill:#cb004e;fill-opacity:1;fill-rule:evenodd;stroke:#cb004e;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" ++ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" ++ transform="scale(-0.6,-0.6)" ++ inkscape:connector-curvature="0" /> ++ </marker> ++ <marker ++ inkscape:stockid="Arrow2Lend" ++ orient="auto" ++ refY="0" ++ refX="0" ++ id="Arrow2Lend" ++ style="overflow:visible" ++ inkscape:isstock="true"> ++ <path ++ id="path4219" ++ style="fill:#cb004e;fill-opacity:1;fill-rule:evenodd;stroke:#cb004e;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" ++ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" ++ transform="matrix(-1.1,0,0,-1.1,-1.1,0)" ++ inkscape:connector-curvature="0" /> ++ </marker> ++ <marker ++ inkscape:stockid="TriangleInL" ++ orient="auto" ++ refY="0" ++ refX="0" ++ id="TriangleInL" ++ style="overflow:visible" ++ inkscape:isstock="true"> ++ <path ++ id="path4331" ++ d="m 5.77,0 -8.65,5 0,-10 8.65,5 z" ++ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:#b3b3b3;stroke-width:1pt;stroke-opacity:1" ++ transform="scale(-0.8,-0.8)" ++ inkscape:connector-curvature="0" /> ++ </marker> ++ <marker ++ inkscape:stockid="Arrow2Lstart" ++ orient="auto" ++ refY="0" ++ refX="0" ++ id="Arrow2Lstart" ++ style="overflow:visible" ++ inkscape:isstock="true"> ++ <path ++ id="path4216" ++ style="fill:#cb004e;fill-opacity:1;fill-rule:evenodd;stroke:#cb004e;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1" ++ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" ++ transform="matrix(1.1,0,0,1.1,1.1,0)" ++ inkscape:connector-curvature="0" /> ++ </marker> ++ <inkscape:path-effect ++ effect="powerstroke" ++ id="path-effect4140" ++ is_visible="true" ++ offset_points="0,0.5" ++ sort_points="true" ++ interpolator_type="Linear" ++ interpolator_beta="0.2" ++ start_linecap_type="zerowidth" ++ linejoin_type="round" ++ miter_limit="4" ++ end_linecap_type="zerowidth" ++ cusp_linecap_type="round" /> ++ <marker ++ inkscape:stockid="TriangleInL" ++ orient="auto" ++ refY="0" ++ refX="0" ++ id="TriangleInL-1" ++ style="overflow:visible" ++ inkscape:isstock="true"> ++ <path ++ inkscape:connector-curvature="0" ++ id="path4331-8" ++ d="m 5.77,0 -8.65,5 0,-10 8.65,5 z" ++ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:#b3b3b3;stroke-width:1pt;stroke-opacity:1" ++ transform="scale(-0.8,-0.8)" /> ++ </marker> ++ <marker ++ inkscape:stockid="TriangleInL" ++ orient="auto" ++ refY="0" ++ refX="0" ++ id="TriangleInL-1-3" ++ style="overflow:visible" ++ inkscape:isstock="true"> ++ <path ++ inkscape:connector-curvature="0" ++ id="path4331-8-7" ++ d="m 5.77,0 -8.65,5 0,-10 8.65,5 z" ++ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:#b3b3b3;stroke-width:1pt;stroke-opacity:1" ++ transform="scale(-0.8,-0.8)" /> ++ </marker> ++ </defs> ++ <sodipodi:namedview ++ id="base" ++ pagecolor="#ffffff" ++ bordercolor="#666666" ++ borderopacity="1.0" ++ inkscape:pageopacity="0.0" ++ inkscape:pageshadow="2" ++ inkscape:zoom="0.99999999" ++ inkscape:cx="123.83444" ++ inkscape:cy="279.21547" ++ inkscape:document-units="px" ++ inkscape:current-layer="layer1" ++ showgrid="false" ++ showguides="false" ++ inkscape:window-width="2560" ++ inkscape:window-height="1056" ++ inkscape:window-x="0" ++ inkscape:window-y="24" ++ inkscape:window-maximized="1" ++ fit-margin-top="0" ++ fit-margin-left="0" ++ fit-margin-right="0" ++ fit-margin-bottom="0" /> ++ <metadata ++ id="metadata7"> ++ <rdf:RDF> ++ <cc:Work ++ rdf:about=""> ++ <dc:format>image/svg+xml</dc:format> ++ <dc:type ++ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> ++ <dc:title></dc:title> ++ </cc:Work> ++ </rdf:RDF> ++ </metadata> ++ <g ++ inkscape:label="Layer 1" ++ inkscape:groupmode="layer" ++ id="layer1" ++ transform="translate(-99.549825,-70.836892)"> ++ <path ++ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:#b3b3b3;stroke-width:1.79780054px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#TriangleInL-1-3)" ++ d="m 231.28087,80.931744 -0.008,371.246666" ++ id="path4144-1-8-1" ++ inkscape:connector-curvature="0" ++ sodipodi:nodetypes="cc" /> ++ <g ++ id="g6309" ++ inkscape:transform-center-x="-9.527809" ++ inkscape:transform-center-y="-8.1612127" ++ transform="matrix(1.171972,1.3632932,-1.3632932,1.171972,275.33248,-179.00364)"> ++ <path ++ sodipodi:nodetypes="cc" ++ inkscape:connector-curvature="0" ++ id="path4144-1-8" ++ d="m 172.88767,70.631028 -0.004,206.500482" ++ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:#b3b3b3;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#TriangleInL-1)" /> ++ <ellipse ++ ry="77.321434" ++ rx="45.89286" ++ cy="180.93364" ++ cx="172.85715" ++ id="path4136" ++ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> ++ <path ++ sodipodi:nodetypes="cc" ++ inkscape:connector-curvature="0" ++ id="path4142" ++ d="m 126.9449,180.93396 91.84596,0.007" ++ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> ++ <path ++ sodipodi:nodetypes="cc" ++ inkscape:connector-curvature="0" ++ id="path4144" ++ d="m 172.84766,103.6564 -0.004,154.59727" ++ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> ++ <text ++ sodipodi:linespacing="125%" ++ id="text4146" ++ y="188.01213" ++ x="128.08986" ++ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.5px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" ++ xml:space="preserve"><tspan ++ y="188.01213" ++ x="128.08986" ++ id="tspan4148" ++ sodipodi:role="line">minor axis</tspan></text> ++ <text ++ transform="matrix(0,-1,1,0,0,0)" ++ sodipodi:linespacing="125%" ++ id="text4150" ++ y="169.33234" ++ x="-256.35562" ++ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.5px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" ++ xml:space="preserve"><tspan ++ y="169.33234" ++ x="-256.35562" ++ id="tspan4152" ++ sodipodi:role="line">major axis</tspan></text> ++ </g> ++ <text ++ xml:space="preserve" ++ style="font-style:normal;font-weight:normal;font-size:71.91202545px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" ++ x="44.285629" ++ y="369.12045" ++ id="text6877" ++ sodipodi:linespacing="125%" ++ transform="matrix(0.76306478,-0.64632201,0.64632201,0.76306478,0,0)"><tspan ++ sodipodi:role="line" ++ id="tspan6879" ++ x="44.285629" ++ y="369.12045" ++ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.4835043px;font-family:sans-serif;-inkscape-font-specification:sans-serif;fill:#b3b3b3;fill-opacity:1">pointing direction</tspan></text> ++ <text ++ xml:space="preserve" ++ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.4835043px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" ++ x="237.00804" ++ y="99.788658" ++ id="text6887" ++ sodipodi:linespacing="125%"><tspan ++ sodipodi:role="line" ++ id="tspan6889" ++ x="237.00804" ++ y="99.788658">y axis</tspan></text> ++ <path ++ style="fill:none;fill-opacity:1;stroke:#cb004e;stroke-width:1.79780054;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)" ++ id="path7011" ++ sodipodi:type="arc" ++ sodipodi:cx="231.14914" ++ sodipodi:cy="268.54077" ++ sodipodi:rx="79.092262" ++ sodipodi:ry="79.092262" ++ sodipodi:start="4.7157629" ++ sodipodi:end="5.5461565" ++ d="m 231.41599,189.44896 a 79.092262,79.092262 0 0 1 58.2985,25.93463" ++ sodipodi:open="true" /> ++ <text ++ xml:space="preserve" ++ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.98900318px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#cb004e;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" ++ x="232.66777" ++ y="184.40468" ++ id="text7119" ++ sodipodi:linespacing="125%"><tspan ++ sodipodi:role="line" ++ id="tspan7121" ++ x="232.66777" ++ y="184.40468" ++ style="font-size:13.4835043px;fill:#cb004e;fill-opacity:1">orientation</tspan></text> ++ </g> ++</svg> +diff --git a/doc/touch-event-properties.dox b/doc/touch-event-properties.dox +new file mode 100644 +index 0000000..bf326f7 +--- /dev/null ++++ b/doc/touch-event-properties.dox +@@ -0,0 +1,42 @@ ++/** ++@page touch_event_properties Properties of a touch event ++ ++This page gives some overview on touchscreen events. With libinput touchscreens ++provide the event types @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref LIBINPUT_EVENT_TOUCH_UP, ++@ref LIBINPUT_EVENT_TOUCH_MOTION and @ref LIBINPUT_EVENT_TOUCH_CANCEL. The ++touchscreen events @ref LIBINPUT_EVENT_TOUCH_DOWN and ++@ref LIBINPUT_EVENT_TOUCH_MOTION provide alongside the actual state change and ++the absolute coordinates (@ref absolute_axes_handling) additional information ++about the touch contact. ++ ++@image html touchscreen-touch-event-properties.svg "Properties of a touch screen contact" ++ ++Assuming the interaction of fingers with a touch screen, touch contacts are ++approximated with an ellipse. The major axis of the ellipse describes the ++pointing direction of the finger. The minor axis is the perpendicular ++extent of the touching shape. The orientation angle is the clockwise rotation of ++the pointing direction against the y-axis of the touchscreen. ++ ++Additionally to the values shown in the drawing above, most touchscreens also ++provide a pressure value to indicate the force applied with the contact point. ++ ++The support for those contact properties varies between the different ++available touchscreens. In the case of pressure libinput will return the ++maximum pressure value, which is 1.0. If only the major axis but no minor axis ++is present, libinput will assume a circular shape and return the major axis ++value for convenience. If also no major axis value is known 0.0 is returned. ++If the orientation is not available libinput will return 0.0 degrees. ++ ++For querying the touch properties see: ++- libinput_event_touch_get_major_transformed() ++- libinput_event_touch_get_minor_transformed() ++- libinput_event_touch_get_orientation() ++- libinput_event_touch_get_pressure() ++ ++For testing which of the touch properties are available see: ++- libinput_event_touch_has_major() ++- libinput_event_touch_has_minor() ++- libinput_event_touch_has_orientation() ++- libinput_event_touch_has_pressure() ++ ++*/ +diff --git a/src/evdev.c b/src/evdev.c +index fac8fcb..86a93eb 100644 +--- a/src/evdev.c ++++ b/src/evdev.c +@@ -49,6 +49,10 @@ + + #define DEFAULT_WHEEL_CLICK_ANGLE 15 + #define DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT ms2us(200) ++#define DEFAULT_TOUCH_PRESSURE 1.0 ++#define DEFAULT_TOUCH_ORIENTATION 0.0 ++#define DEFAULT_TOUCH_MAJOR 0.0 ++#define DEFAULT_TOUCH_MINOR 0.0 + + enum evdev_key_type { + EVDEV_KEY_TYPE_NONE, +@@ -321,6 +325,100 @@ evdev_device_transform_y(struct evdev_device *device, + return scale_axis(device->abs.absinfo_y, y, height); + } + ++double ++evdev_device_transform_ellipse_diameter_to_mm(struct evdev_device *device, ++ int diameter, ++ double axis_angle) ++{ ++ double x_res = device->abs.absinfo_x->resolution; ++ double y_res = device->abs.absinfo_y->resolution; ++ ++ if (x_res == y_res) ++ return diameter / x_res; ++ ++ /* resolution differs but no orientation available ++ * -> estimate resolution using the average */ ++ if (device->abs.absinfo_orientation == NULL) { ++ return diameter * 2.0 / (x_res + y_res); ++ } else { ++ /* Why scale x using sine of angle? ++ * axis_angle = 0 indicates that the given diameter ++ * is aligned with the y-axis. */ ++ double x_scaling_ratio = fabs(sin(deg2rad(axis_angle))); ++ double y_scaling_ratio = fabs(cos(deg2rad(axis_angle))); ++ ++ return diameter / hypotf(y_res * y_scaling_ratio, ++ x_res * x_scaling_ratio); ++ } ++} ++ ++double ++evdev_device_transform_ellipse_diameter(struct evdev_device *device, ++ int diameter, ++ double axis_angle, ++ uint32_t width, ++ uint32_t height) ++{ ++ double x_res = device->abs.absinfo_x->resolution; ++ double y_res = device->abs.absinfo_y->resolution; ++ double x_scale = width / (device->abs.dimensions.x + 1.0); ++ double y_scale = height / (device->abs.dimensions.y + 1.0); ++ ++ if (x_res == y_res) ++ return diameter * x_scale; ++ ++ /* no orientation available -> estimate resolution using the ++ * average */ ++ if (device->abs.absinfo_orientation == NULL) { ++ return diameter * (x_scale + y_scale) / 2.0; ++ } else { ++ /* Why scale x using sine of angle? ++ * axis_angle = 0 indicates that the given diameter ++ * is aligned with the y-axis. */ ++ double x_scaling_ratio = fabs(sin(deg2rad(axis_angle))); ++ double y_scaling_ratio = fabs(cos(deg2rad(axis_angle))); ++ ++ return diameter * (y_scale * y_scaling_ratio + ++ x_scale * x_scaling_ratio); ++ } ++} ++ ++double ++evdev_device_transform_orientation(struct evdev_device *device, ++ int32_t orientation) ++{ ++ const struct input_absinfo *orientation_info = ++ device->abs.absinfo_orientation; ++ ++ double angle = DEFAULT_TOUCH_ORIENTATION; ++ ++ /* ABS_MT_ORIENTATION is defined as a clockwise rotation - zero ++ * (instead of minimum) is mapped to the y-axis, and maximum is ++ * mapped to the x-axis. So minimum is likely to be negative but ++ * plays no role in scaling the value to degrees.*/ ++ if (orientation_info) ++ angle = (90.0 * orientation) / orientation_info->maximum; ++ ++ return fmod(360.0 + angle, 360.0); ++} ++ ++double ++evdev_device_transform_pressure(struct evdev_device *device, ++ int32_t pressure) ++{ ++ const struct input_absinfo *pressure_info = ++ device->abs.absinfo_pressure; ++ ++ if (pressure_info) { ++ double max_pressure = pressure_info->maximum; ++ double min_pressure = pressure_info->minimum; ++ return (pressure - min_pressure) / ++ (max_pressure - min_pressure); ++ } else { ++ return DEFAULT_TOUCH_PRESSURE; ++ } ++} ++ + static inline void + normalize_delta(struct evdev_device *device, + const struct device_coords *delta, +@@ -462,6 +560,7 @@ fallback_flush_mt_down(struct fallback_dispatch *dispatch, + struct libinput_seat *seat = base->seat; + struct device_coords point; + struct mt_slot *slot; ++ + int seat_slot; + + if (!(device->seat_caps & EVDEV_DEVICE_TOUCH)) +@@ -490,7 +589,8 @@ fallback_flush_mt_down(struct fallback_dispatch *dispatch, + evdev_transform_absolute(device, &point); + + touch_notify_touch_down(base, time, slot_idx, seat_slot, +- &point); ++ &point, &slot->area, slot->pressure); ++ + + return true; + } +@@ -521,7 +621,7 @@ fallback_flush_mt_motion(struct fallback_dispatch *dispatch, + + evdev_transform_absolute(device, &point); + touch_notify_touch_motion(base, time, slot_idx, seat_slot, +- &point); ++ &point, &slot->area, slot->pressure); + + return true; + } +@@ -562,6 +662,11 @@ fallback_flush_st_down(struct fallback_dispatch *dispatch, + struct libinput_device *base = &device->base; + struct libinput_seat *seat = base->seat; + struct device_coords point; ++ struct ellipse default_area = { ++ .major = DEFAULT_TOUCH_MAJOR, ++ .minor = DEFAULT_TOUCH_MINOR, ++ .orientation = DEFAULT_TOUCH_ORIENTATION, ++ }; + int seat_slot; + + if (!(device->seat_caps & EVDEV_DEVICE_TOUCH)) +@@ -588,7 +693,8 @@ fallback_flush_st_down(struct fallback_dispatch *dispatch, + point = dispatch->abs.point; + evdev_transform_absolute(device, &point); + +- touch_notify_touch_down(base, time, -1, seat_slot, &point); ++ touch_notify_touch_down(base, time, -1, seat_slot, &point, ++ &default_area, DEFAULT_TOUCH_PRESSURE); + + return true; + } +@@ -600,6 +706,11 @@ fallback_flush_st_motion(struct fallback_dispatch *dispatch, + { + struct libinput_device *base = &device->base; + struct device_coords point; ++ struct ellipse default_area = { ++ .major = DEFAULT_TOUCH_MAJOR, ++ .minor = DEFAULT_TOUCH_MINOR, ++ .orientation = DEFAULT_TOUCH_ORIENTATION, ++ }; + int seat_slot; + + point = dispatch->abs.point; +@@ -610,7 +721,8 @@ fallback_flush_st_motion(struct fallback_dispatch *dispatch, + if (seat_slot == -1) + return false; + +- touch_notify_touch_motion(base, time, -1, seat_slot, &point); ++ touch_notify_touch_motion(base, time, -1, seat_slot, &point, ++ &default_area, DEFAULT_TOUCH_PRESSURE); + + return true; + } +@@ -829,6 +941,9 @@ fallback_process_touch(struct fallback_dispatch *dispatch, + struct input_event *e, + uint64_t time) + { ++ struct mt_slot *current_slot = &dispatch->mt.slots[dispatch->mt.slot]; ++ int pending_event = EVDEV_NONE; ++ + switch (e->code) { + case ABS_MT_SLOT: + if ((size_t)e->value >= dispatch->mt.slots_len) { +@@ -858,10 +973,28 @@ fallback_process_touch(struct fallback_dispatch *dispatch, + break; + case ABS_MT_POSITION_Y: + dispatch->mt.slots[dispatch->mt.slot].point.y = e->value; +- if (dispatch->pending_event == EVDEV_NONE) +- dispatch->pending_event = EVDEV_ABSOLUTE_MT_MOTION; ++ pending_event = EVDEV_ABSOLUTE_MT_MOTION; ++ break; ++ case ABS_MT_TOUCH_MAJOR: ++ current_slot->area.major = e->value; ++ pending_event = EVDEV_ABSOLUTE_MT_MOTION; ++ break; ++ case ABS_MT_TOUCH_MINOR: ++ current_slot->area.minor = e->value; ++ pending_event = EVDEV_ABSOLUTE_MT_MOTION; ++ break; ++ case ABS_MT_ORIENTATION: ++ current_slot->area.orientation = e->value; ++ pending_event = EVDEV_ABSOLUTE_MT_MOTION; ++ break; ++ case ABS_MT_PRESSURE: ++ current_slot->pressure = e->value; ++ pending_event = EVDEV_ABSOLUTE_MT_MOTION; + break; + } ++ ++ if (dispatch->pending_event == EVDEV_NONE && pending_event != EVDEV_NONE) ++ dispatch->pending_event = pending_event;; + } + static inline void + fallback_process_absolute_motion(struct fallback_dispatch *dispatch, +@@ -1684,6 +1817,21 @@ fallback_dispatch_init_slots(struct fallback_dispatch *dispatch, + slots[slot].point.y = libevdev_get_slot_value(evdev, + slot, + ABS_MT_POSITION_Y); ++ slots[slot].area.major = ++ libevdev_get_slot_value(evdev, ++ slot, ++ ABS_MT_TOUCH_MAJOR); ++ slots[slot].area.minor = ++ libevdev_get_slot_value(evdev, ++ slot, ++ ABS_MT_TOUCH_MINOR); ++ slots[slot].area.orientation = ++ libevdev_get_slot_value(evdev, ++ slot, ++ ABS_MT_ORIENTATION); ++ slots[slot].pressure = ++ libevdev_get_slot_value(evdev, slot, ABS_MT_PRESSURE); ++ + } + dispatch->mt.slots = slots; + dispatch->mt.slots_len = num_slots; +@@ -2518,6 +2666,15 @@ evdev_configure_device(struct evdev_device *device) + return NULL; + } + ++ device->abs.absinfo_orientation = ++ libevdev_get_abs_info(evdev, ABS_MT_ORIENTATION); ++ device->abs.absinfo_pressure = ++ libevdev_get_abs_info(evdev, ABS_MT_PRESSURE); ++ device->abs.absinfo_major = ++ libevdev_get_abs_info(evdev, ABS_MT_TOUCH_MAJOR); ++ device->abs.absinfo_minor = ++ libevdev_get_abs_info(evdev, ABS_MT_TOUCH_MINOR); ++ + if (!evdev_is_fake_mt_device(device)) + evdev_fix_android_mt(device); + +diff --git a/src/evdev.h b/src/evdev.h +index b811f51..51521de 100644 +--- a/src/evdev.h ++++ b/src/evdev.h +@@ -127,6 +127,8 @@ struct mt_slot { + int32_t seat_slot; + struct device_coords point; + struct device_coords hysteresis_center; ++ struct ellipse area; ++ int32_t pressure; + }; + + struct evdev_device { +@@ -153,6 +155,8 @@ struct evdev_device { + + struct { + const struct input_absinfo *absinfo_x, *absinfo_y; ++ const struct input_absinfo *absinfo_major, *absinfo_minor, ++ *absinfo_pressure, *absinfo_orientation; + bool is_fake_resolution; + + int apply_calibration; +@@ -432,6 +436,27 @@ double + evdev_device_transform_y(struct evdev_device *device, + double y, + uint32_t height); ++ ++double ++evdev_device_transform_ellipse_diameter_to_mm(struct evdev_device *device, ++ int32_t diameter, ++ double axis_angle); ++ ++double ++evdev_device_transform_ellipse_diameter(struct evdev_device *device, ++ int32_t diameter, ++ double axis_angle, ++ uint32_t width, ++ uint32_t height); ++ ++double ++evdev_device_transform_orientation(struct evdev_device *device, ++ int32_t orientation); ++ ++double ++evdev_device_transform_pressure(struct evdev_device *device, ++ int32_t pressure); ++ + void + evdev_device_suspend(struct evdev_device *device); + +diff --git a/src/libinput-private.h b/src/libinput-private.h +index 52f129a..d259b8b 100644 +--- a/src/libinput-private.h ++++ b/src/libinput-private.h +@@ -48,6 +48,11 @@ struct device_coords { + int x, y; + }; + ++/* Ellipse parameters in device coordinates */ ++struct ellipse { ++ int major, minor, orientation; ++}; ++ + /* + * A coordinate pair in device coordinates, capable of holding non discrete + * values, this is necessary e.g. when device coordinates get averaged. +@@ -514,14 +519,18 @@ touch_notify_touch_down(struct libinput_device *device, + uint64_t time, + int32_t slot, + int32_t seat_slot, +- const struct device_coords *point); ++ const struct device_coords *point, ++ const struct ellipse *area, ++ int32_t pressure); + + void + touch_notify_touch_motion(struct libinput_device *device, + uint64_t time, + int32_t slot, + int32_t seat_slot, +- const struct device_coords *point); ++ const struct device_coords *point, ++ const struct ellipse *area, ++ int32_t pressure); + + void + touch_notify_touch_up(struct libinput_device *device, +diff --git a/src/libinput.c b/src/libinput.c +index 1e97ad1..f3df972 100644 +--- a/src/libinput.c ++++ b/src/libinput.c +@@ -112,6 +112,8 @@ struct libinput_event_touch { + int32_t slot; + int32_t seat_slot; + struct device_coords point;