mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-04 05:50:26 +01:00
Merge branch 'wip/tablet-pad-support'
This commit is contained in:
commit
064c72a52a
22 changed files with 2843 additions and 57 deletions
325
doc/svg/tablet-interfaces.svg
Normal file
325
doc/svg/tablet-interfaces.svg
Normal file
|
|
@ -0,0 +1,325 @@
|
|||
<?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:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="229.5488mm"
|
||||
height="86.66362mm"
|
||||
viewBox="0 0 813.36188 307.07582"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="tablet-interfaces.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4294">
|
||||
<stop
|
||||
style="stop-color:#1a1a1a;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4296" />
|
||||
<stop
|
||||
style="stop-color:#808080;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4298" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4294"
|
||||
id="linearGradient4300"
|
||||
x1="465.81339"
|
||||
y1="666.13727"
|
||||
x2="454.82117"
|
||||
y2="658.65521"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.8"
|
||||
inkscape:cx="587.87559"
|
||||
inkscape:cy="104.80851"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g3663-9-5"
|
||||
showgrid="false"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
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="tablet"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
style="display:inline"
|
||||
transform="translate(67.109152,-133.63374)">
|
||||
<g
|
||||
id="g4309"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<rect
|
||||
y="134.15933"
|
||||
x="75.787216"
|
||||
height="306.02466"
|
||||
width="522.19733"
|
||||
id="rect4136"
|
||||
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:1.05118144;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:4.20472551, 1.05118138;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<rect
|
||||
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.74813837;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:2.99255325, 0.74813831;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4140"
|
||||
width="357.34042"
|
||||
height="226.52563"
|
||||
x="199.33878"
|
||||
y="175.42407" />
|
||||
<rect
|
||||
y="175.72914"
|
||||
x="103.10225"
|
||||
height="22.142857"
|
||||
width="65"
|
||||
id="rect4142"
|
||||
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.98900002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<rect
|
||||
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.98900002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4148"
|
||||
width="65"
|
||||
height="22.142857"
|
||||
x="103.10225"
|
||||
y="203.72914" />
|
||||
<rect
|
||||
y="231.72913"
|
||||
x="103.10225"
|
||||
height="22.142857"
|
||||
width="65"
|
||||
id="rect4150"
|
||||
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.98900002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<rect
|
||||
y="323.72913"
|
||||
x="103.10225"
|
||||
height="22.142857"
|
||||
width="65"
|
||||
id="rect4154"
|
||||
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.98900002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<rect
|
||||
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.98900002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect4156"
|
||||
width="65"
|
||||
height="22.142857"
|
||||
x="103.10225"
|
||||
y="351.72913" />
|
||||
<circle
|
||||
r="22.98097"
|
||||
cy="287.06125"
|
||||
cx="135.61298"
|
||||
id="path4158"
|
||||
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.98900002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<ellipse
|
||||
ry="12.608653"
|
||||
rx="11.5985"
|
||||
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.52043104;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:2.08172421, 0.52043105;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="circle4160"
|
||||
cx="135.61298"
|
||||
cy="287.06125" />
|
||||
<rect
|
||||
y="379.72913"
|
||||
x="103.10225"
|
||||
height="22.142857"
|
||||
width="65"
|
||||
id="rect4162"
|
||||
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.98900002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="stylus"
|
||||
style="display:inline"
|
||||
transform="translate(67.109152,-133.63374)">
|
||||
<g
|
||||
id="g4304"
|
||||
transform="matrix(0.37129971,0.09948946,-0.09618892,0.35898192,295.60339,7.6883643)">
|
||||
<path
|
||||
sodipodi:nodetypes="czcc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4286"
|
||||
d="m 387.83544,799.76093 c -1.1128,3.61694 -3.2211,13.05163 -1.08543,14.07769 2.13567,1.02606 7.81039,-3.72162 10.99756,-6.69095 z"
|
||||
style="display:inline;fill:#cccccc;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ssssccssscsssssssssssssssssss"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4283"
|
||||
d="m 392.64431,804.79039 c -8.52094,-5.90399 -8.49394,-11.01546 0.22879,-43.30647 1.03999,-3.85 2.46829,-9.67602 3.17399,-12.9467 0.99731,-4.62219 2.39455,-7.29497 6.27321,-12 2.74456,-3.32932 5.25157,-6.2783 5.57113,-6.5533 40.78433,-60.97488 80.48307,-125.1652 118.27253,-184 9.86283,-15.675 26.59424,-42.225 37.18089,-59 10.58666,-16.775 34.01422,-53.9 52.06125,-82.5 18.04703,-28.6 35.04505,-55.31677 37.77338,-59.37059 l 4.9606,-7.3706 4.1828,0.57332 c 4.16371,0.5707 4.19706,0.54958 7.30887,-4.62941 3.75631,-6.2516 8.82067,-11.57582 12.2516,-12.88026 5.99391,-2.27888 14.03303,2.9506 14.03303,9.12854 0,3.90203 -2.51704,10.62127 -6.02878,16.09385 -1.63417,2.54664 -2.97122,4.85949 -2.97122,5.13969 0,0.28019 0.9,1.54715 2,2.81546 2.28453,2.63408 2.47267,4.21918 0.86833,7.31574 -1.28218,2.47476 -26.61383,45.18798 -55.85724,94.18426 -10.83283,18.15 -25.72943,43.1137 -33.10357,55.47489 -7.37413,12.3612 -13.69273,23.17153 -14.04131,24.02297 -0.34859,0.85144 -7.50972,12.78774 -15.91363,26.52511 -15.54138,25.40455 -32.24417,52.9052 -70.74345,116.47703 -40.26028,66.47968 -43.66308,72.46026 -49.21634,86.5 -1.74036,4.4 -3.92035,8.675 -4.8444,9.5 -0.92405,0.825 -4.36246,3.75 -7.6409,6.5 -3.27845,2.75 -9.57132,8.3067 -13.98415,12.34823 -10.62726,9.73304 -16.99729,13.87361 -22.52334,14.64034 -3.99187,0.55386 -5.03885,0.251 -9.27207,-2.6821 z"
|
||||
style="display:inline;fill:#000000" />
|
||||
<path
|
||||
sodipodi:nodetypes="scccs"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4292"
|
||||
d="m 450.89044,688.88586 c 8.71518,5.62513 45.74035,-59.18436 43.57923,-75.43494 l -7.07107,-6.56599 c -29.93081,25.86352 -47.78438,74.72281 -47.78438,74.72281 0,0 0,0 11.27622,7.27812 z"
|
||||
style="fill:url(#linearGradient4300);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
style="display:inline"
|
||||
transform="matrix(0.98314313,0.18283763,-0.18283763,0.98314313,124.70585,-392.20667)"
|
||||
id="g3663-9-5">
|
||||
<rect
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:2.39000654;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect6268"
|
||||
width="98.462646"
|
||||
height="99.005119"
|
||||
x="-37.056244"
|
||||
y="554.24286"
|
||||
transform="matrix(0.98314312,-0.18283763,0.18283763,0.98314312,0,0)" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 71.874136,599.56332 -149.77963,27.8549"
|
||||
id="path6270"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:17.5px;line-height:125%;font-family:Sans;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"
|
||||
x="-193.01566"
|
||||
y="595.05914"
|
||||
id="text6272"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="matrix(0.98314312,-0.18283763,0.18283763,0.98314312,0,0)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6274"
|
||||
x="-193.01566"
|
||||
y="595.05914">Pad buttons</tspan></text>
|
||||
<rect
|
||||
transform="matrix(0.98314312,-0.18283763,0.18283763,0.98314312,0,0)"
|
||||
y="706.24286"
|
||||
x="-37.056244"
|
||||
height="99.005119"
|
||||
width="98.462646"
|
||||
id="rect6276"
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:2.39000654;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<text
|
||||
transform="matrix(0.98314312,-0.18283763,0.18283763,0.98314312,0,0)"
|
||||
sodipodi:linespacing="125%"
|
||||
id="text6282"
|
||||
y="755.05914"
|
||||
x="-193.01566"
|
||||
style="font-style:normal;font-weight:normal;font-size:17.5px;line-height:125%;font-family:Sans;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="755.05914"
|
||||
x="-193.01566"
|
||||
id="tspan6284"
|
||||
sodipodi:role="line">Pad buttons</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:17.5px;line-height:125%;font-family:Sans;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"
|
||||
x="-193.01566"
|
||||
y="755.05914"
|
||||
id="text6286"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="matrix(0.98314312,-0.18283763,0.18283763,0.98314312,0,0)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6288"
|
||||
x="-193.01566"
|
||||
y="755.05914">Pad buttons</tspan></text>
|
||||
<text
|
||||
transform="matrix(0.98314312,-0.18283763,0.18283763,0.98314312,0,0)"
|
||||
sodipodi:linespacing="125%"
|
||||
id="text6290"
|
||||
y="675.05914"
|
||||
x="-193.01566"
|
||||
style="font-style:normal;font-weight:normal;font-size:17.5px;line-height:125%;font-family:Sans;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="675.05914"
|
||||
x="-193.01566"
|
||||
id="tspan6292"
|
||||
sodipodi:role="line">Pad ring</tspan></text>
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path6296"
|
||||
d="M 125.82687,670.90125 -63.278482,706.06966"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 101.12816,756.8662 -48.65147,784.7211"
|
||||
id="path6298"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 734.27856,551.64315 407.53319,612.40883"
|
||||
id="path6300"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:17.5px;line-height:125%;font-family:Sans;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"
|
||||
x="-193.01566"
|
||||
y="675.05914"
|
||||
id="text6302"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="matrix(0.98314312,-0.18283763,0.18283763,0.98314312,0,0)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6304"
|
||||
x="-193.01566"
|
||||
y="675.05914">Pad ring</tspan></text>
|
||||
<text
|
||||
transform="matrix(0.98314312,-0.18283763,0.18283763,0.98314312,0,0)"
|
||||
sodipodi:linespacing="125%"
|
||||
id="text6306"
|
||||
y="669.05914"
|
||||
x="514.98431"
|
||||
style="font-style:normal;font-weight:normal;font-size:17.5px;line-height:125%;font-family:Sans;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="669.05914"
|
||||
x="514.98431"
|
||||
id="tspan6308"
|
||||
sodipodi:role="line">Tool buttons</tspan></text>
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path6310"
|
||||
d="M 744.15182,604.7329 368.24929,674.64046"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:17.5px;line-height:125%;font-family:Sans;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"
|
||||
x="558.98431"
|
||||
y="723.05914"
|
||||
id="text6312"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="matrix(0.98314312,-0.18283763,0.18283763,0.98314312,0,0)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6314"
|
||||
x="558.98431"
|
||||
y="723.05914">Tool tip</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 15 KiB |
|
|
@ -8,15 +8,23 @@ Apple iPad.
|
|||
|
||||
@image html tablet.svg "Illustration of a graphics tablet"
|
||||
|
||||
@section tablet-tools Tablet buttons vs. tablet tools
|
||||
@section tablet-tools Pad buttons vs. tablet tools
|
||||
|
||||
Most tablets provide two types of devices. The pysical tablet often provides
|
||||
a number of buttons and a touch ring or strip. Interaction on the drawing
|
||||
surface of the tablet requires a tool, usually in the shape of a stylus.
|
||||
The libinput interface exposed by devices with the @ref
|
||||
Most tablets provide two types of devices. The physical tablet often
|
||||
provides a number of buttons and a touch ring or strip. Interaction on the
|
||||
drawing surface of the tablet requires a tool, usually in the shape of a
|
||||
stylus. The libinput interface exposed by devices with the @ref
|
||||
LIBINPUT_DEVICE_CAP_TABLET_TOOL capability applies only to events generated
|
||||
by tools.
|
||||
|
||||
Buttons, rings or strips on the physical tablet hardware (the "pad") are
|
||||
exposed by devices with the @ref LIBINPUT_DEVICE_CAP_TABLET_PAD capability.
|
||||
Pad events do not require a tool to be in proximity. Note that both
|
||||
capabilities may exist on the same device though usually they are split
|
||||
across multiple kernel devices.
|
||||
|
||||
@image html tablet-interfaces.svg "Difference between Pad and Tool buttons"
|
||||
|
||||
Touch events on the tablet integrated into a screen itself are exposed
|
||||
through the @ref LIBINPUT_DEVICE_CAP_TOUCH capability. Touch events on a
|
||||
standalone tablet are exposed through the @ref LIBINPUT_DEVICE_CAP_POINTER
|
||||
|
|
@ -25,7 +33,7 @@ node for the touch device, resulting in a separate libinput device.
|
|||
See libinput_device_get_device_group() for information on how to associate
|
||||
the touch part with other devices exposed by the same physical hardware.
|
||||
|
||||
@section tablet-tip Tool tip events vs. button events
|
||||
@section tablet-tip Tool tip events vs. tool button events
|
||||
|
||||
The primary use of a tablet tool is to draw on the surface of the tablet.
|
||||
When the tool tip comes into contact with the surface, libinput sends an
|
||||
|
|
@ -113,6 +121,8 @@ tablets however extends further than the user may lift the mouse, i.e. the
|
|||
tool may not be lifted out of physical proximity. For such tools, libinput
|
||||
provides software-emulated proximity.
|
||||
|
||||
Events from the pad do not require proximity, they may be sent any time.
|
||||
|
||||
@section tablet-pressure-offset Pressure offset on worn-out tools
|
||||
|
||||
When a tool is used for an extended period it can wear down physically. A
|
||||
|
|
@ -209,4 +219,30 @@ libinput_event_tablet_tool_get_y_transformed() the resulting value may be
|
|||
less than 0 or larger than the upper range provided. It is up to the caller
|
||||
to test for this and handle or ignore these events accordingly.
|
||||
|
||||
@section tablet-pad-buttons Tablet pad button numbers
|
||||
|
||||
Tablet Pad buttons are numbered sequentially, starting with button 0. Thus
|
||||
button numbers returned by libinput_event_tablet_pad_get_button_number()
|
||||
have no semantic meaning, a notable difference to the button codes returned
|
||||
by other libinput interfaces (e.g. libinput_event_tablet_tool_get_button()).
|
||||
|
||||
The Linux kernel requires all input events to have semantic event codes,
|
||||
but generic buttons like those on a pad cannot easily be assigned semantic
|
||||
codes. The kernel supports generic codes in the form of BTN_0 through to
|
||||
BTN_9 and additional unnamed space up until code 0x10f. Additional generic
|
||||
buttons are available as BTN_A in the range dedicated for gamepads and
|
||||
joysticks. Thus, tablet with a large number of buttons have to map across
|
||||
two semantic ranges, have to use unnamed kernel button codes or risk leaking
|
||||
into an unrelated range. libinput transparently maps the kernel event codes
|
||||
into a sequential button range on the pad. Callers should use external
|
||||
sources like libwacom to associate button numbers to their position on the
|
||||
tablet.
|
||||
|
||||
Some buttons may have expected default behaviors. For example, on Wacom
|
||||
Intuos Pro series tablets, the button inside the touch ring is expected to
|
||||
switch between a mode switch. Mode switching is a feature implemented in the
|
||||
caller and libinput does not provide specific handling. Callers should use
|
||||
external sources like libwacom to identify which buttons have semantic
|
||||
behaviors.
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ libinput_la_SOURCES = \
|
|||
evdev-mt-touchpad-gestures.c \
|
||||
evdev-tablet.c \
|
||||
evdev-tablet.h \
|
||||
evdev-tablet-pad.c \
|
||||
filter.c \
|
||||
filter.h \
|
||||
filter-private.h \
|
||||
|
|
|
|||
620
src/evdev-tablet-pad.c
Normal file
620
src/evdev-tablet-pad.c
Normal file
|
|
@ -0,0 +1,620 @@
|
|||
/*
|
||||
* 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 the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "evdev-tablet-pad.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#define pad_set_status(pad_,s_) (pad_)->status |= (s_)
|
||||
#define pad_unset_status(pad_,s_) (pad_)->status &= ~(s_)
|
||||
#define pad_has_status(pad_,s_) (!!((pad_)->status & (s_)))
|
||||
|
||||
static void
|
||||
pad_get_buttons_pressed(struct pad_dispatch *pad,
|
||||
struct button_state *buttons)
|
||||
{
|
||||
struct button_state *state = &pad->button_state;
|
||||
struct button_state *prev_state = &pad->prev_button_state;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < sizeof(buttons->bits); i++)
|
||||
buttons->bits[i] = state->bits[i] & ~(prev_state->bits[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
pad_get_buttons_released(struct pad_dispatch *pad,
|
||||
struct button_state *buttons)
|
||||
{
|
||||
struct button_state *state = &pad->button_state;
|
||||
struct button_state *prev_state = &pad->prev_button_state;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < sizeof(buttons->bits); i++)
|
||||
buttons->bits[i] = prev_state->bits[i] & ~(state->bits[i]);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pad_button_is_down(const struct pad_dispatch *pad,
|
||||
uint32_t button)
|
||||
{
|
||||
return bit_is_set(pad->button_state.bits, button);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pad_any_button_down(const struct pad_dispatch *pad)
|
||||
{
|
||||
const struct button_state *state = &pad->button_state;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < sizeof(state->bits); i++)
|
||||
if (state->bits[i] != 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void
|
||||
pad_button_set_down(struct pad_dispatch *pad,
|
||||
uint32_t button,
|
||||
bool is_down)
|
||||
{
|
||||
struct button_state *state = &pad->button_state;
|
||||
|
||||
if (is_down) {
|
||||
set_bit(state->bits, button);
|
||||
pad_set_status(pad, PAD_BUTTONS_PRESSED);
|
||||
} else {
|
||||
clear_bit(state->bits, button);
|
||||
pad_set_status(pad, PAD_BUTTONS_RELEASED);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pad_process_absolute(struct pad_dispatch *pad,
|
||||
struct evdev_device *device,
|
||||
struct input_event *e,
|
||||
uint64_t time)
|
||||
{
|
||||
switch (e->code) {
|
||||
case ABS_WHEEL:
|
||||
pad->changed_axes |= PAD_AXIS_RING1;
|
||||
pad_set_status(pad, PAD_AXES_UPDATED);
|
||||
break;
|
||||
case ABS_THROTTLE:
|
||||
pad->changed_axes |= PAD_AXIS_RING2;
|
||||
pad_set_status(pad, PAD_AXES_UPDATED);
|
||||
break;
|
||||
case ABS_RX:
|
||||
pad->changed_axes |= PAD_AXIS_STRIP1;
|
||||
pad_set_status(pad, PAD_AXES_UPDATED);
|
||||
break;
|
||||
case ABS_RY:
|
||||
pad->changed_axes |= PAD_AXIS_STRIP2;
|
||||
pad_set_status(pad, PAD_AXES_UPDATED);
|
||||
break;
|
||||
case ABS_MISC:
|
||||
/* The wacom driver always sends a 0 axis event on finger
|
||||
up, but we also get an ABS_MISC 15 on touch down and
|
||||
ABS_MISC 0 on touch up, on top of the actual event. This
|
||||
is kernel behavior for xf86-input-wacom backwards
|
||||
compatibility after the 3.17 wacom HID move.
|
||||
|
||||
We use that event to tell when we truly went a full
|
||||
rotation around the wheel vs. a finger release.
|
||||
|
||||
FIXME: On the Intuos5 and later the kernel merges all
|
||||
states into that event, so if any finger is down on any
|
||||
button, the wheel release won't trigger the ABS_MISC 0
|
||||
but still send a 0 event. We can't currently detect this.
|
||||
*/
|
||||
pad->have_abs_misc_terminator = true;
|
||||
break;
|
||||
default:
|
||||
log_info(device->base.seat->libinput,
|
||||
"Unhandled EV_ABS event code %#x\n", e->code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline double
|
||||
normalize_ring(const struct input_absinfo *absinfo)
|
||||
{
|
||||
/* libinput has 0 as the ring's northernmost point in the device's
|
||||
current logical rotation, increasing clockwise to 1. Wacom has
|
||||
0 on the left-most wheel position.
|
||||
*/
|
||||
double range = absinfo->maximum - absinfo->minimum + 1;
|
||||
double value = (absinfo->value - absinfo->minimum) / range - 0.25;
|
||||
|
||||
if (value < 0.0)
|
||||
value += 1.0;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline double
|
||||
normalize_strip(const struct input_absinfo *absinfo)
|
||||
{
|
||||
/* strip axes don't use a proper value, they just shift the bit left
|
||||
* for each position. 0 isn't a real value either, it's only sent on
|
||||
* finger release */
|
||||
double min = 0,
|
||||
max = log2(absinfo->maximum);
|
||||
double range = max - min;
|
||||
double value = (log2(absinfo->value) - min) / range;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline double
|
||||
pad_handle_ring(struct pad_dispatch *pad,
|
||||
struct evdev_device *device,
|
||||
unsigned int code)
|
||||
{
|
||||
const struct input_absinfo *absinfo;
|
||||
double degrees;
|
||||
|
||||
absinfo = libevdev_get_abs_info(device->evdev, code);
|
||||
assert(absinfo);
|
||||
|
||||
degrees = normalize_ring(absinfo) * 360;
|
||||
|
||||
if (device->left_handed.enabled)
|
||||
degrees = fmod(degrees + 180, 360);
|
||||
|
||||
return degrees;
|
||||
}
|
||||
|
||||
static inline double
|
||||
pad_handle_strip(struct pad_dispatch *pad,
|
||||
struct evdev_device *device,
|
||||
unsigned int code)
|
||||
{
|
||||
const struct input_absinfo *absinfo;
|
||||
double pos;
|
||||
|
||||
absinfo = libevdev_get_abs_info(device->evdev, code);
|
||||
assert(absinfo);
|
||||
|
||||
if (absinfo->value == 0)
|
||||
return 0.0;
|
||||
|
||||
pos = normalize_strip(absinfo);
|
||||
|
||||
if (device->left_handed.enabled)
|
||||
pos = 1.0 - pos;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static void
|
||||
pad_check_notify_axes(struct pad_dispatch *pad,
|
||||
struct evdev_device *device,
|
||||
uint64_t time)
|
||||
{
|
||||
struct libinput_device *base = &device->base;
|
||||
double value;
|
||||
bool send_finger_up = false;
|
||||
|
||||
/* Suppress the reset to 0 on finger up. See the
|
||||
comment in pad_process_absolute */
|
||||
if (pad->have_abs_misc_terminator &&
|
||||
libevdev_get_event_value(device->evdev, EV_ABS, ABS_MISC) == 0)
|
||||
send_finger_up = true;
|
||||
|
||||
if (pad->changed_axes & PAD_AXIS_RING1) {
|
||||
value = pad_handle_ring(pad, device, ABS_WHEEL);
|
||||
if (send_finger_up)
|
||||
value = -1.0;
|
||||
|
||||
tablet_pad_notify_ring(base,
|
||||
time,
|
||||
0,
|
||||
value,
|
||||
LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER);
|
||||
}
|
||||
|
||||
if (pad->changed_axes & PAD_AXIS_RING2) {
|
||||
value = pad_handle_ring(pad, device, ABS_THROTTLE);
|
||||
if (send_finger_up)
|
||||
value = -1.0;
|
||||
|
||||
tablet_pad_notify_ring(base,
|
||||
time,
|
||||
1,
|
||||
value,
|
||||
LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER);
|
||||
}
|
||||
|
||||
if (pad->changed_axes & PAD_AXIS_STRIP1) {
|
||||
value = pad_handle_strip(pad, device, ABS_RX);
|
||||
if (send_finger_up)
|
||||
value = -1.0;
|
||||
|
||||
tablet_pad_notify_strip(base,
|
||||
time,
|
||||
0,
|
||||
value,
|
||||
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER);
|
||||
}
|
||||
|
||||
if (pad->changed_axes & PAD_AXIS_STRIP2) {
|
||||
value = pad_handle_strip(pad, device, ABS_RY);
|
||||
if (send_finger_up)
|
||||
value = -1.0;
|
||||
|
||||
tablet_pad_notify_strip(base,
|
||||
time,
|
||||
1,
|
||||
value,
|
||||
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER);
|
||||
}
|
||||
|
||||
pad->changed_axes = PAD_AXIS_NONE;
|
||||
pad->have_abs_misc_terminator = false;
|
||||
}
|
||||
|
||||
static void
|
||||
pad_process_key(struct pad_dispatch *pad,
|
||||
struct evdev_device *device,
|
||||
struct input_event *e,
|
||||
uint64_t time)
|
||||
{
|
||||
uint32_t button = e->code;
|
||||
uint32_t is_press = e->value != 0;
|
||||
|
||||
pad_button_set_down(pad, button, is_press);
|
||||
}
|
||||
|
||||
static void
|
||||
pad_notify_button_mask(struct pad_dispatch *pad,
|
||||
struct evdev_device *device,
|
||||
uint64_t time,
|
||||
const struct button_state *buttons,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
struct libinput_device *base = &device->base;
|
||||
int32_t code;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < sizeof(buttons->bits); i++) {
|
||||
unsigned char buttons_slice = buttons->bits[i];
|
||||
|
||||
code = i * 8;
|
||||
while (buttons_slice) {
|
||||
int enabled;
|
||||
char map;
|
||||
|
||||
code++;
|
||||
enabled = (buttons_slice & 1);
|
||||
buttons_slice >>= 1;
|
||||
|
||||
if (!enabled)
|
||||
continue;
|
||||
|
||||
map = pad->button_map[code - 1];
|
||||
if (map != -1)
|
||||
tablet_pad_notify_button(base, time, map, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pad_notify_buttons(struct pad_dispatch *pad,
|
||||
struct evdev_device *device,
|
||||
uint64_t time,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
struct button_state buttons;
|
||||
|
||||
if (state == LIBINPUT_BUTTON_STATE_PRESSED)
|
||||
pad_get_buttons_pressed(pad, &buttons);
|
||||
else
|
||||
pad_get_buttons_released(pad, &buttons);
|
||||
|
||||
pad_notify_button_mask(pad, device, time, &buttons, state);
|
||||
}
|
||||
|
||||
static void
|
||||
pad_change_to_left_handed(struct evdev_device *device)
|
||||
{
|
||||
struct pad_dispatch *pad = (struct pad_dispatch*)device->dispatch;
|
||||
|
||||
if (device->left_handed.enabled == device->left_handed.want_enabled)
|
||||
return;
|
||||
|
||||
if (pad_any_button_down(pad))
|
||||
return;
|
||||
|
||||
device->left_handed.enabled = device->left_handed.want_enabled;
|
||||
}
|
||||
|
||||
static void
|
||||
pad_flush(struct pad_dispatch *pad,
|
||||
struct evdev_device *device,
|
||||
uint64_t time)
|
||||
{
|
||||
if (pad_has_status(pad, PAD_AXES_UPDATED)) {
|
||||
pad_check_notify_axes(pad, device, time);
|
||||
pad_unset_status(pad, PAD_AXES_UPDATED);
|
||||
}
|
||||
|
||||
if (pad_has_status(pad, PAD_BUTTONS_RELEASED)) {
|
||||
pad_notify_buttons(pad,
|
||||
device,
|
||||
time,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
pad_unset_status(pad, PAD_BUTTONS_RELEASED);
|
||||
|
||||
pad_change_to_left_handed(device);
|
||||
}
|
||||
|
||||
if (pad_has_status(pad, PAD_BUTTONS_PRESSED)) {
|
||||
pad_notify_buttons(pad,
|
||||
device,
|
||||
time,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
pad_unset_status(pad, PAD_BUTTONS_PRESSED);
|
||||
}
|
||||
|
||||
/* Update state */
|
||||
memcpy(&pad->prev_button_state,
|
||||
&pad->button_state,
|
||||
sizeof(pad->button_state));
|
||||
}
|
||||
|
||||
static void
|
||||
pad_process(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
struct input_event *e,
|
||||
uint64_t time)
|
||||
{
|
||||
struct pad_dispatch *pad = (struct pad_dispatch *)dispatch;
|
||||
|
||||
switch (e->type) {
|
||||
case EV_ABS:
|
||||
pad_process_absolute(pad, device, e, time);
|
||||
break;
|
||||
case EV_KEY:
|
||||
pad_process_key(pad, device, e, time);
|
||||
break;
|
||||
case EV_SYN:
|
||||
pad_flush(pad, device, time);
|
||||
break;
|
||||
default:
|
||||
log_error(device->base.seat->libinput,
|
||||
"Unexpected event type %s (%#x)\n",
|
||||
libevdev_event_type_get_name(e->type),
|
||||
e->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pad_suspend(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
struct pad_dispatch *pad = (struct pad_dispatch *)dispatch;
|
||||
struct libinput *libinput = device->base.seat->libinput;
|
||||
unsigned int code;
|
||||
|
||||
for (code = KEY_ESC; code < KEY_CNT; code++) {
|
||||
if (pad_button_is_down(pad, code))
|
||||
pad_button_set_down(pad, code, false);
|
||||
}
|
||||
|
||||
pad_flush(pad, device, libinput_now(libinput));
|
||||
}
|
||||
|
||||
static void
|
||||
pad_destroy(struct evdev_dispatch *dispatch)
|
||||
{
|
||||
struct pad_dispatch *pad = (struct pad_dispatch*)dispatch;
|
||||
|
||||
free(pad);
|
||||
}
|
||||
|
||||
static struct evdev_dispatch_interface pad_interface = {
|
||||
pad_process,
|
||||
pad_suspend, /* suspend */
|
||||
NULL, /* remove */
|
||||
pad_destroy,
|
||||
NULL, /* device_added */
|
||||
NULL, /* device_removed */
|
||||
NULL, /* device_suspended */
|
||||
NULL, /* device_resumed */
|
||||
NULL, /* post_added */
|
||||
};
|
||||
|
||||
static void
|
||||
pad_init_buttons(struct pad_dispatch *pad,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
unsigned int code;
|
||||
size_t i;
|
||||
int map = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(pad->button_map); i++)
|
||||
pad->button_map[i] = -1;
|
||||
|
||||
/* we match wacom_report_numbered_buttons() from the kernel */
|
||||
for (code = BTN_0; code < BTN_0 + 10; code++) {
|
||||
if (libevdev_has_event_code(device->evdev, EV_KEY, code))
|
||||
pad->button_map[code] = map++;
|
||||
}
|
||||
|
||||
for (code = BTN_A; code < BTN_A + 6; code++) {
|
||||
if (libevdev_has_event_code(device->evdev, EV_KEY, code))
|
||||
pad->button_map[code] = map++;
|
||||
}
|
||||
|
||||
for (code = BTN_BASE; code < BTN_BASE + 2; code++) {
|
||||
if (libevdev_has_event_code(device->evdev, EV_KEY, code))
|
||||
pad->button_map[code] = map++;
|
||||
}
|
||||
|
||||
pad->nbuttons = map;
|
||||
}
|
||||
|
||||
static void
|
||||
pad_init_left_handed(struct evdev_device *device)
|
||||
{
|
||||
if (evdev_tablet_has_left_handed(device))
|
||||
evdev_init_left_handed(device,
|
||||
pad_change_to_left_handed);
|
||||
}
|
||||
|
||||
static int
|
||||
pad_init(struct pad_dispatch *pad, struct evdev_device *device)
|
||||
{
|
||||
pad->base.interface = &pad_interface;
|
||||
pad->device = device;
|
||||
pad->status = PAD_NONE;
|
||||
pad->changed_axes = PAD_AXIS_NONE;
|
||||
|
||||
pad_init_buttons(pad, device);
|
||||
pad_init_left_handed(device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
pad_sendevents_get_modes(struct libinput_device *device)
|
||||
{
|
||||
return LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
|
||||
}
|
||||
|
||||
static enum libinput_config_status
|
||||
pad_sendevents_set_mode(struct libinput_device *device,
|
||||
enum libinput_config_send_events_mode mode)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
struct pad_dispatch *pad = (struct pad_dispatch*)evdev->dispatch;
|
||||
|
||||
if (mode == pad->sendevents.current_mode)
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
|
||||
switch(mode) {
|
||||
case LIBINPUT_CONFIG_SEND_EVENTS_ENABLED:
|
||||
break;
|
||||
case LIBINPUT_CONFIG_SEND_EVENTS_DISABLED:
|
||||
pad_suspend(evdev->dispatch, evdev);
|
||||
break;
|
||||
default:
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
pad->sendevents.current_mode = mode;
|
||||
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static enum libinput_config_send_events_mode
|
||||
pad_sendevents_get_mode(struct libinput_device *device)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
struct pad_dispatch *dispatch = (struct pad_dispatch*)evdev->dispatch;
|
||||
|
||||
return dispatch->sendevents.current_mode;
|
||||
}
|
||||
|
||||
static enum libinput_config_send_events_mode
|
||||
pad_sendevents_get_default_mode(struct libinput_device *device)
|
||||
{
|
||||
return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
|
||||
}
|
||||
|
||||
struct evdev_dispatch *
|
||||
evdev_tablet_pad_create(struct evdev_device *device)
|
||||
{
|
||||
struct pad_dispatch *pad;
|
||||
|
||||
pad = zalloc(sizeof *pad);
|
||||
if (!pad)
|
||||
return NULL;
|
||||
|
||||
if (pad_init(pad, device) != 0) {
|
||||
pad_destroy(&pad->base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
device->base.config.sendevents = &pad->sendevents.config;
|
||||
pad->sendevents.current_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
|
||||
pad->sendevents.config.get_modes = pad_sendevents_get_modes;
|
||||
pad->sendevents.config.set_mode = pad_sendevents_set_mode;
|
||||
pad->sendevents.config.get_mode = pad_sendevents_get_mode;
|
||||
pad->sendevents.config.get_default_mode = pad_sendevents_get_default_mode;
|
||||
|
||||
return &pad->base;
|
||||
}
|
||||
|
||||
int
|
||||
evdev_device_tablet_pad_get_num_buttons(struct evdev_device *device)
|
||||
{
|
||||
struct pad_dispatch *pad = (struct pad_dispatch*)device->dispatch;
|
||||
|
||||
if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD))
|
||||
return -1;
|
||||
|
||||
return pad->nbuttons;
|
||||
}
|
||||
|
||||
int
|
||||
evdev_device_tablet_pad_get_num_rings(struct evdev_device *device)
|
||||
{
|
||||
int nrings = 0;
|
||||
|
||||
if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD))
|
||||
return -1;
|
||||
|
||||
if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_WHEEL)) {
|
||||
nrings++;
|
||||
if (libevdev_has_event_code(device->evdev,
|
||||
EV_ABS,
|
||||
ABS_THROTTLE))
|
||||
nrings++;
|
||||
}
|
||||
|
||||
return nrings;
|
||||
}
|
||||
|
||||
int
|
||||
evdev_device_tablet_pad_get_num_strips(struct evdev_device *device)
|
||||
{
|
||||
int nstrips = 0;
|
||||
|
||||
if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD))
|
||||
return -1;
|
||||
|
||||
if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_RX)) {
|
||||
nstrips++;
|
||||
if (libevdev_has_event_code(device->evdev,
|
||||
EV_ABS,
|
||||
ABS_RY))
|
||||
nstrips++;
|
||||
}
|
||||
|
||||
return nstrips;
|
||||
}
|
||||
69
src/evdev-tablet-pad.h
Normal file
69
src/evdev-tablet-pad.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright © 2015 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef EVDEV_BUTTONSET_WACOM_H
|
||||
#define EVDEV_BUTTONSET_WACOM_H
|
||||
|
||||
#include "evdev.h"
|
||||
|
||||
#define LIBINPUT_BUTTONSET_AXIS_NONE 0
|
||||
|
||||
enum pad_status {
|
||||
PAD_NONE = 0,
|
||||
PAD_AXES_UPDATED = 1 << 0,
|
||||
PAD_BUTTONS_PRESSED = 1 << 1,
|
||||
PAD_BUTTONS_RELEASED = 1 << 2,
|
||||
};
|
||||
|
||||
enum pad_axes {
|
||||
PAD_AXIS_NONE = 0,
|
||||
PAD_AXIS_RING1 = 1 << 0,
|
||||
PAD_AXIS_RING2 = 1 << 1,
|
||||
PAD_AXIS_STRIP1 = 1 << 2,
|
||||
PAD_AXIS_STRIP2 = 1 << 3,
|
||||
};
|
||||
|
||||
struct button_state {
|
||||
unsigned char bits[NCHARS(KEY_CNT)];
|
||||
};
|
||||
|
||||
struct pad_dispatch {
|
||||
struct evdev_dispatch base;
|
||||
struct evdev_device *device;
|
||||
unsigned char status;
|
||||
uint32_t changed_axes;
|
||||
|
||||
struct button_state button_state;
|
||||
struct button_state prev_button_state;
|
||||
|
||||
char button_map[KEY_CNT];
|
||||
unsigned int nbuttons;
|
||||
|
||||
bool have_abs_misc_terminator;
|
||||
|
||||
struct {
|
||||
struct libinput_device_config_send_events config;
|
||||
enum libinput_config_send_events_mode current_mode;
|
||||
} sendevents;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1606,45 +1606,9 @@ tablet_init_accel(struct tablet_dispatch *tablet, struct evdev_device *device)
|
|||
static void
|
||||
tablet_init_left_handed(struct evdev_device *device)
|
||||
{
|
||||
#if HAVE_LIBWACOM
|
||||
struct libinput *libinput = device->base.seat->libinput;
|
||||
WacomDeviceDatabase *db;
|
||||
WacomDevice *d = NULL;
|
||||
WacomError *error;
|
||||
const char *devnode;
|
||||
|
||||
db = libwacom_database_new();
|
||||
if (!db) {
|
||||
log_info(libinput,
|
||||
"Failed to initialize libwacom context.\n");
|
||||
return;
|
||||
}
|
||||
error = libwacom_error_new();
|
||||
devnode = udev_device_get_devnode(device->udev_device);
|
||||
|
||||
d = libwacom_new_from_path(db,
|
||||
devnode,
|
||||
WFALLBACK_NONE,
|
||||
error);
|
||||
|
||||
if (d) {
|
||||
if (libwacom_is_reversible(d))
|
||||
if (evdev_tablet_has_left_handed(device))
|
||||
evdev_init_left_handed(device,
|
||||
tablet_change_to_left_handed);
|
||||
} else if (libwacom_error_get_code(error) == WERROR_UNKNOWN_MODEL) {
|
||||
log_info(libinput, "Tablet unknown to libwacom\n");
|
||||
} else {
|
||||
log_error(libinput,
|
||||
"libwacom error: %s\n",
|
||||
libwacom_error_get_message(error));
|
||||
}
|
||||
|
||||
if (error)
|
||||
libwacom_error_free(&error);
|
||||
if (d)
|
||||
libwacom_destroy(d);
|
||||
libwacom_database_destroy(db);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
80
src/evdev.c
80
src/evdev.c
|
|
@ -43,6 +43,10 @@
|
|||
#include "filter.h"
|
||||
#include "libinput-private.h"
|
||||
|
||||
#if HAVE_LIBWACOM
|
||||
#include <libwacom/libwacom.h>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_WHEEL_CLICK_ANGLE 15
|
||||
#define DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT ms2us(200)
|
||||
|
||||
|
|
@ -61,7 +65,7 @@ enum evdev_device_udev_tags {
|
|||
EVDEV_UDEV_TAG_TABLET = (1 << 5),
|
||||
EVDEV_UDEV_TAG_JOYSTICK = (1 << 6),
|
||||
EVDEV_UDEV_TAG_ACCELEROMETER = (1 << 7),
|
||||
EVDEV_UDEV_TAG_BUTTONSET = (1 << 8),
|
||||
EVDEV_UDEV_TAG_TABLET_PAD = (1 << 8),
|
||||
EVDEV_UDEV_TAG_POINTINGSTICK = (1 << 9),
|
||||
};
|
||||
|
||||
|
|
@ -78,7 +82,7 @@ static const struct evdev_udev_tag_match evdev_udev_tag_matches[] = {
|
|||
{"ID_INPUT_TOUCHPAD", EVDEV_UDEV_TAG_TOUCHPAD},
|
||||
{"ID_INPUT_TOUCHSCREEN", EVDEV_UDEV_TAG_TOUCHSCREEN},
|
||||
{"ID_INPUT_TABLET", EVDEV_UDEV_TAG_TABLET},
|
||||
{"ID_INPUT_TABLET_PAD", EVDEV_UDEV_TAG_BUTTONSET},
|
||||
{"ID_INPUT_TABLET_PAD", EVDEV_UDEV_TAG_TABLET_PAD},
|
||||
{"ID_INPUT_JOYSTICK", EVDEV_UDEV_TAG_JOYSTICK},
|
||||
{"ID_INPUT_ACCELEROMETER", EVDEV_UDEV_TAG_ACCELEROMETER},
|
||||
{"ID_INPUT_POINTINGSTICK", EVDEV_UDEV_TAG_POINTINGSTICK},
|
||||
|
|
@ -2082,7 +2086,7 @@ evdev_configure_device(struct evdev_device *device)
|
|||
udev_tags & EVDEV_UDEV_TAG_POINTINGSTICK ? " Pointingstick" : "",
|
||||
udev_tags & EVDEV_UDEV_TAG_JOYSTICK ? " Joystick" : "",
|
||||
udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER ? " Accelerometer" : "",
|
||||
udev_tags & EVDEV_UDEV_TAG_BUTTONSET ? " Buttonset" : "");
|
||||
udev_tags & EVDEV_UDEV_TAG_TABLET_PAD ? " TabletPad" : "");
|
||||
|
||||
if (udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER) {
|
||||
log_info(libinput,
|
||||
|
|
@ -2100,14 +2104,6 @@ evdev_configure_device(struct evdev_device *device)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* libwacom assigns tablet _and_ tablet_pad to the pad devices */
|
||||
if (udev_tags & EVDEV_UDEV_TAG_BUTTONSET) {
|
||||
log_info(libinput,
|
||||
"input device '%s', %s is a buttonset, ignoring\n",
|
||||
device->devname, devnode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (evdev_reject_device(device) == -1) {
|
||||
log_info(libinput,
|
||||
"input device '%s', %s was rejected.\n",
|
||||
|
|
@ -2143,7 +2139,17 @@ evdev_configure_device(struct evdev_device *device)
|
|||
tablet_tags = EVDEV_UDEV_TAG_TABLET |
|
||||
EVDEV_UDEV_TAG_TOUCHPAD |
|
||||
EVDEV_UDEV_TAG_TOUCHSCREEN;
|
||||
if ((udev_tags & tablet_tags) == EVDEV_UDEV_TAG_TABLET) {
|
||||
|
||||
/* libwacom assigns tablet _and_ tablet_pad to the pad devices */
|
||||
if (udev_tags & EVDEV_UDEV_TAG_TABLET_PAD) {
|
||||
device->dispatch = evdev_tablet_pad_create(device);
|
||||
device->seat_caps |= EVDEV_DEVICE_TABLET_PAD;
|
||||
log_info(libinput,
|
||||
"input device '%s', %s is a tablet pad\n",
|
||||
device->devname, devnode);
|
||||
return device->dispatch == NULL ? -1 : 0;
|
||||
|
||||
} else if ((udev_tags & tablet_tags) == EVDEV_UDEV_TAG_TABLET) {
|
||||
device->dispatch = evdev_tablet_create(device);
|
||||
device->seat_caps |= EVDEV_DEVICE_TABLET;
|
||||
log_info(libinput,
|
||||
|
|
@ -2572,6 +2578,8 @@ evdev_device_has_capability(struct evdev_device *device,
|
|||
return !!(device->seat_caps & EVDEV_DEVICE_GESTURE);
|
||||
case LIBINPUT_DEVICE_CAP_TABLET_TOOL:
|
||||
return !!(device->seat_caps & EVDEV_DEVICE_TABLET);
|
||||
case LIBINPUT_DEVICE_CAP_TABLET_PAD:
|
||||
return !!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2913,3 +2921,51 @@ evdev_device_destroy(struct evdev_device *device)
|
|||
free(device->mt.slots);
|
||||
free(device);
|
||||
}
|
||||
|
||||
bool
|
||||
evdev_tablet_has_left_handed(struct evdev_device *device)
|
||||
{
|
||||
bool has_left_handed = false;
|
||||
#if HAVE_LIBWACOM
|
||||
struct libinput *libinput = device->base.seat->libinput;
|
||||
WacomDeviceDatabase *db;
|
||||
WacomDevice *d = NULL;
|
||||
WacomError *error;
|
||||
const char *devnode;
|
||||
|
||||
db = libwacom_database_new();
|
||||
if (!db) {
|
||||
log_info(libinput,
|
||||
"Failed to initialize libwacom context.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = libwacom_error_new();
|
||||
devnode = udev_device_get_devnode(device->udev_device);
|
||||
|
||||
d = libwacom_new_from_path(db,
|
||||
devnode,
|
||||
WFALLBACK_NONE,
|
||||
error);
|
||||
|
||||
if (d) {
|
||||
if (libwacom_is_reversible(d))
|
||||
has_left_handed = true;
|
||||
} else if (libwacom_error_get_code(error) == WERROR_UNKNOWN_MODEL) {
|
||||
log_info(libinput, "Tablet unknown to libwacom\n");
|
||||
} else {
|
||||
log_error(libinput,
|
||||
"libwacom error: %s\n",
|
||||
libwacom_error_get_message(error));
|
||||
}
|
||||
|
||||
if (error)
|
||||
libwacom_error_free(&error);
|
||||
if (d)
|
||||
libwacom_destroy(d);
|
||||
libwacom_database_destroy(db);
|
||||
|
||||
out:
|
||||
#endif
|
||||
return has_left_handed;
|
||||
}
|
||||
|
|
|
|||
16
src/evdev.h
16
src/evdev.h
|
|
@ -61,6 +61,7 @@ enum evdev_device_seat_capability {
|
|||
EVDEV_DEVICE_KEYBOARD = (1 << 1),
|
||||
EVDEV_DEVICE_TOUCH = (1 << 2),
|
||||
EVDEV_DEVICE_TABLET = (1 << 3),
|
||||
EVDEV_DEVICE_TABLET_PAD = (1 << 4),
|
||||
EVDEV_DEVICE_GESTURE = (1 << 5),
|
||||
};
|
||||
|
||||
|
|
@ -322,6 +323,9 @@ evdev_mt_touchpad_create(struct evdev_device *device);
|
|||
struct evdev_dispatch *
|
||||
evdev_tablet_create(struct evdev_device *device);
|
||||
|
||||
struct evdev_dispatch *
|
||||
evdev_tablet_pad_create(struct evdev_device *device);
|
||||
|
||||
void
|
||||
evdev_tag_touchpad(struct evdev_device *device,
|
||||
struct udev_device *udev_device);
|
||||
|
|
@ -372,6 +376,15 @@ evdev_device_has_button(struct evdev_device *device, uint32_t code);
|
|||
int
|
||||
evdev_device_has_key(struct evdev_device *device, uint32_t code);
|
||||
|
||||
int
|
||||
evdev_device_tablet_pad_get_num_buttons(struct evdev_device *device);
|
||||
|
||||
int
|
||||
evdev_device_tablet_pad_get_num_rings(struct evdev_device *device);
|
||||
|
||||
int
|
||||
evdev_device_tablet_pad_get_num_strips(struct evdev_device *device);
|
||||
|
||||
double
|
||||
evdev_device_transform_x(struct evdev_device *device,
|
||||
double x,
|
||||
|
|
@ -459,6 +472,9 @@ int
|
|||
evdev_init_left_handed(struct evdev_device *device,
|
||||
void (*change_to_left_handed)(struct evdev_device *));
|
||||
|
||||
bool
|
||||
evdev_tablet_has_left_handed(struct evdev_device *device);
|
||||
|
||||
static inline uint32_t
|
||||
evdev_to_left_handed(struct evdev_device *device,
|
||||
uint32_t button)
|
||||
|
|
|
|||
|
|
@ -544,6 +544,24 @@ tablet_notify_button(struct libinput_device *device,
|
|||
int32_t button,
|
||||
enum libinput_button_state state);
|
||||
|
||||
void
|
||||
tablet_pad_notify_button(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
int32_t button,
|
||||
enum libinput_button_state state);
|
||||
void
|
||||
tablet_pad_notify_ring(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
unsigned int number,
|
||||
double value,
|
||||
enum libinput_tablet_pad_ring_axis_source source);
|
||||
void
|
||||
tablet_pad_notify_strip(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
unsigned int number,
|
||||
double value,
|
||||
enum libinput_tablet_pad_strip_axis_source source);
|
||||
|
||||
static inline uint64_t
|
||||
libinput_now(struct libinput *libinput)
|
||||
{
|
||||
|
|
|
|||
257
src/libinput.c
257
src/libinput.c
|
|
@ -138,6 +138,23 @@ struct libinput_event_tablet_tool {
|
|||
enum libinput_tablet_tool_tip_state tip_state;
|
||||
};
|
||||
|
||||
struct libinput_event_tablet_pad {
|
||||
struct libinput_event base;
|
||||
uint32_t button;
|
||||
enum libinput_button_state state;
|
||||
uint64_t time;
|
||||
struct {
|
||||
enum libinput_tablet_pad_ring_axis_source source;
|
||||
double position;
|
||||
int number;
|
||||
} ring;
|
||||
struct {
|
||||
enum libinput_tablet_pad_strip_axis_source source;
|
||||
double position;
|
||||
int number;
|
||||
} strip;
|
||||
};
|
||||
|
||||
static void
|
||||
libinput_default_log_func(struct libinput *libinput,
|
||||
enum libinput_log_priority priority,
|
||||
|
|
@ -318,6 +335,19 @@ libinput_event_get_tablet_tool_event(struct libinput_event *event)
|
|||
return (struct libinput_event_tablet_tool *) event;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_event_tablet_pad *
|
||||
libinput_event_get_tablet_pad_event(struct libinput_event *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(event),
|
||||
event->type,
|
||||
NULL,
|
||||
LIBINPUT_EVENT_TABLET_PAD_RING,
|
||||
LIBINPUT_EVENT_TABLET_PAD_STRIP,
|
||||
LIBINPUT_EVENT_TABLET_PAD_BUTTON);
|
||||
|
||||
return (struct libinput_event_tablet_pad *) event;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_event_device_notify *
|
||||
libinput_event_get_device_notify_event(struct libinput_event *event)
|
||||
{
|
||||
|
|
@ -1956,6 +1986,9 @@ device_has_cap(struct libinput_device *device,
|
|||
case LIBINPUT_DEVICE_CAP_TABLET_TOOL:
|
||||
capability = "CAP_TABLET_TOOL";
|
||||
break;
|
||||
case LIBINPUT_DEVICE_CAP_TABLET_PAD:
|
||||
capability = "CAP_TABLET_PAD";
|
||||
break;
|
||||
}
|
||||
|
||||
log_bug_libinput(device->seat->libinput,
|
||||
|
|
@ -2343,6 +2376,82 @@ tablet_notify_button(struct libinput_device *device,
|
|||
&button_event->base);
|
||||
}
|
||||
|
||||
void
|
||||
tablet_pad_notify_button(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
int32_t button,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
struct libinput_event_tablet_pad *button_event;
|
||||
|
||||
button_event = zalloc(sizeof *button_event);
|
||||
if (!button_event)
|
||||
return;
|
||||
|
||||
*button_event = (struct libinput_event_tablet_pad) {
|
||||
.time = time,
|
||||
.button = button,
|
||||
.state = state,
|
||||
};
|
||||
|
||||
post_device_event(device,
|
||||
time,
|
||||
LIBINPUT_EVENT_TABLET_PAD_BUTTON,
|
||||
&button_event->base);
|
||||
}
|
||||
|
||||
void
|
||||
tablet_pad_notify_ring(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
unsigned int number,
|
||||
double value,
|
||||
enum libinput_tablet_pad_ring_axis_source source)
|
||||
{
|
||||
struct libinput_event_tablet_pad *ring_event;
|
||||
|
||||
ring_event = zalloc(sizeof *ring_event);
|
||||
if (!ring_event)
|
||||
return;
|
||||
|
||||
*ring_event = (struct libinput_event_tablet_pad) {
|
||||
.time = time,
|
||||
.ring.number = number,
|
||||
.ring.position = value,
|
||||
.ring.source = source,
|
||||
};
|
||||
|
||||
post_device_event(device,
|
||||
time,
|
||||
LIBINPUT_EVENT_TABLET_PAD_RING,
|
||||
&ring_event->base);
|
||||
}
|
||||
|
||||
void
|
||||
tablet_pad_notify_strip(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
unsigned int number,
|
||||
double value,
|
||||
enum libinput_tablet_pad_strip_axis_source source)
|
||||
{
|
||||
struct libinput_event_tablet_pad *strip_event;
|
||||
|
||||
strip_event = zalloc(sizeof *strip_event);
|
||||
if (!strip_event)
|
||||
return;
|
||||
|
||||
*strip_event = (struct libinput_event_tablet_pad) {
|
||||
.time = time,
|
||||
.strip.number = number,
|
||||
.strip.position = value,
|
||||
.strip.source = source,
|
||||
};
|
||||
|
||||
post_device_event(device,
|
||||
time,
|
||||
LIBINPUT_EVENT_TABLET_PAD_STRIP,
|
||||
&strip_event->base);
|
||||
}
|
||||
|
||||
static void
|
||||
gesture_notify(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
|
|
@ -2448,6 +2557,9 @@ event_type_to_str(enum libinput_event_type type)
|
|||
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
|
||||
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_TIP);
|
||||
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
|
||||
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_BUTTON);
|
||||
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_RING);
|
||||
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_STRIP);
|
||||
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN);
|
||||
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE);
|
||||
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_END);
|
||||
|
|
@ -2679,6 +2791,24 @@ libinput_device_keyboard_has_key(struct libinput_device *device, uint32_t code)
|
|||
return evdev_device_has_key((struct evdev_device *)device, code);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_tablet_pad_get_num_buttons(struct libinput_device *device)
|
||||
{
|
||||
return evdev_device_tablet_pad_get_num_buttons((struct evdev_device *)device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_tablet_pad_get_num_rings(struct libinput_device *device)
|
||||
{
|
||||
return evdev_device_tablet_pad_get_num_rings((struct evdev_device *)device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_tablet_pad_get_num_strips(struct libinput_device *device)
|
||||
{
|
||||
return evdev_device_tablet_pad_get_num_strips((struct evdev_device *)device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_event *
|
||||
libinput_event_device_notify_get_base_event(struct libinput_event_device_notify *event)
|
||||
{
|
||||
|
|
@ -2751,6 +2881,133 @@ libinput_event_tablet_tool_get_base_event(struct libinput_event_tablet_tool *eve
|
|||
return &event->base;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
libinput_event_tablet_pad_get_ring_position(struct libinput_event_tablet_pad *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0.0,
|
||||
LIBINPUT_EVENT_TABLET_PAD_RING);
|
||||
|
||||
return event->ring.position;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT unsigned int
|
||||
libinput_event_tablet_pad_get_ring_number(struct libinput_event_tablet_pad *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_TABLET_PAD_RING);
|
||||
|
||||
return event->ring.number;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_tablet_pad_ring_axis_source
|
||||
libinput_event_tablet_pad_get_ring_source(struct libinput_event_tablet_pad *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN,
|
||||
LIBINPUT_EVENT_TABLET_PAD_RING);
|
||||
|
||||
return event->ring.source;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
libinput_event_tablet_pad_get_strip_position(struct libinput_event_tablet_pad *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0.0,
|
||||
LIBINPUT_EVENT_TABLET_PAD_STRIP);
|
||||
|
||||
return event->strip.position;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT unsigned int
|
||||
libinput_event_tablet_pad_get_strip_number(struct libinput_event_tablet_pad *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_TABLET_PAD_STRIP);
|
||||
|
||||
return event->strip.number;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_tablet_pad_strip_axis_source
|
||||
libinput_event_tablet_pad_get_strip_source(struct libinput_event_tablet_pad *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN,
|
||||
LIBINPUT_EVENT_TABLET_PAD_STRIP);
|
||||
|
||||
return event->strip.source;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_event_tablet_pad_get_button_number(struct libinput_event_tablet_pad *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_TABLET_PAD_BUTTON);
|
||||
|
||||
return event->button;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_button_state
|
||||
libinput_event_tablet_pad_get_button_state(struct libinput_event_tablet_pad *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED,
|
||||
LIBINPUT_EVENT_TABLET_PAD_BUTTON);
|
||||
|
||||
return event->state;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_event_tablet_pad_get_time(struct libinput_event_tablet_pad *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_TABLET_PAD_RING,
|
||||
LIBINPUT_EVENT_TABLET_PAD_STRIP,
|
||||
LIBINPUT_EVENT_TABLET_PAD_BUTTON);
|
||||
|
||||
return us2ms(event->time);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint64_t
|
||||
libinput_event_tablet_pad_get_time_usec(struct libinput_event_tablet_pad *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
0,
|
||||
LIBINPUT_EVENT_TABLET_PAD_RING,
|
||||
LIBINPUT_EVENT_TABLET_PAD_STRIP,
|
||||
LIBINPUT_EVENT_TABLET_PAD_BUTTON);
|
||||
|
||||
return event->time;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_event *
|
||||
libinput_event_tablet_pad_get_base_event(struct libinput_event_tablet_pad *event)
|
||||
{
|
||||
require_event_type(libinput_event_get_context(&event->base),
|
||||
event->base.type,
|
||||
NULL,
|
||||
LIBINPUT_EVENT_TABLET_PAD_RING,
|
||||
LIBINPUT_EVENT_TABLET_PAD_STRIP,
|
||||
LIBINPUT_EVENT_TABLET_PAD_BUTTON);
|
||||
|
||||
return &event->base;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_device_group *
|
||||
libinput_device_group_ref(struct libinput_device_group *group)
|
||||
{
|
||||
|
|
|
|||
313
src/libinput.h
313
src/libinput.h
|
|
@ -59,6 +59,7 @@ enum libinput_device_capability {
|
|||
LIBINPUT_DEVICE_CAP_POINTER = 1,
|
||||
LIBINPUT_DEVICE_CAP_TOUCH = 2,
|
||||
LIBINPUT_DEVICE_CAP_TABLET_TOOL = 3,
|
||||
LIBINPUT_DEVICE_CAP_TABLET_PAD = 4,
|
||||
LIBINPUT_DEVICE_CAP_GESTURE = 5,
|
||||
};
|
||||
|
||||
|
|
@ -134,6 +135,36 @@ enum libinput_pointer_axis_source {
|
|||
LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS,
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* The source for a @ref LIBINPUT_EVENT_TABLET_PAD_RING event. See
|
||||
* libinput_event_tablet_pad_get_ring_source() for details.
|
||||
*/
|
||||
enum libinput_tablet_pad_ring_axis_source {
|
||||
LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN = 1,
|
||||
/**
|
||||
* The event is caused by the movement of one or more fingers on
|
||||
* the ring.
|
||||
*/
|
||||
LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER,
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* The source for a @ref LIBINPUT_EVENT_TABLET_PAD_STRIP event. See
|
||||
* libinput_event_tablet_pad_get_strip_source() for details.
|
||||
*/
|
||||
enum libinput_tablet_pad_strip_axis_source {
|
||||
LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN = 1,
|
||||
/**
|
||||
* The event is caused by the movement of one or more fingers on
|
||||
* the strip.
|
||||
*/
|
||||
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER,
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
* @struct libinput_tablet_tool
|
||||
|
|
@ -336,9 +367,34 @@ enum libinput_event_type {
|
|||
* same logical hardware event, the order of the @ref
|
||||
* LIBINPUT_EVENT_TABLET_TOOL_BUTTON and @ref
|
||||
* LIBINPUT_EVENT_TABLET_TOOL_AXIS event is device-specific.
|
||||
*
|
||||
* This event is not to be confused with the button events emitted
|
||||
* by the tablet pad. See @ref LIBINPUT_EVENT_TABLET_PAD_BUTTON.
|
||||
*
|
||||
* @see LIBINPUT_EVENT_TABLET_BUTTON
|
||||
*/
|
||||
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
|
||||
|
||||
/**
|
||||
* A button pressed on a device with the @ref
|
||||
* LIBINPUT_DEVICE_CAP_TABLET_PAD capability.
|
||||
*
|
||||
* This event is not to be confused with the button events emitted
|
||||
* by tools on a tablet. See @ref LIBINPUT_EVENT_TABLET_TOOL_BUTTON.
|
||||
*/
|
||||
LIBINPUT_EVENT_TABLET_PAD_BUTTON = 700,
|
||||
/**
|
||||
* A status change on a tablet ring with the
|
||||
* LIBINPUT_DEVICE_CAP_TABLET_PAD capability.
|
||||
*/
|
||||
LIBINPUT_EVENT_TABLET_PAD_RING,
|
||||
|
||||
/**
|
||||
* A status change on a strip on a device with the @ref
|
||||
* LIBINPUT_DEVICE_CAP_TABLET_PAD capability.
|
||||
*/
|
||||
LIBINPUT_EVENT_TABLET_PAD_STRIP,
|
||||
|
||||
LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN = 800,
|
||||
LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
|
||||
LIBINPUT_EVENT_GESTURE_SWIPE_END,
|
||||
|
|
@ -445,6 +501,17 @@ struct libinput_event_touch;
|
|||
*/
|
||||
struct libinput_event_tablet_tool;
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
* @struct libinput_event_tablet_pad
|
||||
*
|
||||
* Tablet pad event representing a button press, or ring/strip update on
|
||||
* the tablet pad itself. Valid event types for this event are @ref
|
||||
* LIBINPUT_EVENT_TABLET_PAD_BUTTON, @ref LIBINPUT_EVENT_TABLET_PAD_RING and
|
||||
* @ref LIBINPUT_EVENT_TABLET_PAD_STRIP.
|
||||
*/
|
||||
struct libinput_event_tablet_pad;
|
||||
|
||||
/**
|
||||
* @defgroup event Accessing and destruction of events
|
||||
*/
|
||||
|
|
@ -566,6 +633,19 @@ libinput_event_get_gesture_event(struct libinput_event *event);
|
|||
struct libinput_event_tablet_tool *
|
||||
libinput_event_get_tablet_tool_event(struct libinput_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup event
|
||||
*
|
||||
* Return the tablet pad event that is this input event. If the event type does not
|
||||
* match the tablet pad event types, this function returns NULL.
|
||||
*
|
||||
* The inverse of this function is libinput_event_tablet_pad_get_base_event().
|
||||
*
|
||||
* @return A tablet pad event, or NULL for other events
|
||||
*/
|
||||
struct libinput_event_tablet_pad *
|
||||
libinput_event_get_tablet_pad_event(struct libinput_event *event);
|
||||
|
||||
/**
|
||||
* @ingroup event
|
||||
*
|
||||
|
|
@ -1357,7 +1437,17 @@ libinput_event_gesture_get_angle_delta(struct libinput_event_gesture *event);
|
|||
/**
|
||||
* @defgroup event_tablet Tablet events
|
||||
*
|
||||
* Events that come from tools on tablet devices.
|
||||
* Events that come from tools on or the pad of tablet devices.
|
||||
*
|
||||
* Events from tablet devices are exposed by two interfaces, tools and pads.
|
||||
* Tool events originate (usually) from a stylus-like device, pad events
|
||||
* reflect any events originating from the physical tablet itself.
|
||||
*
|
||||
* Note that many tablets support touch events. These are exposed through
|
||||
* the @ref LIBINPUT_DEVICE_CAP_POINTER interface (for external touchpad-like
|
||||
* devices such as the Wacom Intuos series) or @ref
|
||||
* LIBINPUT_DEVICE_CAP_TOUCH interface (for built-in touchscreen-like
|
||||
* devices such as the Wacom Cintiq series).
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -2105,6 +2195,182 @@ void
|
|||
libinput_tablet_tool_set_user_data(struct libinput_tablet_tool *tool,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* @return The generic libinput_event of this event
|
||||
*/
|
||||
struct libinput_event *
|
||||
libinput_event_tablet_pad_get_base_event(struct libinput_event_tablet_pad *event);
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* Returns the current position of the ring, in degrees counterclockwise
|
||||
* from the northern-most point of the ring in the tablet's current logical
|
||||
* orientation.
|
||||
*
|
||||
* If the source is @ref LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER,
|
||||
* libinput sends a terminating event with a ring value of -1 when the
|
||||
* finger is lifted from the ring. A caller may use this information to e.g.
|
||||
* determine if kinetic scrolling should be triggered.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* @ref LIBINPUT_EVENT_TABLET_PAD_RING. For other events, this function
|
||||
* returns 0.
|
||||
*
|
||||
* @param event The libinput tablet pad event
|
||||
* @return The current value of the the axis
|
||||
* @retval -1 The finger was lifted
|
||||
*/
|
||||
double
|
||||
libinput_event_tablet_pad_get_ring_position(struct libinput_event_tablet_pad *event);
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* Returns the number of the ring that has changed state, with 0 being the
|
||||
* first ring. On tablets with only one ring, this function always returns
|
||||
* 0.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* @ref LIBINPUT_EVENT_TABLET_PAD_RING. For other events, this function
|
||||
* returns 0.
|
||||
*
|
||||
* @param event The libinput tablet pad event
|
||||
* @return The index of the ring that changed state
|
||||
*/
|
||||
unsigned int
|
||||
libinput_event_tablet_pad_get_ring_number(struct libinput_event_tablet_pad *event);
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* Returns the source of the interaction with the ring. If the source is
|
||||
* @ref LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER, libinput sends a ring
|
||||
* position value of -1 to terminate the current interaction.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* @ref LIBINPUT_EVENT_TABLET_PAD_RING. For other events, this function
|
||||
* returns 0.
|
||||
*
|
||||
* @param event The libinput tablet pad event
|
||||
* @return The source of the ring interaction
|
||||
*/
|
||||
enum libinput_tablet_pad_ring_axis_source
|
||||
libinput_event_tablet_pad_get_ring_source(struct libinput_event_tablet_pad *event);
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* Returns the current position of the strip, normalized to the range
|
||||
* [0, 1], with 0 being the top/left-most point in the tablet's current
|
||||
* logical orientation.
|
||||
*
|
||||
* If the source is @ref LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER,
|
||||
* libinput sends a terminating event with a ring value of -1 when the
|
||||
* finger is lifted from the ring. A caller may use this information to e.g.
|
||||
* determine if kinetic scrolling should be triggered.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* @ref LIBINPUT_EVENT_TABLET_PAD_STRIP. For other events, this function
|
||||
* returns 0.
|
||||
*
|
||||
* @param event The libinput tablet pad event
|
||||
* @return The current value of the the axis
|
||||
* @retval -1 The finger was lifted
|
||||
*/
|
||||
double
|
||||
libinput_event_tablet_pad_get_strip_position(struct libinput_event_tablet_pad *event);
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* Returns the number of the strip that has changed state, with 0 being the
|
||||
* first strip. On tablets with only one strip, this function always returns
|
||||
* 0.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* @ref LIBINPUT_EVENT_TABLET_PAD_STRIP. For other events, this function
|
||||
* returns 0.
|
||||
*
|
||||
* @param event The libinput tablet pad event
|
||||
* @return The index of the strip that changed state
|
||||
*/
|
||||
unsigned int
|
||||
libinput_event_tablet_pad_get_strip_number(struct libinput_event_tablet_pad *event);
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* Returns the source of the interaction with the strip. If the source is
|
||||
* @ref LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER, libinput sends a strip
|
||||
* position value of -1 to terminate the current interaction.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* @ref LIBINPUT_EVENT_TABLET_PAD_STRIP. For other events, this function
|
||||
* returns 0.
|
||||
*
|
||||
* @param event The libinput tablet pad event
|
||||
* @return The source of the strip interaction
|
||||
*/
|
||||
enum libinput_tablet_pad_strip_axis_source
|
||||
libinput_event_tablet_pad_get_strip_source(struct libinput_event_tablet_pad *event);
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* Return the button number that triggered this event, starting at 0.
|
||||
* For events that are not of type @ref LIBINPUT_EVENT_TABLET_PAD_BUTTON,
|
||||
* this function returns 0.
|
||||
*
|
||||
* Note that the number returned is a generic sequential button number and
|
||||
* not a semantic button code as defined in linux/input.h.
|
||||
* See @ref tablet-pad-buttons for more details.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* @ref LIBINPUT_EVENT_TABLET_PAD_BUTTON. For other events, this function
|
||||
* returns 0.
|
||||
*
|
||||
* @param event The libinput tablet pad event
|
||||
* @return the button triggering this event
|
||||
*/
|
||||
uint32_t
|
||||
libinput_event_tablet_pad_get_button_number(struct libinput_event_tablet_pad *event);
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* Return the button state of the event.
|
||||
*
|
||||
* @note It is an application bug to call this function for events other than
|
||||
* @ref LIBINPUT_EVENT_TABLET_PAD_BUTTON. For other events, this function
|
||||
* returns 0.
|
||||
*
|
||||
* @param event The libinput tablet pad event
|
||||
* @return the button state triggering this event
|
||||
*/
|
||||
enum libinput_button_state
|
||||
libinput_event_tablet_pad_get_button_state(struct libinput_event_tablet_pad *event);
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* @param event The libinput tablet pad event
|
||||
* @return The event time for this event
|
||||
*/
|
||||
uint32_t
|
||||
libinput_event_tablet_pad_get_time(struct libinput_event_tablet_pad *event);
|
||||
|
||||
/**
|
||||
* @ingroup event_tablet
|
||||
*
|
||||
* @param event The libinput tablet pad event
|
||||
* @return The event time for this event in microseconds
|
||||
*/
|
||||
uint64_t
|
||||
libinput_event_tablet_pad_get_time_usec(struct libinput_event_tablet_pad *event);
|
||||
|
||||
/**
|
||||
* @defgroup base Initialization and manipulation of libinput contexts
|
||||
*/
|
||||
|
|
@ -2931,6 +3197,51 @@ int
|
|||
libinput_device_keyboard_has_key(struct libinput_device *device,
|
||||
uint32_t code);
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
*
|
||||
* Return the number of buttons on a device with the
|
||||
* @ref LIBINPUT_DEVICE_CAP_TABLET_PAD capability.
|
||||
* Buttons on a pad device are numbered sequentially, see @ref
|
||||
* tablet-pad-buttons for details.
|
||||
*
|
||||
* @param device A current input device
|
||||
*
|
||||
* @return The number of buttons supported by the device.
|
||||
*/
|
||||
int
|
||||
libinput_device_tablet_pad_get_num_buttons(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
*
|
||||
* Return the number of rings a device with the @ref
|
||||
* LIBINPUT_DEVICE_CAP_TABLET_PAD capability provides.
|
||||
*
|
||||
* @param device A current input device
|
||||
*
|
||||
* @return The number of rings or 0 if the device has no rings.
|
||||
*
|
||||
* @see libinput_event_tablet_pad_get_ring_number
|
||||
*/
|
||||
int
|
||||
libinput_device_tablet_pad_get_num_rings(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
*
|
||||
* Return the number of strips a device with the @ref
|
||||
* LIBINPUT_DEVICE_CAP_TABLET_PAD capability provides.
|
||||
*
|
||||
* @param device A current input device
|
||||
*
|
||||
* @return The number of strips or 0 if the device has no strips.
|
||||
*
|
||||
* @see libinput_event_tablet_pad_get_strip_number
|
||||
*/
|
||||
int
|
||||
libinput_device_tablet_pad_get_num_strips(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup device
|
||||
*
|
||||
|
|
|
|||
|
|
@ -234,3 +234,21 @@ LIBINPUT_1.2 {
|
|||
libinput_tablet_tool_set_user_data;
|
||||
libinput_tablet_tool_unref;
|
||||
} LIBINPUT_1.1;
|
||||
|
||||
LIBINPUT_1.3 {
|
||||
libinput_device_tablet_pad_get_num_buttons;
|
||||
libinput_device_tablet_pad_get_num_rings;
|
||||
libinput_device_tablet_pad_get_num_strips;
|
||||
libinput_event_get_tablet_pad_event;
|
||||
libinput_event_tablet_pad_get_base_event;
|
||||
libinput_event_tablet_pad_get_button_number;
|
||||
libinput_event_tablet_pad_get_button_state;
|
||||
libinput_event_tablet_pad_get_ring_position;
|
||||
libinput_event_tablet_pad_get_ring_number;
|
||||
libinput_event_tablet_pad_get_ring_source;
|
||||
libinput_event_tablet_pad_get_strip_position;
|
||||
libinput_event_tablet_pad_get_strip_number;
|
||||
libinput_event_tablet_pad_get_strip_source;
|
||||
libinput_event_tablet_pad_get_time;
|
||||
libinput_event_tablet_pad_get_time_usec;
|
||||
} LIBINPUT_1.2;
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ liblitest_la_SOURCES = \
|
|||
litest-device-wacom-cintiq-tablet.c \
|
||||
litest-device-wacom-cintiq-24hd.c \
|
||||
litest-device-wacom-intuos-tablet.c \
|
||||
litest-device-wacom-intuos3-pad.c \
|
||||
litest-device-wacom-intuos5-pad.c \
|
||||
litest-device-wacom-isdv4-tablet.c \
|
||||
litest-device-wacom-touch.c \
|
||||
litest-device-wacom-intuos-finger.c \
|
||||
|
|
@ -72,6 +74,7 @@ run_tests = \
|
|||
test-touchpad \
|
||||
test-touchpad-tap \
|
||||
test-touchpad-buttons \
|
||||
test-pad \
|
||||
test-tablet \
|
||||
test-device \
|
||||
test-gestures \
|
||||
|
|
@ -121,6 +124,10 @@ test_tablet_SOURCES = tablet.c
|
|||
test_tablet_LDADD = $(TEST_LIBS)
|
||||
test_tablet_LDFLAGS = -static
|
||||
|
||||
test_pad_SOURCES = pad.c
|
||||
test_pad_LDADD = $(TEST_LIBS)
|
||||
test_pad_LDFLAGS = -static
|
||||
|
||||
test_touchpad_SOURCES = touchpad.c
|
||||
test_touchpad_LDADD = $(TEST_LIBS)
|
||||
test_touchpad_LDFLAGS = -no-install
|
||||
|
|
|
|||
117
test/litest-device-wacom-intuos3-pad.c
Normal file
117
test/litest-device-wacom-intuos3-pad.c
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* 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 the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
||||
static void
|
||||
litest_wacom_intuos3_pad_setup(void)
|
||||
{
|
||||
struct litest_device *d = litest_create_device(LITEST_WACOM_INTUOS3_PAD);
|
||||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static struct input_event down[] = {
|
||||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static struct input_event move[] = {
|
||||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static struct input_event strip_start[] = {
|
||||
{ .type = EV_ABS, .code = ABS_RX, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MISC, .value = 15 },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
} ;
|
||||
|
||||
static struct input_event strip_change[] = {
|
||||
{ .type = EV_ABS, .code = ABS_RX, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
} ;
|
||||
|
||||
static struct input_event strip_end[] = {
|
||||
{ .type = EV_ABS, .code = ABS_RX, .value = 0 },
|
||||
{ .type = EV_ABS, .code = ABS_MISC, .value = 0 },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
} ;
|
||||
|
||||
static struct litest_device_interface interface = {
|
||||
.touch_down_events = down,
|
||||
.touch_move_events = move,
|
||||
.pad_strip_start_events = strip_start,
|
||||
.pad_strip_change_events = strip_change,
|
||||
.pad_strip_end_events = strip_end,
|
||||
};
|
||||
|
||||
static struct input_absinfo absinfo[] = {
|
||||
{ ABS_X, 0, 1, 0, 0, 0 },
|
||||
{ ABS_Y, 0, 1, 0, 0, 0 },
|
||||
{ ABS_RX, 0, 4096, 0, 0, 0 },
|
||||
{ ABS_MISC, 0, 0, 0, 0, 0 },
|
||||
{ .value = -1 },
|
||||
};
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x3,
|
||||
.vendor = 0x56a,
|
||||
.product = 0xb7,
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
EV_KEY, BTN_0,
|
||||
EV_KEY, BTN_1,
|
||||
EV_KEY, BTN_2,
|
||||
EV_KEY, BTN_3,
|
||||
EV_KEY, BTN_STYLUS,
|
||||
-1, -1,
|
||||
};
|
||||
|
||||
static const char udev_rule[] =
|
||||
"ACTION==\"remove\", GOTO=\"pad_end\"\n"
|
||||
"KERNEL!=\"event*\", GOTO=\"pad_end\"\n"
|
||||
"\n"
|
||||
"ATTRS{name}==\"litest Wacom Intuos3 4x6 Pad*\",\\\n"
|
||||
" ENV{ID_INPUT_TABLET_PAD}=\"1\"\n"
|
||||
"\n"
|
||||
"LABEL=\"pad_end\"";
|
||||
|
||||
struct litest_test_device litest_wacom_intuos3_pad_device = {
|
||||
.type = LITEST_WACOM_INTUOS3_PAD,
|
||||
.features = LITEST_TABLET_PAD | LITEST_STRIP,
|
||||
.shortname = "wacom-intuos3-pad",
|
||||
.setup = litest_wacom_intuos3_pad_setup,
|
||||
.interface = &interface,
|
||||
|
||||
.name = "Wacom Intuos3 4x6 Pad",
|
||||
.id = &input_id,
|
||||
.events = events,
|
||||
.absinfo = absinfo,
|
||||
.udev_rule = udev_rule,
|
||||
};
|
||||
122
test/litest-device-wacom-intuos5-pad.c
Normal file
122
test/litest-device-wacom-intuos5-pad.c
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* 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 the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
||||
static void
|
||||
litest_wacom_intuos5_pad_setup(void)
|
||||
{
|
||||
struct litest_device *d = litest_create_device(LITEST_WACOM_INTUOS5_PAD);
|
||||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static struct input_event down[] = {
|
||||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static struct input_event move[] = {
|
||||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static struct input_event ring_start[] = {
|
||||
{ .type = EV_ABS, .code = ABS_WHEEL, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MISC, .value = 15 },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
} ;
|
||||
|
||||
static struct input_event ring_change[] = {
|
||||
{ .type = EV_ABS, .code = ABS_WHEEL, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
} ;
|
||||
|
||||
static struct input_event ring_end[] = {
|
||||
{ .type = EV_ABS, .code = ABS_WHEEL, .value = 0 },
|
||||
{ .type = EV_ABS, .code = ABS_MISC, .value = 0 },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
} ;
|
||||
|
||||
static struct litest_device_interface interface = {
|
||||
.touch_down_events = down,
|
||||
.touch_move_events = move,
|
||||
.pad_ring_start_events = ring_start,
|
||||
.pad_ring_change_events = ring_change,
|
||||
.pad_ring_end_events = ring_end,
|
||||
};
|
||||
|
||||
static struct input_absinfo absinfo[] = {
|
||||
{ ABS_X, 0, 1, 0, 0, 0 },
|
||||
{ ABS_Y, 0, 1, 0, 0, 0 },
|
||||
{ ABS_WHEEL, 0, 71, 0, 0, 0 },
|
||||
{ ABS_MISC, 0, 0, 0, 0, 10 },
|
||||
{ .value = -1 },
|
||||
};
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x3,
|
||||
.vendor = 0x56a,
|
||||
.product = 0x27,
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
EV_KEY, BTN_0,
|
||||
EV_KEY, BTN_1,
|
||||
EV_KEY, BTN_2,
|
||||
EV_KEY, BTN_3,
|
||||
EV_KEY, BTN_4,
|
||||
EV_KEY, BTN_5,
|
||||
EV_KEY, BTN_6,
|
||||
EV_KEY, BTN_7,
|
||||
EV_KEY, BTN_8,
|
||||
EV_KEY, BTN_STYLUS,
|
||||
-1, -1,
|
||||
};
|
||||
|
||||
static const char udev_rule[] =
|
||||
"ACTION==\"remove\", GOTO=\"pad_end\"\n"
|
||||
"KERNEL!=\"event*\", GOTO=\"pad_end\"\n"
|
||||
"\n"
|
||||
"ATTRS{name}==\"litest Wacom Intuos5 touch M Pad*\",\\\n"
|
||||
" ENV{ID_INPUT_TABLET_PAD}=\"1\"\n"
|
||||
"\n"
|
||||
"LABEL=\"pad_end\"";
|
||||
|
||||
struct litest_test_device litest_wacom_intuos5_pad_device = {
|
||||
.type = LITEST_WACOM_INTUOS5_PAD,
|
||||
.features = LITEST_TABLET_PAD | LITEST_RING,
|
||||
.shortname = "wacom-pad",
|
||||
.setup = litest_wacom_intuos5_pad_setup,
|
||||
.interface = &interface,
|
||||
|
||||
.name = "Wacom Intuos5 touch M Pad",
|
||||
.id = &input_id,
|
||||
.events = events,
|
||||
.absinfo = absinfo,
|
||||
.udev_rule = udev_rule,
|
||||
};
|
||||
|
|
@ -105,6 +105,22 @@ struct litest_device_interface {
|
|||
struct input_event *tablet_proximity_out_events;
|
||||
struct input_event *tablet_motion_events;
|
||||
|
||||
/**
|
||||
* Pad events, LITEST_AUTO_ASSIGN is allowed on event values
|
||||
* for ABS_WHEEL
|
||||
*/
|
||||
struct input_event *pad_ring_start_events;
|
||||
struct input_event *pad_ring_change_events;
|
||||
struct input_event *pad_ring_end_events;
|
||||
|
||||
/**
|
||||
* Pad events, LITEST_AUTO_ASSIGN is allowed on event values
|
||||
* for ABS_RX
|
||||
*/
|
||||
struct input_event *pad_strip_start_events;
|
||||
struct input_event *pad_strip_change_events;
|
||||
struct input_event *pad_strip_end_events;
|
||||
|
||||
int min[2]; /* x/y axis minimum */
|
||||
int max[2]; /* x/y axis maximum */
|
||||
};
|
||||
|
|
|
|||
228
test/litest.c
228
test/litest.c
|
|
@ -380,6 +380,8 @@ extern struct litest_test_device litest_yubikey_device;
|
|||
extern struct litest_test_device litest_synaptics_i2c_device;
|
||||
extern struct litest_test_device litest_wacom_cintiq_24hd_device;
|
||||
extern struct litest_test_device litest_multitouch_fuzz_screen_device;
|
||||
extern struct litest_test_device litest_wacom_intuos3_pad_device;
|
||||
extern struct litest_test_device litest_wacom_intuos5_pad_device;
|
||||
|
||||
struct litest_test_device* devices[] = {
|
||||
&litest_synaptics_clickpad_device,
|
||||
|
|
@ -426,6 +428,8 @@ struct litest_test_device* devices[] = {
|
|||
&litest_synaptics_i2c_device,
|
||||
&litest_wacom_cintiq_24hd_device,
|
||||
&litest_multitouch_fuzz_screen_device,
|
||||
&litest_wacom_intuos3_pad_device,
|
||||
&litest_wacom_intuos5_pad_device,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
@ -1811,6 +1815,15 @@ litest_scale_axis(const struct litest_device *d,
|
|||
return (abs->maximum - abs->minimum) * val/100.0 + abs->minimum;
|
||||
}
|
||||
|
||||
static inline int
|
||||
litest_scale_range(int min, int max, double val)
|
||||
{
|
||||
litest_assert_int_ge((int)val, 0);
|
||||
litest_assert_int_le((int)val, 100);
|
||||
|
||||
return (max - min) * val/100.0 + min;
|
||||
}
|
||||
|
||||
int
|
||||
litest_scale(const struct litest_device *d, unsigned int axis, double val)
|
||||
{
|
||||
|
|
@ -1821,12 +1834,120 @@ litest_scale(const struct litest_device *d, unsigned int axis, double val)
|
|||
if (axis <= ABS_Y) {
|
||||
min = d->interface->min[axis];
|
||||
max = d->interface->max[axis];
|
||||
return (max - min) * val/100.0 + min;
|
||||
|
||||
return litest_scale_range(min, max, val);
|
||||
} else {
|
||||
return litest_scale_axis(d, axis, val);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
auto_assign_pad_value(struct litest_device *dev,
|
||||
struct input_event *ev,
|
||||
double value)
|
||||
{
|
||||
const struct input_absinfo *abs;
|
||||
|
||||
if (ev->value != LITEST_AUTO_ASSIGN ||
|
||||
ev->type != EV_ABS)
|
||||
return value;
|
||||
|
||||
abs = libevdev_get_abs_info(dev->evdev, ev->code);
|
||||
litest_assert_notnull(abs);
|
||||
|
||||
if (ev->code == ABS_RX || ev->code == ABS_RY) {
|
||||
double min = abs->minimum != 0 ? log2(abs->minimum) : 0,
|
||||
max = abs->maximum != 0 ? log2(abs->maximum) : 0;
|
||||
|
||||
/* Value 0 is reserved for finger up, so a value of 0% is
|
||||
* actually 1 */
|
||||
if (value == 0.0) {
|
||||
return 1;
|
||||
} else {
|
||||
value = litest_scale_range(min, max, value);
|
||||
return pow(2, value);
|
||||
}
|
||||
} else {
|
||||
return litest_scale_range(abs->minimum, abs->maximum, value);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
litest_pad_ring_start(struct litest_device *d, double value)
|
||||
{
|
||||
struct input_event *ev;
|
||||
|
||||
ev = d->interface->pad_ring_start_events;
|
||||
while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
|
||||
value = auto_assign_pad_value(d, ev, value);
|
||||
litest_event(d, ev->type, ev->code, value);
|
||||
ev++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
litest_pad_ring_change(struct litest_device *d, double value)
|
||||
{
|
||||
struct input_event *ev;
|
||||
|
||||
ev = d->interface->pad_ring_change_events;
|
||||
while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
|
||||
value = auto_assign_pad_value(d, ev, value);
|
||||
litest_event(d, ev->type, ev->code, value);
|
||||
ev++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
litest_pad_ring_end(struct litest_device *d)
|
||||
{
|
||||
struct input_event *ev;
|
||||
|
||||
ev = d->interface->pad_ring_end_events;
|
||||
while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
|
||||
litest_event(d, ev->type, ev->code, ev->value);
|
||||
ev++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
litest_pad_strip_start(struct litest_device *d, double value)
|
||||
{
|
||||
struct input_event *ev;
|
||||
|
||||
ev = d->interface->pad_strip_start_events;
|
||||
while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
|
||||
value = auto_assign_pad_value(d, ev, value);
|
||||
litest_event(d, ev->type, ev->code, value);
|
||||
ev++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
litest_pad_strip_change(struct litest_device *d, double value)
|
||||
{
|
||||
struct input_event *ev;
|
||||
|
||||
ev = d->interface->pad_strip_change_events;
|
||||
while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
|
||||
value = auto_assign_pad_value(d, ev, value);
|
||||
litest_event(d, ev->type, ev->code, value);
|
||||
ev++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
litest_pad_strip_end(struct litest_device *d)
|
||||
{
|
||||
struct input_event *ev;
|
||||
|
||||
ev = d->interface->pad_strip_end_events;
|
||||
while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
|
||||
litest_event(d, ev->type, ev->code, ev->value);
|
||||
ev++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
litest_wait_for_event(struct libinput *li)
|
||||
{
|
||||
|
|
@ -1965,6 +2086,15 @@ litest_event_type_str(struct libinput_event *event)
|
|||
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
|
||||
str = "TABLET TOOL BUTTON";
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
|
||||
str = "TABLET PAD BUTTON";
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_RING:
|
||||
str = "TABLET PAD RING";
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_STRIP:
|
||||
str = "TABLET PAD STRIP";
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
|
@ -1974,6 +2104,7 @@ litest_print_event(struct libinput_event *event)
|
|||
{
|
||||
struct libinput_event_pointer *p;
|
||||
struct libinput_event_tablet_tool *t;
|
||||
struct libinput_event_tablet_pad *pad;
|
||||
struct libinput_device *dev;
|
||||
enum libinput_event_type type;
|
||||
double x, y;
|
||||
|
|
@ -2035,6 +2166,26 @@ litest_print_event(struct libinput_event *event)
|
|||
libinput_event_tablet_tool_get_button(t),
|
||||
libinput_event_tablet_tool_get_button_state(t));
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
|
||||
pad = libinput_event_get_tablet_pad_event(event);
|
||||
fprintf(stderr, "button %d state %d",
|
||||
libinput_event_tablet_pad_get_button_number(pad),
|
||||
libinput_event_tablet_pad_get_button_state(pad));
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_RING:
|
||||
pad = libinput_event_get_tablet_pad_event(event);
|
||||
fprintf(stderr, "ring %d position %.2f source %d",
|
||||
libinput_event_tablet_pad_get_ring_number(pad),
|
||||
libinput_event_tablet_pad_get_ring_position(pad),
|
||||
libinput_event_tablet_pad_get_ring_source(pad));
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_STRIP:
|
||||
pad = libinput_event_get_tablet_pad_event(event);
|
||||
fprintf(stderr, "strip %d position %.2f source %d",
|
||||
libinput_event_tablet_pad_get_ring_number(pad),
|
||||
libinput_event_tablet_pad_get_ring_position(pad),
|
||||
libinput_event_tablet_pad_get_ring_source(pad));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -2456,6 +2607,81 @@ void litest_assert_tablet_proximity_event(struct libinput *li,
|
|||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
struct libinput_event_tablet_pad *
|
||||
litest_is_pad_button_event(struct libinput_event *event,
|
||||
unsigned int button,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
struct libinput_event_tablet_pad *p;
|
||||
enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_BUTTON;
|
||||
|
||||
litest_assert(event != NULL);
|
||||
litest_assert_int_eq(libinput_event_get_type(event), type);
|
||||
|
||||
p = libinput_event_get_tablet_pad_event(event);
|
||||
litest_assert(p != NULL);
|
||||
|
||||
litest_assert_int_eq(libinput_event_tablet_pad_get_button_number(p),
|
||||
button);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
struct libinput_event_tablet_pad *
|
||||
litest_is_pad_ring_event(struct libinput_event *event,
|
||||
unsigned int number,
|
||||
enum libinput_tablet_pad_ring_axis_source source)
|
||||
{
|
||||
struct libinput_event_tablet_pad *p;
|
||||
enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_RING;
|
||||
|
||||
litest_assert(event != NULL);
|
||||
litest_assert_int_eq(libinput_event_get_type(event), type);
|
||||
p = libinput_event_get_tablet_pad_event(event);
|
||||
|
||||
litest_assert_int_eq(libinput_event_tablet_pad_get_ring_number(p),
|
||||
number);
|
||||
litest_assert_int_eq(libinput_event_tablet_pad_get_ring_source(p),
|
||||
source);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
struct libinput_event_tablet_pad *
|
||||
litest_is_pad_strip_event(struct libinput_event *event,
|
||||
unsigned int number,
|
||||
enum libinput_tablet_pad_strip_axis_source source)
|
||||
{
|
||||
struct libinput_event_tablet_pad *p;
|
||||
enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_STRIP;
|
||||
|
||||
litest_assert(event != NULL);
|
||||
litest_assert_int_eq(libinput_event_get_type(event), type);
|
||||
p = libinput_event_get_tablet_pad_event(event);
|
||||
|
||||
litest_assert_int_eq(libinput_event_tablet_pad_get_strip_number(p),
|
||||
number);
|
||||
litest_assert_int_eq(libinput_event_tablet_pad_get_strip_source(p),
|
||||
source);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
litest_assert_pad_button_event(struct libinput *li,
|
||||
unsigned int button,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_tablet_pad *pev;
|
||||
|
||||
litest_wait_for_event(li);
|
||||
event = libinput_get_event(li);
|
||||
|
||||
pev = litest_is_pad_button_event(event, button, state);
|
||||
libinput_event_destroy(libinput_event_tablet_pad_get_base_event(pev));
|
||||
}
|
||||
|
||||
void
|
||||
litest_assert_scroll(struct libinput *li,
|
||||
enum libinput_pointer_axis axis,
|
||||
|
|
|
|||
|
|
@ -197,6 +197,8 @@ enum litest_device_type {
|
|||
LITEST_SYNAPTICS_I2C = -43,
|
||||
LITEST_WACOM_CINTIQ_24HD = -44,
|
||||
LITEST_MULTITOUCH_FUZZ_SCREEN = -45,
|
||||
LITEST_WACOM_INTUOS3_PAD = -46,
|
||||
LITEST_WACOM_INTUOS5_PAD = -47,
|
||||
};
|
||||
|
||||
enum litest_device_feature {
|
||||
|
|
@ -223,6 +225,9 @@ enum litest_device_feature {
|
|||
LITEST_DISTANCE = 1 << 18,
|
||||
LITEST_TOOL_SERIAL = 1 << 19,
|
||||
LITEST_TILT = 1 << 20,
|
||||
LITEST_TABLET_PAD = 1 << 21,
|
||||
LITEST_RING = 1 << 22,
|
||||
LITEST_STRIP = 1 << 23,
|
||||
};
|
||||
|
||||
struct litest_device {
|
||||
|
|
@ -440,6 +445,24 @@ litest_tablet_motion(struct litest_device *d,
|
|||
int x, int y,
|
||||
struct axis_replacement *axes);
|
||||
|
||||
void
|
||||
litest_pad_ring_start(struct litest_device *d, double value);
|
||||
|
||||
void
|
||||
litest_pad_ring_change(struct litest_device *d, double value);
|
||||
|
||||
void
|
||||
litest_pad_ring_end(struct litest_device *d);
|
||||
|
||||
void
|
||||
litest_pad_strip_start(struct litest_device *d, double value);
|
||||
|
||||
void
|
||||
litest_pad_strip_change(struct litest_device *d, double value);
|
||||
|
||||
void
|
||||
litest_pad_strip_end(struct litest_device *d);
|
||||
|
||||
void
|
||||
litest_hover_start(struct litest_device *d,
|
||||
unsigned int slot,
|
||||
|
|
@ -526,6 +549,19 @@ struct libinput_event_tablet_tool *
|
|||
litest_is_tablet_event(struct libinput_event *event,
|
||||
enum libinput_event_type type);
|
||||
|
||||
struct libinput_event_tablet_pad *
|
||||
litest_is_pad_button_event(struct libinput_event *event,
|
||||
unsigned int button,
|
||||
enum libinput_button_state state);
|
||||
struct libinput_event_tablet_pad *
|
||||
litest_is_pad_ring_event(struct libinput_event *event,
|
||||
unsigned int number,
|
||||
enum libinput_tablet_pad_ring_axis_source source);
|
||||
struct libinput_event_tablet_pad *
|
||||
litest_is_pad_strip_event(struct libinput_event *event,
|
||||
unsigned int number,
|
||||
enum libinput_tablet_pad_strip_axis_source source);
|
||||
|
||||
void
|
||||
litest_assert_button_event(struct libinput *li,
|
||||
unsigned int button,
|
||||
|
|
@ -549,6 +585,10 @@ void
|
|||
litest_assert_tablet_proximity_event(struct libinput *li,
|
||||
enum libinput_tablet_tool_proximity_state state);
|
||||
|
||||
void
|
||||
litest_assert_pad_button_event(struct libinput *li,
|
||||
unsigned int button,
|
||||
enum libinput_button_state state);
|
||||
struct libevdev_uinput *
|
||||
litest_create_uinput_device(const char *name,
|
||||
struct input_id *id,
|
||||
|
|
|
|||
51
test/misc.c
51
test/misc.c
|
|
@ -134,6 +134,7 @@ START_TEST(event_conversion_device_notify)
|
|||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_gesture_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_tool_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
|
||||
|
|
@ -190,6 +191,7 @@ START_TEST(event_conversion_pointer)
|
|||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_gesture_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_tool_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
libinput_event_destroy(event);
|
||||
|
|
@ -240,6 +242,7 @@ START_TEST(event_conversion_pointer_abs)
|
|||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_gesture_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_tool_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
libinput_event_destroy(event);
|
||||
|
|
@ -283,6 +286,7 @@ START_TEST(event_conversion_key)
|
|||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_gesture_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_tool_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
libinput_event_destroy(event);
|
||||
|
|
@ -333,6 +337,7 @@ START_TEST(event_conversion_touch)
|
|||
ck_assert(libinput_event_get_keyboard_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_gesture_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_tool_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
libinput_event_destroy(event);
|
||||
|
|
@ -381,6 +386,7 @@ START_TEST(event_conversion_gesture)
|
|||
ck_assert(libinput_event_get_pointer_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_keyboard_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
libinput_event_destroy(event);
|
||||
|
|
@ -427,6 +433,50 @@ START_TEST(event_conversion_tablet)
|
|||
ck_assert(libinput_event_get_pointer_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_keyboard_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
ck_assert_int_gt(events, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(event_conversion_tablet_pad)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
int events = 0;
|
||||
|
||||
litest_button_click(dev, BTN_0, true);
|
||||
litest_pad_ring_start(dev, 10);
|
||||
litest_pad_ring_end(dev);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
while ((event = libinput_get_event(li))) {
|
||||
enum libinput_event_type type;
|
||||
type = libinput_event_get_type(event);
|
||||
|
||||
if (type >= LIBINPUT_EVENT_TABLET_PAD_BUTTON &&
|
||||
type <= LIBINPUT_EVENT_TABLET_PAD_STRIP) {
|
||||
struct libinput_event_tablet_pad *p;
|
||||
struct libinput_event *base;
|
||||
|
||||
p = libinput_event_get_tablet_pad_event(event);
|
||||
base = libinput_event_tablet_pad_get_base_event(p);
|
||||
ck_assert(event == base);
|
||||
|
||||
events++;
|
||||
|
||||
litest_disable_log_handler(li);
|
||||
ck_assert(libinput_event_get_device_notify_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_pointer_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_keyboard_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_touch_event(event) == NULL);
|
||||
ck_assert(libinput_event_get_tablet_tool_event(event) == NULL);
|
||||
litest_restore_log_handler(li);
|
||||
}
|
||||
libinput_event_destroy(event);
|
||||
|
|
@ -895,6 +945,7 @@ litest_setup_tests(void)
|
|||
litest_add_for_device("events:conversion", event_conversion_touch, LITEST_WACOM_TOUCH);
|
||||
litest_add_for_device("events:conversion", event_conversion_gesture, LITEST_BCM5974);
|
||||
litest_add_for_device("events:conversion", event_conversion_tablet, LITEST_WACOM_CINTIQ);
|
||||
litest_add_for_device("events:conversion", event_conversion_tablet_pad, LITEST_WACOM_INTUOS5_PAD);
|
||||
litest_add_no_device("bitfield_helpers", bitfield_helpers);
|
||||
|
||||
litest_add_no_device("context:refcount", context_ref_counting);
|
||||
|
|
|
|||
431
test/pad.c
Normal file
431
test/pad.c
Normal file
|
|
@ -0,0 +1,431 @@
|
|||
/*
|
||||
* 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 the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <check.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libinput.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "libinput-util.h"
|
||||
#include "litest.h"
|
||||
|
||||
START_TEST(pad_cap)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
|
||||
ck_assert(libinput_device_has_capability(device,
|
||||
LIBINPUT_DEVICE_CAP_TABLET_PAD));
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pad_no_cap)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
|
||||
ck_assert(!libinput_device_has_capability(device,
|
||||
LIBINPUT_DEVICE_CAP_TABLET_PAD));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pad_num_buttons)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
unsigned int code;
|
||||
unsigned int nbuttons = 0;
|
||||
|
||||
for (code = BTN_0; code < KEY_MAX; code++) {
|
||||
/* BTN_STYLUS is set for compatibility reasons but not
|
||||
* actually hooked up */
|
||||
if (code == BTN_STYLUS)
|
||||
continue;
|
||||
|
||||
if (libevdev_has_event_code(dev->evdev, EV_KEY, code))
|
||||
nbuttons++;
|
||||
}
|
||||
|
||||
ck_assert_int_eq(libinput_device_tablet_pad_get_num_buttons(device),
|
||||
nbuttons);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pad_button)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
unsigned int code;
|
||||
unsigned int expected_number = 0;
|
||||
struct libinput_event *ev;
|
||||
struct libinput_event_tablet_pad *pev;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
for (code = BTN_LEFT; code < KEY_MAX; code++) {
|
||||
if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
|
||||
continue;
|
||||
|
||||
litest_button_click(dev, code, 1);
|
||||
litest_button_click(dev, code, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
switch (code) {
|
||||
case BTN_STYLUS:
|
||||
litest_assert_empty_queue(li);
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ev = libinput_get_event(li);
|
||||
pev = litest_is_pad_button_event(ev,
|
||||
expected_number,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
ev = libinput_event_tablet_pad_get_base_event(pev);
|
||||
libinput_event_destroy(ev);
|
||||
|
||||
ev = libinput_get_event(li);
|
||||
pev = litest_is_pad_button_event(ev,
|
||||
expected_number,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
ev = libinput_event_tablet_pad_get_base_event(pev);
|
||||
libinput_event_destroy(ev);
|
||||
|
||||
expected_number++;
|
||||
}
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pad_has_ring)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
int nrings;
|
||||
|
||||
nrings = libinput_device_tablet_pad_get_num_rings(device);
|
||||
ck_assert_int_ge(nrings, 1);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pad_ring)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *ev;
|
||||
struct libinput_event_tablet_pad *pev;
|
||||
int val;
|
||||
double degrees, expected;
|
||||
|
||||
litest_pad_ring_start(dev, 10);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* Wacom's 0 value is at 275 degrees */
|
||||
expected = 270;
|
||||
|
||||
for (val = 0; val < 100; val += 10) {
|
||||
litest_pad_ring_change(dev, val);
|
||||
libinput_dispatch(li);
|
||||
|
||||
ev = libinput_get_event(li);
|
||||
pev = litest_is_pad_ring_event(ev,
|
||||
0,
|
||||
LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER);
|
||||
|
||||
degrees = libinput_event_tablet_pad_get_ring_position(pev);
|
||||
ck_assert_double_ge(degrees, 0.0);
|
||||
ck_assert_double_lt(degrees, 360.0);
|
||||
|
||||
/* rounding errors, mostly caused by small physical range */
|
||||
ck_assert_double_ge(degrees, expected - 2);
|
||||
ck_assert_double_le(degrees, expected + 2);
|
||||
|
||||
libinput_event_destroy(ev);
|
||||
|
||||
expected = fmod(degrees + 36, 360);
|
||||
}
|
||||
|
||||
litest_pad_ring_end(dev);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pad_ring_finger_up)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *ev;
|
||||
struct libinput_event_tablet_pad *pev;
|
||||
double degrees;
|
||||
|
||||
litest_pad_ring_start(dev, 10);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_pad_ring_end(dev);
|
||||
libinput_dispatch(li);
|
||||
|
||||
ev = libinput_get_event(li);
|
||||
pev = litest_is_pad_ring_event(ev,
|
||||
0,
|
||||
LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER);
|
||||
|
||||
degrees = libinput_event_tablet_pad_get_ring_position(pev);
|
||||
ck_assert_double_eq(degrees, -1.0);
|
||||
libinput_event_destroy(ev);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pad_has_strip)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
int nstrips;
|
||||
|
||||
nstrips = libinput_device_tablet_pad_get_num_strips(device);
|
||||
ck_assert_int_ge(nstrips, 1);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pad_strip)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *ev;
|
||||
struct libinput_event_tablet_pad *pev;
|
||||
int val;
|
||||
double pos, expected;
|
||||
|
||||
litest_pad_strip_start(dev, 10);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
expected = 0;
|
||||
|
||||
/* 9.5 works with the generic axis scaling without jumping over a
|
||||
* value. */
|
||||
for (val = 0; val < 100; val += 9.5) {
|
||||
litest_pad_strip_change(dev, val);
|
||||
libinput_dispatch(li);
|
||||
|
||||
ev = libinput_get_event(li);
|
||||
pev = litest_is_pad_strip_event(ev,
|
||||
0,
|
||||
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER);
|
||||
|
||||
pos = libinput_event_tablet_pad_get_strip_position(pev);
|
||||
ck_assert_double_ge(pos, 0.0);
|
||||
ck_assert_double_lt(pos, 1.0);
|
||||
|
||||
/* rounding errors, mostly caused by small physical range */
|
||||
ck_assert_double_ge(pos, expected - 0.02);
|
||||
ck_assert_double_le(pos, expected + 0.02);
|
||||
|
||||
libinput_event_destroy(ev);
|
||||
|
||||
expected = pos + 0.08;
|
||||
}
|
||||
|
||||
litest_pad_strip_change(dev, 100);
|
||||
libinput_dispatch(li);
|
||||
|
||||
ev = libinput_get_event(li);
|
||||
pev = litest_is_pad_strip_event(ev,
|
||||
0,
|
||||
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER);
|
||||
pos = libinput_event_tablet_pad_get_strip_position(pev);
|
||||
ck_assert_double_eq(pos, 1.0);
|
||||
libinput_event_destroy(ev);
|
||||
|
||||
litest_pad_strip_end(dev);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pad_strip_finger_up)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *ev;
|
||||
struct libinput_event_tablet_pad *pev;
|
||||
double pos;
|
||||
|
||||
litest_pad_strip_start(dev, 10);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_pad_strip_end(dev);
|
||||
libinput_dispatch(li);
|
||||
|
||||
ev = libinput_get_event(li);
|
||||
pev = litest_is_pad_strip_event(ev,
|
||||
0,
|
||||
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER);
|
||||
|
||||
pos = libinput_event_tablet_pad_get_strip_position(pev);
|
||||
ck_assert_double_eq(pos, -1.0);
|
||||
libinput_event_destroy(ev);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pad_left_handed_default)
|
||||
{
|
||||
#if HAVE_LIBWACOM
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
enum libinput_config_status status;
|
||||
|
||||
ck_assert(libinput_device_config_left_handed_is_available(device));
|
||||
|
||||
ck_assert_int_eq(libinput_device_config_left_handed_get_default(device),
|
||||
0);
|
||||
ck_assert_int_eq(libinput_device_config_left_handed_get(device),
|
||||
0);
|
||||
|
||||
status = libinput_device_config_left_handed_set(dev->libinput_device, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
ck_assert_int_eq(libinput_device_config_left_handed_get(device),
|
||||
1);
|
||||
ck_assert_int_eq(libinput_device_config_left_handed_get_default(device),
|
||||
0);
|
||||
|
||||
status = libinput_device_config_left_handed_set(dev->libinput_device, 0);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
ck_assert_int_eq(libinput_device_config_left_handed_get(device),
|
||||
0);
|
||||
ck_assert_int_eq(libinput_device_config_left_handed_get_default(device),
|
||||
0);
|
||||
|
||||
#endif
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pad_no_left_handed)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
enum libinput_config_status status;
|
||||
|
||||
ck_assert(!libinput_device_config_left_handed_is_available(device));
|
||||
|
||||
ck_assert_int_eq(libinput_device_config_left_handed_get_default(device),
|
||||
0);
|
||||
ck_assert_int_eq(libinput_device_config_left_handed_get(device),
|
||||
0);
|
||||
|
||||
status = libinput_device_config_left_handed_set(dev->libinput_device, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
|
||||
|
||||
ck_assert_int_eq(libinput_device_config_left_handed_get(device),
|
||||
0);
|
||||
ck_assert_int_eq(libinput_device_config_left_handed_get_default(device),
|
||||
0);
|
||||
|
||||
status = libinput_device_config_left_handed_set(dev->libinput_device, 0);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
|
||||
|
||||
ck_assert_int_eq(libinput_device_config_left_handed_get(device),
|
||||
0);
|
||||
ck_assert_int_eq(libinput_device_config_left_handed_get_default(device),
|
||||
0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pad_left_handed_ring)
|
||||
{
|
||||
#if HAVE_LIBWACOM
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *ev;
|
||||
struct libinput_event_tablet_pad *pev;
|
||||
int val;
|
||||
double degrees, expected;
|
||||
|
||||
libinput_device_config_left_handed_set(dev->libinput_device, 1);
|
||||
|
||||
litest_pad_ring_start(dev, 10);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* Wacom's 0 value is at 275 degrees -> 90 in left-handed mode*/
|
||||
expected = 90;
|
||||
|
||||
for (val = 0; val < 100; val += 10) {
|
||||
litest_pad_ring_change(dev, val);
|
||||
libinput_dispatch(li);
|
||||
|
||||
ev = libinput_get_event(li);
|
||||
pev = litest_is_pad_ring_event(ev,
|
||||
0,
|
||||
LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER);
|
||||
|
||||
degrees = libinput_event_tablet_pad_get_ring_position(pev);
|
||||
ck_assert_double_ge(degrees, 0.0);
|
||||
ck_assert_double_lt(degrees, 360.0);
|
||||
|
||||
/* rounding errors, mostly caused by small physical range */
|
||||
ck_assert_double_ge(degrees, expected - 2);
|
||||
ck_assert_double_le(degrees, expected + 2);
|
||||
|
||||
libinput_event_destroy(ev);
|
||||
|
||||
expected = fmod(degrees + 36, 360);
|
||||
}
|
||||
|
||||
litest_pad_ring_end(dev);
|
||||
#endif
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
litest_setup_tests(void)
|
||||
{
|
||||
litest_add("pad:cap", pad_cap, LITEST_TABLET_PAD, LITEST_ANY);
|
||||
litest_add("pad:cap", pad_no_cap, LITEST_ANY, LITEST_TABLET_PAD);
|
||||
|
||||
litest_add("pad:button", pad_num_buttons, LITEST_TABLET_PAD, LITEST_ANY);
|
||||
litest_add("pad:button", pad_button, LITEST_TABLET_PAD, LITEST_ANY);
|
||||
|
||||
litest_add("pad:ring", pad_has_ring, LITEST_RING, LITEST_ANY);
|
||||
litest_add("pad:ring", pad_ring, LITEST_RING, LITEST_ANY);
|
||||
litest_add("pad:ring", pad_ring_finger_up, LITEST_RING, LITEST_ANY);
|
||||
|
||||
litest_add("pad:strip", pad_has_strip, LITEST_STRIP, LITEST_ANY);
|
||||
litest_add("pad:strip", pad_strip, LITEST_STRIP, LITEST_ANY);
|
||||
litest_add("pad:strip", pad_strip_finger_up, LITEST_STRIP, LITEST_ANY);
|
||||
|
||||
litest_add_for_device("pad:left_handed", pad_left_handed_default, LITEST_WACOM_INTUOS5_PAD);
|
||||
litest_add_for_device("pad:left_handed", pad_no_left_handed, LITEST_WACOM_INTUOS3_PAD);
|
||||
litest_add_for_device("pad:left_handed", pad_left_handed_ring, LITEST_WACOM_INTUOS5_PAD);
|
||||
/* None of the current strip tablets are left-handed */
|
||||
}
|
||||
|
|
@ -121,6 +121,15 @@ print_event_header(struct libinput_event *ev)
|
|||
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
|
||||
type = "TABLET_TOOL_BUTTON";
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
|
||||
type = "TABLET_PAD_BUTTON";
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_RING:
|
||||
type = "TABLET_PAD_RING";
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_STRIP:
|
||||
type = "TABLET_PAD_STRIP";
|
||||
break;
|
||||
}
|
||||
|
||||
printf("%-7s %-16s ", libinput_device_get_sysname(dev), type);
|
||||
|
|
@ -172,6 +181,9 @@ print_device_notify(struct libinput_event *ev)
|
|||
if (libinput_device_has_capability(dev,
|
||||
LIBINPUT_DEVICE_CAP_TABLET_TOOL))
|
||||
printf("T");
|
||||
if (libinput_device_has_capability(dev,
|
||||
LIBINPUT_DEVICE_CAP_TABLET_PAD))
|
||||
printf("P");
|
||||
|
||||
if (libinput_device_get_size(dev, &w, &h) == 0)
|
||||
printf("\tsize %.2f/%.2fmm", w, h);
|
||||
|
|
@ -574,6 +586,66 @@ print_gesture_event_with_coords(struct libinput_event *ev)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_tablet_pad_button_event(struct libinput_event *ev)
|
||||
{
|
||||
struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
|
||||
enum libinput_button_state state;
|
||||
|
||||
print_event_time(libinput_event_tablet_pad_get_time(p));
|
||||
|
||||
state = libinput_event_tablet_pad_get_button_state(p);
|
||||
printf("%3d %s\n",
|
||||
libinput_event_tablet_pad_get_button_number(p),
|
||||
state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released");
|
||||
}
|
||||
|
||||
static void
|
||||
print_tablet_pad_ring_event(struct libinput_event *ev)
|
||||
{
|
||||
struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
|
||||
const char *source = "<invalid>";
|
||||
|
||||
print_event_time(libinput_event_tablet_pad_get_time(p));
|
||||
|
||||
switch (libinput_event_tablet_pad_get_ring_source(p)) {
|
||||
case LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER:
|
||||
source = "finger";
|
||||
break;
|
||||
case LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN:
|
||||
source = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
printf("ring %d position %.2f (source %s)\n",
|
||||
libinput_event_tablet_pad_get_ring_number(p),
|
||||
libinput_event_tablet_pad_get_ring_position(p),
|
||||
source);
|
||||
}
|
||||
|
||||
static void
|
||||
print_tablet_pad_strip_event(struct libinput_event *ev)
|
||||
{
|
||||
struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
|
||||
const char *source = "<invalid>";
|
||||
|
||||
print_event_time(libinput_event_tablet_pad_get_time(p));
|
||||
|
||||
switch (libinput_event_tablet_pad_get_strip_source(p)) {
|
||||
case LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER:
|
||||
source = "finger";
|
||||
break;
|
||||
case LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN:
|
||||
source = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
printf("strip %d position %.2f (source %s)\n",
|
||||
libinput_event_tablet_pad_get_strip_number(p),
|
||||
libinput_event_tablet_pad_get_strip_position(p),
|
||||
source);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_and_print_events(struct libinput *li)
|
||||
{
|
||||
|
|
@ -653,6 +725,15 @@ handle_and_print_events(struct libinput *li)
|
|||
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
|
||||
print_tablet_button_event(ev);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
|
||||
print_tablet_pad_button_event(ev);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_RING:
|
||||
print_tablet_pad_ring_event(ev);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_STRIP:
|
||||
print_tablet_pad_strip_event(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
libinput_event_destroy(ev);
|
||||
|
|
|
|||
|
|
@ -798,6 +798,10 @@ handle_event_libinput(GIOChannel *source, GIOCondition condition, gpointer data)
|
|||
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
|
||||
handle_event_tablet(ev, w);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
|
||||
case LIBINPUT_EVENT_TABLET_PAD_RING:
|
||||
case LIBINPUT_EVENT_TABLET_PAD_STRIP:
|
||||
break;
|
||||
}
|
||||
|
||||
libinput_event_destroy(ev);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue