Merge branch 'wip/tablet-pad-modes-v3'

This commit is contained in:
Peter Hutterer 2016-07-04 10:26:03 +10:00
commit 35a6ebc536
22 changed files with 2367 additions and 163 deletions

View file

@ -49,7 +49,9 @@ diagram_files = \
$(srcdir)/svg/software-buttons.svg \
$(srcdir)/svg/swipe-gestures.svg \
$(srcdir)/svg/tablet-axes.svg \
$(srcdir)/svg/tablet-cintiq24hd-modes.svg \
$(srcdir)/svg/tablet-interfaces.svg \
$(srcdir)/svg/tablet-intuos-modes.svg \
$(srcdir)/svg/tablet-left-handed.svg \
$(srcdir)/svg/tablet-out-of-bounds.svg \
$(srcdir)/svg/tablet.svg \

View file

@ -0,0 +1,460 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="134.12471mm"
height="73.121918mm"
viewBox="0 0 475.24503 259.09341"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="tablet-cintiq24hd-modes.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8"
inkscape:cx="235.34348"
inkscape:cy="122.76858"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
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">
<sodipodi:guide
position="63.613208,240.91603"
orientation="0,1"
id="guide4164" />
<sodipodi:guide
position="61.087828,13.126636"
orientation="0,1"
id="guide4166" />
<sodipodi:guide
position="455.7142,176.16061"
orientation="0,1"
id="guide5966" />
<sodipodi:guide
position="457.99098,166.42846"
orientation="0,1"
id="guide5968" />
<sodipodi:guide
position="457.05348,156.47311"
orientation="-0.00010854417,-0.99999999"
id="guide5970" />
<sodipodi:guide
position="454.4642,169.19632"
orientation="1,0"
id="guide5972" />
<sodipodi:guide
position="22.365981,176.16061"
orientation="1,0"
id="guide5974" />
</sodipodi:namedview>
<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(-139.42745,-156.36228)">
<rect
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.92000002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4136"
width="474.32504"
height="258.1734"
x="139.88745"
y="156.82228"
rx="5" />
<rect
y="175.42407"
x="199.33878"
height="226.52563"
width="357.34042"
id="rect4140"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.74800003;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<g
id="g5913">
<g
style="stroke-width:1.87739301;stroke-miterlimit:4;stroke-dasharray:none"
transform="matrix(0.53265351,0,0,0.53265351,104.30809,96.440418)"
id="g7023">
<circle
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:1.87739301;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path4158"
cx="135.61298"
cy="287.06125"
r="22.98097" />
<ellipse
cy="287.06125"
cx="135.61298"
id="circle4160"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:1.87739301;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
rx="11.5985"
ry="12.608653" />
</g>
<rect
rx="0.5"
y="268.93671"
x="175.8243"
height="8.9902887"
width="13.786156"
id="rect4162"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.29022256;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
rx="0.5"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.29022256;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect7027"
width="13.786156"
height="8.9902887"
x="175.8243"
y="280.97675" />
<rect
rx="0.5"
y="293.01678"
x="175.8243"
height="8.9902887"
width="13.786156"
id="rect7029"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.29022256;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
rx="0.5"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.44849709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect7031"
width="9.1119308"
height="32.483532"
x="161.90343"
y="269.44443" />
<rect
rx="0.5"
y="269.44443"
x="149.90343"
height="32.483532"
width="9.1119308"
id="rect7033"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.44849709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
rx="0.5"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.19463234;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect7035"
width="9.3657951"
height="5.9516821"
x="149.77649"
y="256.10321" />
<rect
rx="0.5"
y="246.10321"
x="149.77649"
height="5.9516821"
width="9.3657951"
id="rect7037"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.19463234;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
rx="0.5"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.19463234;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect7039"
width="9.3657951"
height="5.9516821"
x="149.77649"
y="236.10321" />
</g>
<g
id="g5889">
<g
id="g7056"
transform="matrix(-0.53265351,0,0,0.53265351,651.12665,96.440418)"
style="fill:#4e4e4e;fill-opacity:0.99215686;stroke-width:1.87739301;stroke-miterlimit:4;stroke-dasharray:none">
<circle
r="22.98097"
cy="287.06125"
cx="135.61298"
id="circle7058"
style="opacity:0.92000002;fill:#4e4e4e;fill-opacity:0.99215686;stroke:#4d4d4d;stroke-width:1.87739301;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<ellipse
ry="12.608653"
rx="11.5985"
style="opacity:0.92000002;fill:#4e4e4e;fill-opacity:0.99215686;stroke:#4d4d4d;stroke-width:1.87739301;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="ellipse7060"
cx="135.61298"
cy="287.06125" />
</g>
<rect
transform="scale(-1,1)"
style="opacity:0.92000002;fill:#4e4e4e;fill-opacity:0.99215686;stroke:#4d4d4d;stroke-width:0.29022256;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect7062"
width="13.786156"
height="8.9902887"
x="-579.61047"
y="268.93671"
rx="0.5" />
<rect
transform="scale(-1,1)"
y="280.97675"
x="-579.61047"
height="8.9902887"
width="13.786156"
id="rect7064"
style="opacity:0.92000002;fill:#4e4e4e;fill-opacity:0.99215686;stroke:#4d4d4d;stroke-width:0.29022256;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
rx="0.5" />
<rect
transform="scale(-1,1)"
style="opacity:0.92000002;fill:#4e4e4e;fill-opacity:0.99215686;stroke:#4d4d4d;stroke-width:0.29022256;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect7066"
width="13.786156"
height="8.9902887"
x="-579.61047"
y="293.01678"
rx="0.5" />
<rect
transform="scale(-1,1)"
y="269.44443"
x="-593.53131"
height="32.483532"
width="9.1119308"
id="rect7068"
style="opacity:0.92000002;fill:#4e4e4e;fill-opacity:0.99215686;stroke:#4d4d4d;stroke-width:0.44849709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
rx="0.5" />
<rect
transform="scale(-1,1)"
style="opacity:0.92000002;fill:#4e4e4e;fill-opacity:0.99215686;stroke:#4d4d4d;stroke-width:0.44849709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect7070"
width="9.1119308"
height="32.483532"
x="-605.53131"
y="269.44443"
rx="0.5" />
<rect
transform="scale(-1,1)"
y="256.10321"
x="-605.65826"
height="5.9516821"
width="9.3657951"
id="rect7072"
style="opacity:0.92000002;fill:#4e4e4e;fill-opacity:0.99215686;stroke:#4d4d4d;stroke-width:0.19463234;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
rx="0.5" />
<rect
transform="scale(-1,1)"
style="opacity:0.92000002;fill:#4e4e4e;fill-opacity:0.99215686;stroke:#4d4d4d;stroke-width:0.19463234;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect7074"
width="9.3657951"
height="5.9516821"
x="-605.65826"
y="246.10321"
rx="0.5" />
<rect
transform="scale(-1,1)"
y="236.10321"
x="-605.65826"
height="5.9516821"
width="9.3657951"
id="rect7076"
style="opacity:0.92000002;fill:#4e4e4e;fill-opacity:0.99215686;stroke:#4d4d4d;stroke-width:0.19463234;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
rx="0.5" />
</g>
<circle
r="1.0714241"
cy="239.25041"
cx="593.89166"
id="circle5003"
style="opacity:1;fill:#858585;fill-opacity:1;stroke:none;stroke-width:0.56541353;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<circle
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.56541353;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle5941"
cx="593.89166"
cy="249.01828"
r="1.0714241" />
<circle
r="1.0714241"
cy="258.98257"
cx="593.89166"
id="circle5943"
style="opacity:1;fill:#858585;fill-opacity:1;stroke:none;stroke-width:0.56541353;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<circle
r="1.0714241"
cy="239.27275"
cx="161.79344"
id="circle5003-7"
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.56541353;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<circle
style="display:inline;opacity:1;fill:#858585;fill-opacity:1;stroke:none;stroke-width:0.56541353;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle5941-3"
cx="161.79344"
cy="249.04956"
r="1.0714241" />
<circle
r="1.0714241"
cy="259.00488"
cx="161.79344"
id="circle5943-4"
style="display:inline;opacity:1;fill:#858585;fill-opacity:1;stroke:none;stroke-width:0.56541353;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;line-height:125%;font-family:'sans serif';-inkscape-font-specification:'sans serif';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="231.68831"
y="209.7363"
id="text5031"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5033"
x="231.68831"
y="209.7363"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'sans serif';-inkscape-font-specification:'sans serif';fill:#ff0000;fill-opacity:1">mode indicators</tspan></text>
<text
sodipodi:linespacing="125%"
id="text6033"
y="209.7363"
x="421.35587"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;line-height:125%;font-family:'sans serif';-inkscape-font-specification:'sans serif';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'sans serif';-inkscape-font-specification:'sans serif';fill:#ff0000;fill-opacity:1"
y="209.7363"
x="421.35587"
id="tspan6035"
sodipodi:role="line">mode indicators</tspan></text>
<text
sodipodi:linespacing="125%"
id="text6037"
y="291.72427"
x="204.56126"
style="font-style:normal;font-weight:normal;font-size:15px;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
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'sans serif';-inkscape-font-specification:'sans serif';fill:#ff0000;fill-opacity:1"
y="291.72427"
x="204.56126"
id="tspan6039"
sodipodi:role="line">mode toggle buttons</tspan></text>
<g
id="g6047">
<path
inkscape:connector-curvature="0"
id="path6041"
d="m 163.79343,258.98257 27.45536,0 38.75,-44.41964 40.98214,0.26786"
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path6043"
d="m 163.79343,249.02722 35.9375,0"
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path6045"
d="m 163.79343,239.29507 44.41964,0"
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
id="g6052"
transform="matrix(-1,0,0,1,755.65383,-0.02232143)">
<path
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 163.79343,258.98257 27.45536,0 38.75,-44.41964 40.98214,0.26786"
id="path6054"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 163.79343,249.02722 35.9375,0"
id="path6056"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 163.79343,239.29507 44.41964,0"
id="path6058"
inkscape:connector-curvature="0" />
</g>
<g
id="g6096">
<path
inkscape:connector-curvature="0"
id="path6088"
d="m 145.10947,239.29507 0,55.95257 78.53936,0"
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path6090"
d="m 145.23574,239.29507 4.98762,0"
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 145.23574,259.29507 4.98762,0"
id="path6092"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path6094"
d="m 145.23574,249.01096 4.98762,0"
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
id="g6102"
transform="matrix(-1,0,0,1,754.76113,0)">
<path
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 145.10947,239.29507 0,55.95257 78.53936,0"
id="path6104"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 145.23574,239.29507 4.98762,0"
id="path6106"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path6108"
d="m 145.23574,259.29507 4.98762,0"
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 145.23574,249.01096 4.98762,0"
id="path6110"
inkscape:connector-curvature="0" />
</g>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:15px;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="420.56128"
y="291.72427"
id="text6112"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6114"
x="420.56128"
y="291.72427"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'sans serif';-inkscape-font-specification:'sans serif';fill:#ff0000;fill-opacity:1">mode toggle buttons</tspan></text>
</g>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="stylus"
style="display:inline"
transform="translate(-139.42745,-156.36228)" />
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

View file

@ -0,0 +1,321 @@
<?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="111.70494mm"
height="65.496956mm"
viewBox="0 0 395.80491 232.07583"
id="svg4249"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="tablet-intuos-modes.svg">
<defs
id="defs4251">
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker5774"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Lend">
<path
transform="matrix(-0.8,0,0,-0.8,-10,0)"
style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
id="path5776"
inkscape:connector-curvature="0" />
</marker>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4294"
id="linearGradient4300"
x1="465.81339"
y1="666.13727"
x2="454.82117"
y2="658.65521"
gradientUnits="userSpaceOnUse" />
<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>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="77.55251"
inkscape:cy="104.65462"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:guide-bbox="true"
fit-margin-left="0.1"
fit-margin-top="0"
fit-margin-right="0"
fit-margin-bottom="0">
<inkscape:grid
type="xygrid"
id="grid4897"
originx="-56.206096"
originy="-132.53353" />
<sodipodi:guide
position="71.578207,133.89422"
orientation="0,1"
id="guide4991" />
<sodipodi:guide
position="28.258193,123.80577"
orientation="1,0"
id="guide4993" />
<sodipodi:guide
position="63.704627,120.85934"
orientation="1,0"
id="guide4995" />
<sodipodi:guide
position="48.704626,98.44863"
orientation="0,1"
id="guide4997" />
<sodipodi:guide
position="54.937501,116.125"
orientation="0,1"
id="guide5057" />
<sodipodi:guide
position="46.000001,127.5625"
orientation="1,0"
id="guide5059" />
</sodipodi:namedview>
<metadata
id="metadata4254">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-56.206094,-687.75286)">
<g
id="g5039">
<rect
y="688.15009"
x="56.95763"
height="231.28139"
width="394.65616"
id="rect4136"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.79444152;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.56541353;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4140"
width="270.06381"
height="171.19916"
x="150.33304"
y="719.33636" />
<rect
y="719.56689"
x="77.601257"
height="16.734699"
width="49.124439"
id="rect4142"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.74744725;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.74744725;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4148"
width="49.124439"
height="16.734699"
x="77.601257"
y="740.72821" />
<rect
y="761.88947"
x="77.601257"
height="16.734699"
width="49.124439"
id="rect4150"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.74744725;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
y="831.41949"
x="77.601257"
height="16.734699"
width="49.124439"
id="rect4154"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.74744725;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.74744725;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4156"
width="49.124439"
height="16.734699"
x="77.601257"
y="852.58075" />
<circle
r="17.368113"
cy="803.70734"
cx="102.17159"
id="path4158"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.74744725;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<ellipse
ry="9.5291233"
rx="8.7656898"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.39332128;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle4160"
cx="102.17159"
cy="803.70734" />
<rect
y="873.74207"
x="77.601257"
height="16.734699"
width="49.124439"
id="rect4162"
style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.74744725;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
<g
id="g4304"
transform="matrix(0.2806137,0.07519021,-0.0726958,0.27130439,247.48122,626.86299)">
<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>
<circle
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.56541353;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path5001"
cx="119.91072"
cy="785.93445"
r="1.0714241" />
<circle
r="1.0714241"
cy="785.93445"
cx="84.458878"
id="circle5003"
style="opacity:1;fill:#858585;fill-opacity:1;stroke:none;stroke-width:0.56541353;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<circle
r="1.0714241"
cy="821.38873"
cx="119.91072"
id="circle5005"
style="opacity:1;fill:#858585;fill-opacity:1;stroke:none;stroke-width:0.56541353;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<circle
style="opacity:1;fill:#858585;fill-opacity:1;stroke:none;stroke-width:0.56541353;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle5007"
cx="84.458878"
cy="821.38873"
r="1.0714241" />
<g
id="g5021">
<path
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0999999;stroke-dasharray:none;stroke-opacity:1"
d="M 121.60675,784.75904 144.71431,766.2249"
id="path5015"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
d="m 109.26292,766.15758 101.60169,0.0205 m -124.715997,18.514 23.107557,-18.53414"
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path5017" />
</g>
<g
id="g5025"
transform="matrix(1,0,0,-1,0,1607.4699)">
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path5027"
d="M 121.60675,784.75904 144.71431,766.2249"
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0999999;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path5029"
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 109.26292,766.15758 101.60169,0.0205 m -124.715997,18.514 23.107557,-18.53414"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</g>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;line-height:125%;font-family:'sans serif';-inkscape-font-specification:'sans serif';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="134.17352"
y="761.21094"
id="text5031"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5033"
x="134.17352"
y="761.21094"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'sans serif';-inkscape-font-specification:'sans serif';fill:#ff0000;fill-opacity:1">mode indicators</tspan></text>
<text
sodipodi:linespacing="125%"
id="text5035"
y="857.37744"
x="134.17352"
style="font-style:normal;font-weight:normal;font-size:15px;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
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'sans serif';-inkscape-font-specification:'sans serif';fill:#ff0000;fill-opacity:1"
y="857.37744"
x="134.17352"
id="tspan5037"
sodipodi:role="line">mode indicators</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.40000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 102.39358,803.70368 61,0"
id="path5051"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:15px;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="167.36102"
y="806.87744"
id="text5053"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5055"
x="167.36102"
y="806.87744"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;font-family:'sans serif';-inkscape-font-specification:'sans serif';fill:#ff0000;fill-opacity:1">mode toggle button</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -240,8 +240,7 @@ 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
switch between modes, see @ref tablet-pad-modes. Callers should use
external sources like libwacom to identify which buttons have semantic
behaviors.
@ -276,4 +275,60 @@ symmetric and thus do not support left-handed mode. libinput requires
libwacom to determine if a tablet is capable of being switched to
left-handed mode.
@section tablet-pad-modes Tablet pad modes
Tablet pad modes are virtual groupings of button, ring and strip
functionality. A caller may assign different functionalities depending on
the mode the tablet is in. For example, in mode 0 the touch ring may emulate
scrolling, in mode 1 the touch ring may emulate zooming, etc. libinput
handles the modes and mode switching but does not assign specific
functionality to buttons, rings or strips based on the mode. It is up to the
caller to decide whether the mode only applies to buttons, rings and strips
or only to rings and strips (this is the case with the Wacom OS X and
Windows driver).
The availability of modes on a touchpad usually depends on visual feedback
such as LEDs around the touch ring. If no visual feedback is available, only
one mode may be available.
Mode switching is controlled by libinput and usually toggled by one or
more buttons on the device. For example, on the Wacom Intuos 4, 5, and
Pro series tablets the mode button is the button centered in the touch
ring and toggles the modes sequentially. On the Wacom Cintiq 24HD the
three buttons next to each touch ring allow for directly changing the
mode to the desired setting.
Multiple modes may exist on the tablet, libinput uses the term "mode group"
for such groupings of buttons that share a mode and mode toggle. For
example, the Wacom Cintiq 24HD has two separate mode groups, one for the
left set of buttons, strips, and touch rings and one for the right set.
libinput handles the mode groups independently and returns the mode for each
button as appropriate. The mode group is static for the lifetime of the
device.
@image html tablet-intuos-modes.svg "Modes on an Intuos Pro-like tablet"
In the image above, the Intuos Pro-like tablet provides 4 LEDs to indicate
the currently active modes. The button inside the touch ring cycles through
the modes in a clockwise fashion. The upper-right LED indicates that the
currently active mode is 1, based on 0-indexed mode numbering.
libinput_event_tablet_pad_get_mode() would thus return 1 for all button and
ring events on this tablet. When the center button is pressed, the mode
switches to mode 2, the LED changes to the bottom-right and
libinput_event_tablet_pad_get_mode() returns 2 for the center button event
and all subsequent events.
@image html tablet-cintiq24hd-modes.svg "Modes on an Cintiq 24HD-like tablet"
In the image above, the Cintiq 24HD-like tablet provides 3 LEDs on each side
of the tablet to indicate the currently active mode for that group of
buttons and the respective ring. The buttons next to the touch ring select
the mode directly. The two LEDs indicate that the mode for the left set of
buttons is currently 0, the mode for the right set of buttons is currently
1, based on 0-indexed mode numbering. libinput_event_tablet_pad_get_mode()
would thus return 0 for all button and ring events on the left and 1 for all
button and ring events on the right. When one of the three mode toggle
buttons on the right is pressed, the right mode switches to that button's
mode but the left mode remains unchanged.
*/

View file

@ -22,6 +22,7 @@ libinput_la_SOURCES = \
evdev-tablet.h \
evdev-tablet-pad.c \
evdev-tablet-pad.h \
evdev-tablet-pad-leds.c \
filter.c \
filter.h \
filter-private.h \

177
src/evdev-tablet-pad-leds.c Normal file
View file

@ -0,0 +1,177 @@
/*
* Copyright © 2016 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of 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 <assert.h>
#include <limits.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "evdev-tablet-pad.h"
struct pad_led_group {
struct libinput_tablet_pad_mode_group base;
};
static void
pad_led_group_destroy(struct libinput_tablet_pad_mode_group *g)
{
struct pad_led_group *group = (struct pad_led_group *)g;
free(group);
}
static struct pad_led_group *
pad_group_new_basic(struct pad_dispatch *pad,
unsigned int group_index,
int nleds)
{
struct pad_led_group *group;
group = zalloc(sizeof *group);
if (!group)
return NULL;
group->base.device = &pad->device->base;
group->base.refcount = 1;
group->base.index = group_index;
group->base.current_mode = 0;
group->base.num_modes = nleds;
group->base.destroy = pad_led_group_destroy;
return group;
}
static inline struct libinput_tablet_pad_mode_group *
pad_get_mode_group(struct pad_dispatch *pad, unsigned int index)
{
struct libinput_tablet_pad_mode_group *group;
list_for_each(group, &pad->modes.mode_group_list, link) {
if (group->index == index)
return group;
}
return NULL;
}
static int
pad_init_fallback_group(struct pad_dispatch *pad)
{
struct pad_led_group *group;
group = pad_group_new_basic(pad, 0, 1);
if (!group)
return 1;
/* If we only have one group, all buttons/strips/rings are part of
* that group. We rely on the other layers to filter out invalid
* indices */
group->base.button_mask = -1;
group->base.strip_mask = -1;
group->base.ring_mask = -1;
group->base.toggle_button_mask = 0;
list_insert(&pad->modes.mode_group_list, &group->base.link);
return 0;
}
int
pad_init_leds(struct pad_dispatch *pad,
struct evdev_device *device)
{
int rc = 1;
list_init(&pad->modes.mode_group_list);
if (pad->nbuttons > 32) {
log_bug_libinput(device->base.seat->libinput,
"Too many pad buttons for modes %d\n",
pad->nbuttons);
return rc;
}
/* Eventually we slot the libwacom-based led detection in here. That
* requires getting the kernel ready first. For now we just init the
* fallback single-mode group.
*/
rc = pad_init_fallback_group(pad);
return rc;
}
void
pad_destroy_leds(struct pad_dispatch *pad)
{
struct libinput_tablet_pad_mode_group *group, *tmpgrp;
list_for_each_safe(group, tmpgrp, &pad->modes.mode_group_list, link)
libinput_tablet_pad_mode_group_unref(group);
}
void
pad_button_update_mode(struct libinput_tablet_pad_mode_group *g,
unsigned int button_index,
enum libinput_button_state state)
{
struct pad_led_group *group = (struct pad_led_group*)g;
if (state != LIBINPUT_BUTTON_STATE_PRESSED)
return;
if (!libinput_tablet_pad_mode_group_button_is_toggle(g, button_index))
return;
log_bug_libinput(group->base.device->seat->libinput,
"Button %d should not be a toggle button",
button_index);
}
int
evdev_device_tablet_pad_get_num_mode_groups(struct evdev_device *device)
{
struct pad_dispatch *pad = (struct pad_dispatch*)device->dispatch;
struct libinput_tablet_pad_mode_group *group;
int num_groups = 0;
if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD))
return -1;
list_for_each(group, &pad->modes.mode_group_list, link)
num_groups++;
return num_groups;
}
struct libinput_tablet_pad_mode_group *
evdev_device_tablet_pad_get_mode_group(struct evdev_device *device,
unsigned int index)
{
struct pad_dispatch *pad = (struct pad_dispatch*)device->dispatch;
if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD))
return NULL;
return pad_get_mode_group(pad, index);
}

View file

@ -209,12 +209,45 @@ pad_handle_strip(struct pad_dispatch *pad,
return pos;
}
static inline struct libinput_tablet_pad_mode_group *
pad_ring_get_mode_group(struct pad_dispatch *pad,
unsigned int ring)
{
struct libinput_tablet_pad_mode_group *group;
list_for_each(group, &pad->modes.mode_group_list, link) {
if (libinput_tablet_pad_mode_group_has_ring(group, ring))
return group;
}
assert(!"Unable to find ring mode group");
return NULL;
}
static inline struct libinput_tablet_pad_mode_group *
pad_strip_get_mode_group(struct pad_dispatch *pad,
unsigned int strip)
{
struct libinput_tablet_pad_mode_group *group;
list_for_each(group, &pad->modes.mode_group_list, link) {
if (libinput_tablet_pad_mode_group_has_strip(group, strip))
return group;
}
assert(!"Unable to find strip mode group");
return NULL;
}
static void
pad_check_notify_axes(struct pad_dispatch *pad,
struct evdev_device *device,
uint64_t time)
{
struct libinput_device *base = &device->base;
struct libinput_tablet_pad_mode_group *group;
double value;
bool send_finger_up = false;
@ -229,11 +262,13 @@ pad_check_notify_axes(struct pad_dispatch *pad,
if (send_finger_up)
value = -1.0;
group = pad_ring_get_mode_group(pad, 0);
tablet_pad_notify_ring(base,
time,
0,
value,
LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER);
LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER,
group);
}
if (pad->changed_axes & PAD_AXIS_RING2) {
@ -241,11 +276,13 @@ pad_check_notify_axes(struct pad_dispatch *pad,
if (send_finger_up)
value = -1.0;
group = pad_ring_get_mode_group(pad, 1);
tablet_pad_notify_ring(base,
time,
1,
value,
LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER);
LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER,
group);
}
if (pad->changed_axes & PAD_AXIS_STRIP1) {
@ -253,11 +290,13 @@ pad_check_notify_axes(struct pad_dispatch *pad,
if (send_finger_up)
value = -1.0;
group = pad_strip_get_mode_group(pad, 0);
tablet_pad_notify_strip(base,
time,
0,
value,
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER);
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER,
group);
}
if (pad->changed_axes & PAD_AXIS_STRIP2) {
@ -265,11 +304,13 @@ pad_check_notify_axes(struct pad_dispatch *pad,
if (send_finger_up)
value = -1.0;
group = pad_strip_get_mode_group(pad, 1);
tablet_pad_notify_strip(base,
time,
1,
value,
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER);
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER,
group);
}
pad->changed_axes = PAD_AXIS_NONE;
@ -288,6 +329,22 @@ pad_process_key(struct pad_dispatch *pad,
pad_button_set_down(pad, button, is_press);
}
static inline struct libinput_tablet_pad_mode_group *
pad_button_get_mode_group(struct pad_dispatch *pad,
unsigned int button)
{
struct libinput_tablet_pad_mode_group *group;
list_for_each(group, &pad->modes.mode_group_list, link) {
if (libinput_tablet_pad_mode_group_has_button(group, button))
return group;
}
assert(!"Unable to find button mode group\n");
return NULL;
}
static void
pad_notify_button_mask(struct pad_dispatch *pad,
struct evdev_device *device,
@ -296,6 +353,7 @@ pad_notify_button_mask(struct pad_dispatch *pad,
enum libinput_button_state state)
{
struct libinput_device *base = &device->base;
struct libinput_tablet_pad_mode_group *group;
int32_t code;
unsigned int i;
@ -315,8 +373,11 @@ pad_notify_button_mask(struct pad_dispatch *pad,
continue;
map = pad->button_map[code - 1];
if (map != -1)
tablet_pad_notify_button(base, time, map, state);
if (map != -1) {
group = pad_button_get_mode_group(pad, map);
pad_button_update_mode(group, map, state);
tablet_pad_notify_button(base, time, map, state, group);
}
}
}
}
@ -437,6 +498,7 @@ pad_destroy(struct evdev_dispatch *dispatch)
{
struct pad_dispatch *pad = (struct pad_dispatch*)dispatch;
pad_destroy_leds(pad);
free(pad);
}
@ -500,6 +562,8 @@ pad_init(struct pad_dispatch *pad, struct evdev_device *device)
pad_init_buttons(pad, device);
pad_init_left_handed(device);
if (pad_init_leds(pad, device) != 0)
return 1;
return 0;
}

View file

@ -64,6 +64,10 @@ struct pad_dispatch {
struct libinput_device_config_send_events config;
enum libinput_config_send_events_mode current_mode;
} sendevents;
struct {
struct list mode_group_list;
} modes;
};
static inline struct libinput *
@ -72,4 +76,12 @@ pad_libinput_context(const struct pad_dispatch *pad)
return evdev_libinput_context(pad->device);
}
int
pad_init_leds(struct pad_dispatch *pad, struct evdev_device *device);
void
pad_destroy_leds(struct pad_dispatch *pad);
void
pad_button_update_mode(struct libinput_tablet_pad_mode_group *g,
unsigned int pressed_button,
enum libinput_button_state state);
#endif

View file

@ -389,6 +389,22 @@ evdev_device_tablet_pad_get_num_rings(struct evdev_device *device);
int
evdev_device_tablet_pad_get_num_strips(struct evdev_device *device);
int
evdev_device_tablet_pad_get_num_mode_groups(struct evdev_device *device);
struct libinput_tablet_pad_mode_group *
evdev_device_tablet_pad_get_mode_group(struct evdev_device *device,
unsigned int index);
unsigned int
evdev_device_tablet_pad_mode_group_get_button_target(
struct libinput_tablet_pad_mode_group *g,
unsigned int button_index);
struct libinput_tablet_pad_led *
evdev_device_tablet_pad_get_led(struct evdev_device *device,
unsigned int led);
double
evdev_device_transform_x(struct evdev_device *device,
double x,

View file

@ -329,6 +329,25 @@ struct libinput_tablet_tool {
bool has_pressure_offset;
};
struct libinput_tablet_pad_mode_group {
struct libinput_device *device;
struct list link;
int refcount;
void *user_data;
unsigned int index;
unsigned int num_modes;
unsigned int current_mode;
uint32_t button_mask;
uint32_t ring_mask;
uint32_t strip_mask;
uint32_t toggle_button_mask;
void (*destroy)(struct libinput_tablet_pad_mode_group *group);
};
struct libinput_event {
enum libinput_event_type type;
struct libinput_device *device;
@ -566,19 +585,22 @@ void
tablet_pad_notify_button(struct libinput_device *device,
uint64_t time,
int32_t button,
enum libinput_button_state state);
enum libinput_button_state state,
struct libinput_tablet_pad_mode_group *group);
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);
enum libinput_tablet_pad_ring_axis_source source,
struct libinput_tablet_pad_mode_group *group);
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);
enum libinput_tablet_pad_strip_axis_source source,
struct libinput_tablet_pad_mode_group *group);
static inline uint64_t
libinput_now(struct libinput *libinput)

View file

@ -27,6 +27,7 @@
#include <assert.h>
#include <unistd.h>
#include <limits.h>
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
@ -86,6 +87,7 @@ int list_empty(const struct list *list);
pos = tmp, \
tmp = container_of(pos->member.next, tmp, member))
#define NBITS(b) (b * 8)
#define LONG_BITS (sizeof(long) * 8)
#define NLONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
@ -399,4 +401,23 @@ us2ms(uint64_t us)
return (uint32_t)(us / 1000);
}
static inline bool
safe_atoi(const char *str, int *val)
{
char *endptr;
long v;
v = strtol(str, &endptr, 10);
if (str == endptr)
return false;
if (*str != '\0' && *endptr != '\0')
return false;
if (v > INT_MAX || v < INT_MIN)
return false;
*val = v;
return true;
}
#endif /* LIBINPUT_UTIL_H */

View file

@ -140,6 +140,8 @@ struct libinput_event_tablet_tool {
struct libinput_event_tablet_pad {
struct libinput_event base;
unsigned int mode;
struct libinput_tablet_pad_mode_group *mode_group;
uint64_t time;
struct {
uint32_t number;
@ -1666,6 +1668,12 @@ libinput_event_tablet_tool_destroy(struct libinput_event_tablet_tool *event)
libinput_tablet_tool_unref(event->tool);
}
static void
libinput_event_tablet_pad_destroy(struct libinput_event_tablet_pad *event)
{
libinput_tablet_pad_mode_group_unref(event->mode_group);
}
LIBINPUT_EXPORT void
libinput_event_destroy(struct libinput_event *event)
{
@ -1680,6 +1688,13 @@ libinput_event_destroy(struct libinput_event *event)
libinput_event_tablet_tool_destroy(
libinput_event_get_tablet_tool_event(event));
break;
case LIBINPUT_EVENT_TABLET_PAD_RING:
case LIBINPUT_EVENT_TABLET_PAD_STRIP:
case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
case LIBINPUT_EVENT_TABLET_PAD_MODE:
libinput_event_tablet_pad_destroy(
libinput_event_get_tablet_pad_event(event));
break;
default:
break;
}
@ -2400,18 +2415,24 @@ void
tablet_pad_notify_button(struct libinput_device *device,
uint64_t time,
int32_t button,
enum libinput_button_state state)
enum libinput_button_state state,
struct libinput_tablet_pad_mode_group *group)
{
struct libinput_event_tablet_pad *button_event;
unsigned int mode;
button_event = zalloc(sizeof *button_event);
if (!button_event)
return;
mode = libinput_tablet_pad_mode_group_get_mode(group);
*button_event = (struct libinput_event_tablet_pad) {
.time = time,
.button.number = button,
.button.state = state,
.mode_group = libinput_tablet_pad_mode_group_ref(group),
.mode = mode,
};
post_device_event(device,
@ -2425,19 +2446,25 @@ tablet_pad_notify_ring(struct libinput_device *device,
uint64_t time,
unsigned int number,
double value,
enum libinput_tablet_pad_ring_axis_source source)
enum libinput_tablet_pad_ring_axis_source source,
struct libinput_tablet_pad_mode_group *group)
{
struct libinput_event_tablet_pad *ring_event;
unsigned int mode;
ring_event = zalloc(sizeof *ring_event);
if (!ring_event)
return;
mode = libinput_tablet_pad_mode_group_get_mode(group);
*ring_event = (struct libinput_event_tablet_pad) {
.time = time,
.ring.number = number,
.ring.position = value,
.ring.source = source,
.mode_group = libinput_tablet_pad_mode_group_ref(group),
.mode = mode,
};
post_device_event(device,
@ -2451,19 +2478,25 @@ tablet_pad_notify_strip(struct libinput_device *device,
uint64_t time,
unsigned int number,
double value,
enum libinput_tablet_pad_strip_axis_source source)
enum libinput_tablet_pad_strip_axis_source source,
struct libinput_tablet_pad_mode_group *group)
{
struct libinput_event_tablet_pad *strip_event;
unsigned int mode;
strip_event = zalloc(sizeof *strip_event);
if (!strip_event)
return;
mode = libinput_tablet_pad_mode_group_get_mode(group);
*strip_event = (struct libinput_event_tablet_pad) {
.time = time,
.strip.number = number,
.strip.position = value,
.strip.source = source,
.mode_group = libinput_tablet_pad_mode_group_ref(group),
.mode = mode,
};
post_device_event(device,
@ -2580,6 +2613,7 @@ event_type_to_str(enum libinput_event_type type)
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_TABLET_PAD_MODE);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_END);
@ -2829,6 +2863,121 @@ 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 int
libinput_device_tablet_pad_get_num_mode_groups(struct libinput_device *device)
{
return evdev_device_tablet_pad_get_num_mode_groups((struct evdev_device *)device);
}
LIBINPUT_EXPORT struct libinput_tablet_pad_mode_group*
libinput_device_tablet_pad_get_mode_group(struct libinput_device *device,
unsigned int index)
{
return evdev_device_tablet_pad_get_mode_group((struct evdev_device *)device,
index);
}
LIBINPUT_EXPORT unsigned int
libinput_tablet_pad_mode_group_get_num_modes(
struct libinput_tablet_pad_mode_group *group)
{
return group->num_modes;
}
LIBINPUT_EXPORT unsigned int
libinput_tablet_pad_mode_group_get_mode(struct libinput_tablet_pad_mode_group *group)
{
return group->current_mode;
}
LIBINPUT_EXPORT unsigned int
libinput_tablet_pad_mode_group_get_index(struct libinput_tablet_pad_mode_group *group)
{
return group->index;
}
LIBINPUT_EXPORT int
libinput_tablet_pad_mode_group_has_button(struct libinput_tablet_pad_mode_group *group,
unsigned int button)
{
if ((int)button >=
libinput_device_tablet_pad_get_num_buttons(group->device))
return 0;
return !!(group->button_mask & (1 << button));
}
LIBINPUT_EXPORT int
libinput_tablet_pad_mode_group_has_ring(struct libinput_tablet_pad_mode_group *group,
unsigned int ring)
{
if ((int)ring >=
libinput_device_tablet_pad_get_num_rings(group->device))
return 0;
return !!(group->ring_mask & (1 << ring));
}
LIBINPUT_EXPORT int
libinput_tablet_pad_mode_group_has_strip(struct libinput_tablet_pad_mode_group *group,
unsigned int strip)
{
if ((int)strip >=
libinput_device_tablet_pad_get_num_strips(group->device))
return 0;
return !!(group->strip_mask & (1 << strip));
}
LIBINPUT_EXPORT int
libinput_tablet_pad_mode_group_button_is_toggle(struct libinput_tablet_pad_mode_group *group,
unsigned int button)
{
if ((int)button >=
libinput_device_tablet_pad_get_num_buttons(group->device))
return 0;
return !!(group->toggle_button_mask & (1 << button));
}
LIBINPUT_EXPORT struct libinput_tablet_pad_mode_group *
libinput_tablet_pad_mode_group_ref(
struct libinput_tablet_pad_mode_group *group)
{
group->refcount++;
return group;
}
LIBINPUT_EXPORT struct libinput_tablet_pad_mode_group *
libinput_tablet_pad_mode_group_unref(
struct libinput_tablet_pad_mode_group *group)
{
assert(group->refcount > 0);
group->refcount--;
if (group->refcount > 0)
return group;
list_remove(&group->link);
group->destroy(group);
return NULL;
}
LIBINPUT_EXPORT void
libinput_tablet_pad_mode_group_set_user_data(
struct libinput_tablet_pad_mode_group *group,
void *user_data)
{
group->user_data = user_data;
}
LIBINPUT_EXPORT void *
libinput_tablet_pad_mode_group_get_user_data(
struct libinput_tablet_pad_mode_group *group)
{
return group->user_data;
}
LIBINPUT_EXPORT struct libinput_event *
libinput_event_device_notify_get_base_event(struct libinput_event_device_notify *event)
{
@ -2989,6 +3138,32 @@ libinput_event_tablet_pad_get_button_state(struct libinput_event_tablet_pad *eve
return event->button.state;
}
LIBINPUT_EXPORT unsigned int
libinput_event_tablet_pad_get_mode(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->mode;
}
LIBINPUT_EXPORT struct libinput_tablet_pad_mode_group *
libinput_event_tablet_pad_get_mode_group(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->mode_group;
}
LIBINPUT_EXPORT uint32_t
libinput_event_tablet_pad_get_time(struct libinput_event_tablet_pad *event)
{

View file

@ -37,6 +37,132 @@ extern "C" {
__attribute__ ((format (printf, _format, _args)))
#define LIBINPUT_ATTRIBUTE_DEPRECATED __attribute__ ((deprecated))
/**
* @ingroup base
* @struct libinput
*
* A handle for accessing libinput. This struct is refcounted, use
* libinput_ref() and libinput_unref().
*/
struct libinput;
/**
* @ingroup device
* @struct libinput_device
*
* A base handle for accessing libinput devices. This struct is
* refcounted, use libinput_device_ref() and libinput_device_unref().
*/
struct libinput_device;
/**
* @ingroup device
* @struct libinput_device_group
*
* A base handle for accessing libinput device groups. This struct is
* refcounted, use libinput_device_group_ref() and
* libinput_device_group_unref().
*/
struct libinput_device_group;
/**
* @ingroup seat
* @struct libinput_seat
*
* The base handle for accessing libinput seats. This struct is
* refcounted, use libinput_seat_ref() and libinput_seat_unref().
*/
struct libinput_seat;
/**
* @ingroup device
* @struct libinput_tablet_tool
*
* An object representing a tool being used by a device with the @ref
* LIBINPUT_DEVICE_CAP_TABLET_TOOL capability.
*
* Tablet events generated by such a device are bound to a specific tool
* rather than coming from the device directly. Depending on the hardware it
* is possible to track the same physical tool across multiple
* struct libinput_device devices, see @ref tablet-serial-numbers.
*
* This struct is refcounted, use libinput_tablet_tool_ref() and
* libinput_tablet_tool_unref().
*/
struct libinput_tablet_tool;
/**
* @ingroup event
* @struct libinput_event
*
* The base event type. Use libinput_event_get_pointer_event() or similar to
* get the actual event type.
*
* @warning Unlike other structs events are considered transient and
* <b>not</b> refcounted.
*/
struct libinput_event;
/**
* @ingroup event
* @struct libinput_event_device_notify
*
* An event notifying the caller of a device being added or removed.
*/
struct libinput_event_device_notify;
/**
* @ingroup event_keyboard
* @struct libinput_event_keyboard
*
* A keyboard event representing a key press/release.
*/
struct libinput_event_keyboard;
/**
* @ingroup event_pointer
* @struct libinput_event_pointer
*
* A pointer event representing relative or absolute pointer movement,
* a button press/release or scroll axis events.
*/
struct libinput_event_pointer;
/**
* @ingroup event_touch
* @struct libinput_event_touch
*
* Touch event representing a touch down, move or up, as well as a touch
* cancel and touch frame events. Valid event types for this event are @ref
* LIBINPUT_EVENT_TOUCH_DOWN, @ref LIBINPUT_EVENT_TOUCH_MOTION, @ref
* LIBINPUT_EVENT_TOUCH_UP, @ref LIBINPUT_EVENT_TOUCH_CANCEL and @ref
* LIBINPUT_EVENT_TOUCH_FRAME.
*/
struct libinput_event_touch;
/**
* @ingroup event_tablet
* @struct libinput_event_tablet_tool
*
* Tablet tool event representing an axis update, button press, or tool
* update. Valid event types for this event are @ref
* LIBINPUT_EVENT_TABLET_TOOL_AXIS, @ref
* LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY and @ref
* LIBINPUT_EVENT_TABLET_TOOL_BUTTON.
*/
struct libinput_event_tablet_tool;
/**
* @ingroup event_tablet_pad
* @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;
/**
* @ingroup base
*
@ -136,7 +262,7 @@ enum libinput_pointer_axis_source {
};
/**
* @ingroup event_tablet
* @ingroup event_tablet_pad
*
* The source for a @ref LIBINPUT_EVENT_TABLET_PAD_RING event. See
* libinput_event_tablet_pad_get_ring_source() for details.
@ -151,7 +277,7 @@ enum libinput_tablet_pad_ring_axis_source {
};
/**
* @ingroup event_tablet
* @ingroup event_tablet_pad
*
* The source for a @ref LIBINPUT_EVENT_TABLET_PAD_STRIP event. See
* libinput_event_tablet_pad_get_strip_source() for details.
@ -165,23 +291,6 @@ enum libinput_tablet_pad_strip_axis_source {
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER,
};
/**
* @ingroup device
* @struct libinput_tablet_tool
*
* An object representing a tool being used by a device with the @ref
* LIBINPUT_DEVICE_CAP_TABLET_TOOL capability.
*
* Tablet events generated by such a device are bound to a specific tool
* rather than coming from the device directly. Depending on the hardware it
* is possible to track the same physical tool across multiple
* struct libinput_device devices, see @ref tablet-serial-numbers.
*
* This struct is refcounted, use libinput_tablet_tool_ref() and
* libinput_tablet_tool_unref().
*/
struct libinput_tablet_tool;
/**
* @ingroup device
*
@ -246,6 +355,236 @@ enum libinput_tablet_tool_tip_state {
LIBINPUT_TABLET_TOOL_TIP_DOWN = 1,
};
/**
* @defgroup tablet_pad_modes Tablet pad modes
*
* Handling the virtual mode groups of buttons, strips and rings on tablet
* pad devices. See @ref tablet-pad-modes for details.
*/
/**
* @ingroup tablet_pad_modes
* @struct libinput_tablet_pad_mode_group
*
* A mode on a tablet pad is a virtual grouping of functionality, usually
* based on some visual feedback like LEDs on the pad. The set of buttons,
* rings and strips that share the same mode are a "mode group". Whenever
* the mode changes, all buttons, rings and strips within this mode group
* are affected. See @ref tablet-pad-modes for detail.
*
* Most tablets only have a single mode group, some tablets provide multiple
* mode groups through independent banks of LEDs (e.g. the Wacom Cintiq
* 24HD). libinput guarantees that at least one mode group is always
* available.
*
* This struct is refcounted, use libinput_tablet_pad_mode_group_ref() and
* libinput_tablet_pad_mode_group_unref().
*/
struct libinput_tablet_pad_mode_group;
/**
* @ingroup tablet_pad_modes
*
* Most devices only provide a single mode group, however devices such as
* the Wacom Cintiq 22HD provide two mode groups. If multiple mode groups
* are available, a caller should use
* libinput_tablet_pad_mode_group_has_button(),
* libinput_tablet_pad_mode_group_has_ring() and
* libinput_tablet_pad_mode_group_has_strip() to associate each button,
* ring and strip with the correct mode group.
*
* @return the number of mode groups available on this device
*/
int
libinput_device_tablet_pad_get_num_mode_groups(struct libinput_device *device);
/**
* @ingroup tablet_pad_modes
*
* The returned mode group is not refcounted and may become invalid after
* the next call to libinput. Use libinput_tablet_pad_mode_group_ref() and
* libinput_tablet_pad_mode_group_unref() to continue using the handle
* outside of the immediate scope.
*
* While at least one reference is kept by the caller, the returned mode
* group will be identical for each subsequent call of this function with
* the same index and that same struct is returned from
* libinput_event_tablet_pad_get_mode_group(), provided the event was
* generated by this mode group.
*
* @param device A device with the @ref LIBINPUT_DEVICE_CAP_TABLET_PAD
* capability
* @param index A mode group index
* @return the mode group with the given index or NULL if an invalid index
* is given.
*/
struct libinput_tablet_pad_mode_group*
libinput_device_tablet_pad_get_mode_group(struct libinput_device *device,
unsigned int index);
/**
* @ingroup tablet_pad_modes
*
* The returned number is the same index as passed to
* libinput_device_tablet_pad_get_mode_group(). For tablets with only one
* mode this number is always 0.
*
* @param group A previously obtained mode group
* @return the numeric index this mode group represents, starting at 0
*/
unsigned int
libinput_tablet_pad_mode_group_get_index(struct libinput_tablet_pad_mode_group *group);
/**
* @ingroup tablet_pad_modes
*
* Query the mode group for the number of available modes. This number is
* usually decided by the number of physical LEDs available on the device.
* Different mode groups may have a different number of modes.
* Use libinput_tablet_pad_mode_group_get_mode() to get the currently active
* mode.
*
* libinput guarantees that at least one mode is available. A device without
* mode switching capability has a single mode group and a single mode.
*
* @param group A previously obtained mode group
* @return the number of modes available in this mode group
*/
unsigned int
libinput_tablet_pad_mode_group_get_num_modes(struct libinput_tablet_pad_mode_group *group);
/**
* @ingroup tablet_pad_modes
*
* Return the current mode this mode group is in. Note that the returned
* mode is the mode valid as of completing the last libinput_dispatch().
* The returned mode may thus be different to the mode returned by
* libinput_event_tablet_pad_get_mode().
*
* For example, if the mode was toggled three times between the call to
* libinput_dispatch(), this function returns the third mode but the events
* in the event queue will return the modes 1, 2 and 3, respectively.
*
* @param group A previously obtained mode group
* @return the numeric index of the current mode in this group, starting at 0
*
* @see libinput_event_tablet_pad_get_mode
*/
unsigned int
libinput_tablet_pad_mode_group_get_mode(struct libinput_tablet_pad_mode_group *group);
/**
* @ingroup tablet_pad_modes
*
* Devices without mode switching capabilities return true for every button.
*
* @param group A previously obtained mode group
* @param button A button index, starting at 0
* @return true if the given button index is part of this mode group or
* false otherwise
*/
int
libinput_tablet_pad_mode_group_has_button(struct libinput_tablet_pad_mode_group *group,
unsigned int button);
/**
* @ingroup tablet_pad_modes
*
* Devices without mode switching capabilities return true for every ring.
*
* @param group A previously obtained mode group
* @param ring A ring index, starting at 0
* @return true if the given ring index is part of this mode group or
* false otherwise
*/
int
libinput_tablet_pad_mode_group_has_ring(struct libinput_tablet_pad_mode_group *group,
unsigned int ring);
/**
* @ingroup tablet_pad_modes
*
* Devices without mode switching capabilities return true for every strip.
*
* @param group A previously obtained mode group
* @param strip A strip index, starting at 0
* @return true if the given strip index is part of this mode group or
* false otherwise
*/
int
libinput_tablet_pad_mode_group_has_strip(struct libinput_tablet_pad_mode_group *group,
unsigned int strip);
/**
* @ingroup tablet_pad_modes
*
* Devices without mode switching capabilities return false for every button.
*
* @param group A previously obtained mode group
* @param button A button index, starting at 0
* @retval non-zero if the button is a mode toggle button for this group, or
* zero otherwise
*/
int
libinput_tablet_pad_mode_group_button_is_toggle(struct libinput_tablet_pad_mode_group *group,
unsigned int button);
/**
* @ingroup tablet_pad_modes
*
* Increase the refcount of the mode group. A mode device group will be
* freed whenever the refcount reaches 0.
*
* @param group A previously obtained mode group
* @return The passed mode group
*/
struct libinput_tablet_pad_mode_group *
libinput_tablet_pad_mode_group_ref(
struct libinput_tablet_pad_mode_group *group);
/**
* @ingroup tablet_pad_modes
*
* Decrease the refcount of the mode group. A mode device group will be
* freed whenever the refcount reaches 0.
*
* @param group A previously obtained mode group
* @return NULL if the group was destroyed, otherwise the passed mode group
*/
struct libinput_tablet_pad_mode_group *
libinput_tablet_pad_mode_group_unref(
struct libinput_tablet_pad_mode_group *group);
/**
* @ingroup tablet_pad_modes
*
* Set caller-specific data associated with this mode group. libinput does
* not manage, look at, or modify this data. The caller must ensure the
* data is valid.
*
* @param group A previously obtained mode group
* @param user_data Caller-specific data pointer
* @see libinput_tablet_pad_mode_group_get_user_data
*
*/
void
libinput_tablet_pad_mode_group_set_user_data(
struct libinput_tablet_pad_mode_group *group,
void *user_data);
/**
* @ingroup tablet_pad_modes
*
* Get the caller-specific data associated with this input device, if any.
*
* @param group A previously obtained mode group
* @return Caller-specific data pointer or NULL if none was set
* @see libinput_tablet_pad_mode_group_set_user_data
*/
void *
libinput_tablet_pad_mode_group_get_user_data(
struct libinput_tablet_pad_mode_group *group);
/**
* @ingroup base
*
@ -395,6 +734,19 @@ enum libinput_event_type {
*/
LIBINPUT_EVENT_TABLET_PAD_STRIP,
/**
* A mode change on a device with the @ref
* LIBINPUT_DEVICE_CAP_TABLET_PAD capability.
*
* This event is triggered when the mode is changed through
* external means. The event reflects a mode change (see @ref
* tablet-pad-modes) occurring as a result other than that of
* pressing a mode toggle button.
*
* @note Support for this event is not yet implemented.
*/
LIBINPUT_EVENT_TABLET_PAD_MODE,
LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN = 800,
LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
LIBINPUT_EVENT_GESTURE_SWIPE_END,
@ -403,115 +755,6 @@ enum libinput_event_type {
LIBINPUT_EVENT_GESTURE_PINCH_END,
};
/**
* @ingroup base
* @struct libinput
*
* A handle for accessing libinput. This struct is refcounted, use
* libinput_ref() and libinput_unref().
*/
struct libinput;
/**
* @ingroup device
* @struct libinput_device
*
* A base handle for accessing libinput devices. This struct is
* refcounted, use libinput_device_ref() and libinput_device_unref().
*/
struct libinput_device;
/**
* @ingroup device
* @struct libinput_device_group
*
* A base handle for accessing libinput device groups. This struct is
* refcounted, use libinput_device_group_ref() and
* libinput_device_group_unref().
*/
struct libinput_device_group;
/**
* @ingroup seat
* @struct libinput_seat
*
* The base handle for accessing libinput seats. This struct is
* refcounted, use libinput_seat_ref() and libinput_seat_unref().
*/
struct libinput_seat;
/**
* @ingroup event
* @struct libinput_event
*
* The base event type. Use libinput_event_get_pointer_event() or similar to
* get the actual event type.
*
* @warning Unlike other structs events are considered transient and
* <b>not</b> refcounted.
*/
struct libinput_event;
/**
* @ingroup event
* @struct libinput_event_device_notify
*
* An event notifying the caller of a device being added or removed.
*/
struct libinput_event_device_notify;
/**
* @ingroup event_keyboard
* @struct libinput_event_keyboard
*
* A keyboard event representing a key press/release.
*/
struct libinput_event_keyboard;
/**
* @ingroup event_pointer
* @struct libinput_event_pointer
*
* A pointer event representing relative or absolute pointer movement,
* a button press/release or scroll axis events.
*/
struct libinput_event_pointer;
/**
* @ingroup event_touch
* @struct libinput_event_touch
*
* Touch event representing a touch down, move or up, as well as a touch
* cancel and touch frame events. Valid event types for this event are @ref
* LIBINPUT_EVENT_TOUCH_DOWN, @ref LIBINPUT_EVENT_TOUCH_MOTION, @ref
* LIBINPUT_EVENT_TOUCH_UP, @ref LIBINPUT_EVENT_TOUCH_CANCEL and @ref
* LIBINPUT_EVENT_TOUCH_FRAME.
*/
struct libinput_event_touch;
/**
* @ingroup event_tablet
* @struct libinput_event_tablet_tool
*
* Tablet tool event representing an axis update, button press, or tool
* update. Valid event types for this event are @ref
* LIBINPUT_EVENT_TABLET_TOOL_AXIS, @ref
* LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY and @ref
* LIBINPUT_EVENT_TABLET_TOOL_BUTTON.
*/
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
*/
@ -1449,7 +1692,8 @@ libinput_event_gesture_get_angle_delta(struct libinput_event_gesture *event);
/**
* @defgroup event_tablet Tablet events
*
* Events that come from tools on or the pad of tablet devices.
* Events that come from tools on tablet devices. For events from the pad,
* see @ref event_tablet_pad.
*
* Events from tablet devices are exposed by two interfaces, tools and pads.
* Tool events originate (usually) from a stylus-like device, pad events
@ -2212,7 +2456,14 @@ libinput_tablet_tool_set_user_data(struct libinput_tablet_tool *tool,
void *user_data);
/**
* @ingroup event_tablet
* @defgroup event_tablet_pad Tablet pad events
*
* Events that come from the pad of tablet devices. For events from the
* tablet tools, see @ref event_tablet.
*/
/**
* @ingroup event_tablet_pad
*
* @return The generic libinput_event of this event
*/
@ -2220,7 +2471,7 @@ struct libinput_event *
libinput_event_tablet_pad_get_base_event(struct libinput_event_tablet_pad *event);
/**
* @ingroup event_tablet
* @ingroup event_tablet_pad
*
* Returns the current position of the ring, in degrees counterclockwise
* from the northern-most point of the ring in the tablet's current logical
@ -2243,7 +2494,7 @@ double
libinput_event_tablet_pad_get_ring_position(struct libinput_event_tablet_pad *event);
/**
* @ingroup event_tablet
* @ingroup event_tablet_pad
*
* 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
@ -2260,7 +2511,7 @@ unsigned int
libinput_event_tablet_pad_get_ring_number(struct libinput_event_tablet_pad *event);
/**
* @ingroup event_tablet
* @ingroup event_tablet_pad
*
* Returns the source of the interaction with the ring. If the source is
* @ref LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER, libinput sends a ring
@ -2277,7 +2528,7 @@ enum libinput_tablet_pad_ring_axis_source
libinput_event_tablet_pad_get_ring_source(struct libinput_event_tablet_pad *event);
/**
* @ingroup event_tablet
* @ingroup event_tablet_pad
*
* 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
@ -2300,7 +2551,7 @@ double
libinput_event_tablet_pad_get_strip_position(struct libinput_event_tablet_pad *event);
/**
* @ingroup event_tablet
* @ingroup event_tablet_pad
*
* 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
@ -2317,7 +2568,7 @@ unsigned int
libinput_event_tablet_pad_get_strip_number(struct libinput_event_tablet_pad *event);
/**
* @ingroup event_tablet
* @ingroup event_tablet_pad
*
* Returns the source of the interaction with the strip. If the source is
* @ref LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER, libinput sends a strip
@ -2334,7 +2585,7 @@ enum libinput_tablet_pad_strip_axis_source
libinput_event_tablet_pad_get_strip_source(struct libinput_event_tablet_pad *event);
/**
* @ingroup event_tablet
* @ingroup event_tablet_pad
*
* Return the button number that triggered this event, starting at 0.
* For events that are not of type @ref LIBINPUT_EVENT_TABLET_PAD_BUTTON,
@ -2355,7 +2606,7 @@ uint32_t
libinput_event_tablet_pad_get_button_number(struct libinput_event_tablet_pad *event);
/**
* @ingroup event_tablet
* @ingroup event_tablet_pad
*
* Return the button state of the event.
*
@ -2369,6 +2620,53 @@ libinput_event_tablet_pad_get_button_number(struct libinput_event_tablet_pad *ev
enum libinput_button_state
libinput_event_tablet_pad_get_button_state(struct libinput_event_tablet_pad *event);
/**
* @ingroup event_tablet_pad
*
* Returns the current mode this button, ring, or strip is considered in.
* The mode is a virtual grouping of functionality, usually based on some
* visual feedback like LEDs on the pad. See @ref tablet-pad-modes for
* details. Mode indices start at 0, a device that does not support modes
* always returns 0.
*
* Mode switching is controlled by libinput and more than one mode may exist
* on the tablet. This function returns the mode that this event's button,
* ring or strip is logically grouped in. If the button is the mode toggle
* button and the button event caused a new mode to be toggled, the mode
* returned is the new mode the button is in.
*
* Note that the returned mode is the mode valid as of the time of the
* event. The returned mode may thus be different to the mode returned by
* libinput_tablet_pad_mode_group_get_mode(). See
* libinput_tablet_pad_mode_group_get_mode() for details.
*
* @param event The libinput tablet pad event
* @return the current 0-indexed mode of this button, ring or strip
*
* @see libinput_tablet_pad_mode_group_get_mode
*/
unsigned int
libinput_event_tablet_pad_get_mode(struct libinput_event_tablet_pad *event);
/**
* @ingroup event_tablet_pad
*
* Returns the current mode group this button, ring, or strip is considered in.
* The mode is a virtual grouping of functionality, usually based on some
* visual feedback like LEDs on the pad. See @ref tablet-pad-modes for
* details.
*
* The returned mode group is not refcounted and may become invalid after
* the next call to libinput. Use libinput_tablet_pad_mode_group_ref() and
* libinput_tablet_pad_mode_group_unref() to continue using the handle
* outside of the immediate scope.
*
* @param event The libinput tablet pad event
* @return the current 0-indexed mode of this button, ring or strip
*/
struct libinput_tablet_pad_mode_group *
libinput_event_tablet_pad_get_mode_group(struct libinput_event_tablet_pad *event);
/**
* @ingroup event_tablet
*
@ -2379,7 +2677,7 @@ uint32_t
libinput_event_tablet_pad_get_time(struct libinput_event_tablet_pad *event);
/**
* @ingroup event_tablet
* @ingroup event_tablet_pad
*
* @param event The libinput tablet pad event
* @return The event time for this event in microseconds

View file

@ -258,4 +258,19 @@ LIBINPUT_1.4 {
libinput_device_config_rotation_get_default_angle;
libinput_device_config_rotation_is_available;
libinput_device_config_rotation_set_angle;
libinput_device_tablet_pad_get_mode_group;
libinput_device_tablet_pad_get_num_mode_groups;
libinput_event_tablet_pad_get_mode;
libinput_event_tablet_pad_get_mode_group;
libinput_tablet_pad_mode_group_button_is_toggle;
libinput_tablet_pad_mode_group_get_index;
libinput_tablet_pad_mode_group_get_mode;
libinput_tablet_pad_mode_group_get_num_modes;
libinput_tablet_pad_mode_group_get_user_data;
libinput_tablet_pad_mode_group_has_button;
libinput_tablet_pad_mode_group_has_strip;
libinput_tablet_pad_mode_group_has_ring;
libinput_tablet_pad_mode_group_ref;
libinput_tablet_pad_mode_group_set_user_data;
libinput_tablet_pad_mode_group_unref;
} LIBINPUT_1.3;

View file

@ -50,6 +50,8 @@ liblitest_la_SOURCES = \
litest-device-wacom-bamboo-tablet.c \
litest-device-wacom-cintiq-tablet.c \
litest-device-wacom-cintiq-24hd.c \
litest-device-wacom-cintiq-24hdt-pad.c \
litest-device-wacom-ekr.c \
litest-device-wacom-intuos-tablet.c \
litest-device-wacom-intuos3-pad.c \
litest-device-wacom-intuos5-pad.c \

View file

@ -0,0 +1,148 @@
/*
* 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 <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include "litest.h"
#include "litest-int.h"
static void litest_wacom_cintiq_pad_setup(void)
{
struct litest_device *d;
d = litest_create_device(LITEST_WACOM_CINTIQ_24HDT_PAD);
litest_set_current_device(d);
}
static void
litest_wacom_cintiq_pad_teardown(void)
{
litest_generic_device_teardown();
}
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_THROTTLE, 0, 71, 0, 0, 0 },
{ ABS_MISC, 0, 0, 0, 0, 0 },
{ .value = -1 },
};
static struct input_id input_id = {
.bustype = 0x3,
.vendor = 0x56a,
.product = 0xf8,
.version = 0x110,
};
static int events[] = {
EV_KEY, KEY_PROG1,
EV_KEY, KEY_PROG2,
EV_KEY, KEY_PROG3,
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_9,
EV_KEY, BTN_SOUTH,
EV_KEY, BTN_EAST,
EV_KEY, BTN_C,
EV_KEY, BTN_NORTH,
EV_KEY, BTN_WEST,
EV_KEY, BTN_Z,
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 Cintiq 24 HD touch Pad*\",\\\n"
" ENV{ID_INPUT_TABLET_PAD}=\"1\"\n"
"\n"
"LABEL=\"pad_end\"";
struct litest_test_device litest_wacom_cintiq_24hdt_pad_device = {
.type = LITEST_WACOM_CINTIQ_24HDT_PAD,
.features = LITEST_TABLET_PAD | LITEST_RING,
.shortname = "wacom-cintiq-24hdt-pad",
.setup = litest_wacom_cintiq_pad_setup,
.teardown = litest_wacom_cintiq_pad_teardown,
.interface = &interface,
.name = "Wacom Cintiq 24 HD touch Pad",
.id = &input_id,
.events = events,
.absinfo = absinfo,
.udev_rule = udev_rule,
};

View file

@ -0,0 +1,132 @@
/*
* 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_ekr_setup(void)
{
struct litest_device *d = litest_create_device(LITEST_WACOM_EKR);
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, 0 },
{ .value = -1 },
};
static struct input_id input_id = {
.bustype = 0x3,
.vendor = 0x56a,
.product = 0x331,
};
static int events[] = {
EV_KEY, BTN_0,
EV_KEY, BTN_1,
EV_KEY, BTN_2,
EV_KEY, BTN_3,
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_9,
EV_KEY, BTN_BASE,
EV_KEY, BTN_BASE2,
EV_KEY, BTN_SOUTH,
EV_KEY, BTN_EAST,
EV_KEY, BTN_C,
EV_KEY, BTN_NORTH,
EV_KEY, BTN_WEST,
EV_KEY, BTN_Z,
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 Express Key Remote Pad*\",\\\n"
" ENV{ID_INPUT_TABLET_PAD}=\"1\"\n"
"\n"
"LABEL=\"pad_end\"";
struct litest_test_device litest_wacom_ekr_device = {
.type = LITEST_WACOM_EKR,
.features = LITEST_TABLET_PAD | LITEST_RING,
.shortname = "wacom-ekr",
.setup = litest_wacom_ekr_setup,
.interface = &interface,
.name = "Wacom Express Key Remote Pad",
.id = &input_id,
.events = events,
.absinfo = absinfo,
.udev_rule = udev_rule,
};

View file

@ -384,6 +384,8 @@ extern struct litest_test_device litest_wacom_intuos3_pad_device;
extern struct litest_test_device litest_wacom_intuos5_pad_device;
extern struct litest_test_device litest_keyboard_all_codes_device;
extern struct litest_test_device litest_magicmouse_device;
extern struct litest_test_device litest_wacom_ekr_device;
extern struct litest_test_device litest_wacom_cintiq_24hdt_pad_device;
struct litest_test_device* devices[] = {
&litest_synaptics_clickpad_device,
@ -434,6 +436,8 @@ struct litest_test_device* devices[] = {
&litest_wacom_intuos5_pad_device,
&litest_keyboard_all_codes_device,
&litest_magicmouse_device,
&litest_wacom_ekr_device,
&litest_wacom_cintiq_24hdt_pad_device,
NULL,
};
@ -2083,6 +2087,9 @@ litest_event_type_str(struct libinput_event *event)
case LIBINPUT_EVENT_TABLET_PAD_STRIP:
str = "TABLET PAD STRIP";
break;
case LIBINPUT_EVENT_TABLET_PAD_MODE:
str = "TABLET PAD MODE";
break;
}
return str;
}

View file

@ -201,6 +201,8 @@ enum litest_device_type {
LITEST_WACOM_INTUOS5_PAD,
LITEST_KEYBOARD_ALL_CODES,
LITEST_MAGICMOUSE,
LITEST_WACOM_EKR,
LITEST_WACOM_CINTIQ_24HDT_PAD,
};
enum litest_device_feature {

View file

@ -407,6 +407,230 @@ START_TEST(pad_left_handed_ring)
}
END_TEST
START_TEST(pad_mode_groups)
{
struct litest_device *dev = litest_current_device();
struct libinput_device *device = dev->libinput_device;
struct libinput_tablet_pad_mode_group *group;
int ngroups;
int i;
ngroups = libinput_device_tablet_pad_get_num_mode_groups(device);
ck_assert_int_eq(ngroups, 1);
for (i = 0; i < ngroups; i++) {
group = libinput_device_tablet_pad_get_mode_group(device, i);
ck_assert_notnull(group);
ck_assert_int_eq(libinput_tablet_pad_mode_group_get_index(group),
i);
}
group = libinput_device_tablet_pad_get_mode_group(device, ngroups);
ck_assert(group == NULL);
group = libinput_device_tablet_pad_get_mode_group(device, ngroups + 1);
ck_assert(group == NULL);
}
END_TEST
START_TEST(pad_mode_groups_userdata)
{
struct litest_device *dev = litest_current_device();
struct libinput_device *device = dev->libinput_device;
struct libinput_tablet_pad_mode_group *group;
int rc;
void *userdata = &rc;
group = libinput_device_tablet_pad_get_mode_group(device, 0);
ck_assert(libinput_tablet_pad_mode_group_get_user_data(group) ==
NULL);
libinput_tablet_pad_mode_group_set_user_data(group, userdata);
ck_assert(libinput_tablet_pad_mode_group_get_user_data(group) ==
&rc);
libinput_tablet_pad_mode_group_set_user_data(group, NULL);
ck_assert(libinput_tablet_pad_mode_group_get_user_data(group) ==
NULL);
}
END_TEST
START_TEST(pad_mode_groups_ref)
{
struct litest_device *dev = litest_current_device();
struct libinput_device *device = dev->libinput_device;
struct libinput_tablet_pad_mode_group *group, *g;
group = libinput_device_tablet_pad_get_mode_group(device, 0);
g = libinput_tablet_pad_mode_group_ref(group);
ck_assert_ptr_eq(g, group);
/* We don't expect this to be freed. Any leaks should be caught by
* valgrind. */
g = libinput_tablet_pad_mode_group_unref(group);
ck_assert_ptr_eq(g, group);
}
END_TEST
START_TEST(pad_mode_group_mode)
{
struct litest_device *dev = litest_current_device();
struct libinput_device *device = dev->libinput_device;
struct libinput_tablet_pad_mode_group *group;
int ngroups;
unsigned int nmodes, mode;
ngroups = libinput_device_tablet_pad_get_num_mode_groups(device);
ck_assert_int_ge(ngroups, 1);
group = libinput_device_tablet_pad_get_mode_group(device, 0);
nmodes = libinput_tablet_pad_mode_group_get_num_modes(group);
ck_assert_int_eq(nmodes, 1);
mode = libinput_tablet_pad_mode_group_get_mode(group);
ck_assert_int_lt(mode, nmodes);
}
END_TEST
START_TEST(pad_mode_group_has)
{
struct litest_device *dev = litest_current_device();
struct libinput_device *device = dev->libinput_device;
struct libinput_tablet_pad_mode_group *group;
int ngroups, nbuttons, nrings, nstrips;
int i, b, r, s;
ngroups = libinput_device_tablet_pad_get_num_mode_groups(device);
ck_assert_int_ge(ngroups, 1);
nbuttons = libinput_device_tablet_pad_get_num_buttons(device);
nrings = libinput_device_tablet_pad_get_num_rings(device);
nstrips = libinput_device_tablet_pad_get_num_strips(device);
for (b = 0; b < nbuttons; b++) {
bool found = false;
for (i = 0; i < ngroups; i++) {
group = libinput_device_tablet_pad_get_mode_group(device,
i);
if (libinput_tablet_pad_mode_group_has_button(group,
b)) {
ck_assert(!found);
found = true;
}
}
ck_assert(found);
}
for (s = 0; s < nstrips; s++) {
bool found = false;
for (i = 0; i < ngroups; i++) {
group = libinput_device_tablet_pad_get_mode_group(device,
i);
if (libinput_tablet_pad_mode_group_has_strip(group,
s)) {
ck_assert(!found);
found = true;
}
}
ck_assert(found);
}
for (r = 0; r < nrings; r++) {
bool found = false;
for (i = 0; i < ngroups; i++) {
group = libinput_device_tablet_pad_get_mode_group(device,
i);
if (libinput_tablet_pad_mode_group_has_ring(group,
r)) {
ck_assert(!found);
found = true;
}
}
ck_assert(found);
}
}
END_TEST
START_TEST(pad_mode_group_has_invalid)
{
struct litest_device *dev = litest_current_device();
struct libinput_device *device = dev->libinput_device;
struct libinput_tablet_pad_mode_group* group;
int ngroups, nbuttons, nrings, nstrips;
int i;
int rc;
ngroups = libinput_device_tablet_pad_get_num_mode_groups(device);
ck_assert_int_ge(ngroups, 1);
nbuttons = libinput_device_tablet_pad_get_num_buttons(device);
nrings = libinput_device_tablet_pad_get_num_rings(device);
nstrips = libinput_device_tablet_pad_get_num_strips(device);
for (i = 0; i < ngroups; i++) {
group = libinput_device_tablet_pad_get_mode_group(device, i);
rc = libinput_tablet_pad_mode_group_has_button(group,
nbuttons);
ck_assert_int_eq(rc, 0);
rc = libinput_tablet_pad_mode_group_has_button(group,
nbuttons + 1);
ck_assert_int_eq(rc, 0);
rc = libinput_tablet_pad_mode_group_has_button(group,
0x1000000);
ck_assert_int_eq(rc, 0);
}
for (i = 0; i < ngroups; i++) {
group = libinput_device_tablet_pad_get_mode_group(device, i);
rc = libinput_tablet_pad_mode_group_has_strip(group,
nstrips);
ck_assert_int_eq(rc, 0);
rc = libinput_tablet_pad_mode_group_has_strip(group,
nstrips + 1);
ck_assert_int_eq(rc, 0);
rc = libinput_tablet_pad_mode_group_has_strip(group,
0x1000000);
ck_assert_int_eq(rc, 0);
}
for (i = 0; i < ngroups; i++) {
group = libinput_device_tablet_pad_get_mode_group(device, i);
rc = libinput_tablet_pad_mode_group_has_ring(group,
nrings);
ck_assert_int_eq(rc, 0);
rc = libinput_tablet_pad_mode_group_has_ring(group,
nrings + 1);
ck_assert_int_eq(rc, 0);
rc = libinput_tablet_pad_mode_group_has_ring(group,
0x1000000);
ck_assert_int_eq(rc, 0);
}
}
END_TEST
START_TEST(pad_mode_group_has_no_toggle)
{
struct litest_device *dev = litest_current_device();
struct libinput_device *device = dev->libinput_device;
struct libinput_tablet_pad_mode_group* group;
int ngroups, nbuttons;
int i, b;
ngroups = libinput_device_tablet_pad_get_num_mode_groups(device);
ck_assert_int_ge(ngroups, 1);
/* Button must not be toggle buttons */
nbuttons = libinput_device_tablet_pad_get_num_buttons(device);
for (i = 0; i < ngroups; i++) {
group = libinput_device_tablet_pad_get_mode_group(device, i);
for (b = 0; b < nbuttons; b++) {
ck_assert(!libinput_tablet_pad_mode_group_button_is_toggle(
group,
b));
}
}
}
END_TEST
void
litest_setup_tests(void)
{
@ -428,4 +652,12 @@ litest_setup_tests(void)
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 */
litest_add("pad:modes", pad_mode_groups, LITEST_TABLET_PAD, LITEST_ANY);
litest_add("pad:modes", pad_mode_groups_userdata, LITEST_TABLET_PAD, LITEST_ANY);
litest_add("pad:modes", pad_mode_groups_ref, LITEST_TABLET_PAD, LITEST_ANY);
litest_add("pad:modes", pad_mode_group_mode, LITEST_TABLET_PAD, LITEST_ANY);
litest_add("pad:modes", pad_mode_group_has, LITEST_TABLET_PAD, LITEST_ANY);
litest_add("pad:modes", pad_mode_group_has_invalid, LITEST_TABLET_PAD, LITEST_ANY);
litest_add("pad:modes", pad_mode_group_has_no_toggle, LITEST_TABLET_PAD, LITEST_ANY);
}

View file

@ -130,6 +130,9 @@ print_event_header(struct libinput_event *ev)
case LIBINPUT_EVENT_TABLET_PAD_STRIP:
type = "TABLET_PAD_STRIP";
break;
case LIBINPUT_EVENT_TABLET_PAD_MODE:
type = "TABLET_PAD_MODE";
break;
}
printf("%-7s %-16s ", libinput_device_get_sysname(dev), type);
@ -232,16 +235,18 @@ print_device_notify(struct libinput_event *ev)
if (libinput_device_has_capability(dev,
LIBINPUT_DEVICE_CAP_TABLET_PAD)) {
int nbuttons, nstrips, nrings;
int nbuttons, nstrips, nrings, ngroups;
nbuttons = libinput_device_tablet_pad_get_num_buttons(dev);
nstrips = libinput_device_tablet_pad_get_num_strips(dev);
nrings = libinput_device_tablet_pad_get_num_rings(dev);
ngroups = libinput_device_tablet_pad_get_num_mode_groups(dev);
printf(" buttons:%d strips:%d rings:%d",
printf(" buttons:%d strips:%d rings:%d mode groups:%d",
nbuttons,
nstrips,
nrings);
nrings,
ngroups);
}
printf("\n");
@ -604,14 +609,25 @@ static void
print_tablet_pad_button_event(struct libinput_event *ev)
{
struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
struct libinput_tablet_pad_mode_group *group;
enum libinput_button_state state;
unsigned int button, mode;
print_event_time(libinput_event_tablet_pad_get_time(p));
button = libinput_event_tablet_pad_get_button_number(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");
mode = libinput_event_tablet_pad_get_mode(p);
printf("%3d %s (mode %d)",
button,
state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released",
mode);
group = libinput_event_tablet_pad_get_mode_group(p);
if (libinput_tablet_pad_mode_group_button_is_toggle(group, button))
printf(" <mode toggle>");
printf("\n");
}
static void
@ -619,6 +635,7 @@ 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>";
unsigned int mode;
print_event_time(libinput_event_tablet_pad_get_time(p));
@ -631,10 +648,12 @@ print_tablet_pad_ring_event(struct libinput_event *ev)
break;
}
printf("ring %d position %.2f (source %s)\n",
mode = libinput_event_tablet_pad_get_mode(p);
printf("ring %d position %.2f (source %s) (mode %d)\n",
libinput_event_tablet_pad_get_ring_number(p),
libinput_event_tablet_pad_get_ring_position(p),
source);
source,
mode);
}
static void
@ -642,6 +661,7 @@ 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>";
unsigned int mode;
print_event_time(libinput_event_tablet_pad_get_time(p));
@ -654,10 +674,28 @@ print_tablet_pad_strip_event(struct libinput_event *ev)
break;
}
printf("strip %d position %.2f (source %s)\n",
mode = libinput_event_tablet_pad_get_mode(p);
printf("strip %d position %.2f (source %s) (mode %d)\n",
libinput_event_tablet_pad_get_strip_number(p),
libinput_event_tablet_pad_get_strip_position(p),
source);
source,
mode);
}
static void
print_tablet_pad_mode_event(struct libinput_event *ev)
{
struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
struct libinput_tablet_pad_mode_group *group;
unsigned int mode;
print_event_time(libinput_event_tablet_pad_get_time(p));
group = libinput_event_tablet_pad_get_mode_group(p);
mode = libinput_event_tablet_pad_get_mode(p);
printf("group %d mode %d\n",
libinput_tablet_pad_mode_group_get_index(group),
mode);
}
static int
@ -748,6 +786,9 @@ handle_and_print_events(struct libinput *li)
case LIBINPUT_EVENT_TABLET_PAD_STRIP:
print_tablet_pad_strip_event(ev);
break;
case LIBINPUT_EVENT_TABLET_PAD_MODE:
print_tablet_pad_mode_event(ev);
break;
}
libinput_event_destroy(ev);

View file

@ -843,6 +843,7 @@ handle_event_libinput(GIOChannel *source, GIOCondition condition, gpointer data)
case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
case LIBINPUT_EVENT_TABLET_PAD_RING:
case LIBINPUT_EVENT_TABLET_PAD_STRIP:
case LIBINPUT_EVENT_TABLET_PAD_MODE:
break;
}