Merge branch 'wip/macro'

This commit is contained in:
Benjamin Tissoires
2015-09-10 13:25:42 -04:00
11 changed files with 618 additions and 139 deletions

6
TODO
View File

@@ -17,3 +17,9 @@ require HID parsing in libratbag for relatively little benefit. The only
advantage we really get out of it is that a configuration UI would be able
to update itself if a user presses a button to e.g. change the profile while
the UI is running.
Macro support:
- enhance doctext
- add API support for name/groups
- revamp the API?
- add command to set a macro in ratbag-command

View File

@@ -48,7 +48,17 @@
xlink:href="#linearGradient4449"
id="linearGradient4562"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.698701,0,0,1.698701,6.5113742,644.61147)"
gradientTransform="matrix(1.698701,0,0,1.698701,340.78058,475.26804)"
x1="31.968746"
y1="18.546629"
x2="31.968746"
y2="29.577879" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4449"
id="linearGradient4215"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.698701,0,0,1.698701,111.54723,131.64433)"
x1="31.968746"
y1="18.546629"
x2="31.968746"
@@ -56,22 +66,13 @@
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4336"
id="linearGradient4616"
id="linearGradient4219"
gradientUnits="userSpaceOnUse"
x1="97.085503"
y1="74.08123"
x2="95.471596"
y2="200.83122" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4449"
id="linearGradient4618"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.698701,0,0,1.698701,111.54723,46.23633)"
x1="31.968746"
y1="18.546629"
x2="31.968746"
y2="29.577879" />
y2="200.83122"
gradientTransform="translate(0,85.407996)" />
</defs>
<sodipodi:namedview
id="base"
@@ -81,10 +82,10 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.67909341"
inkscape:cx="740.12675"
inkscape:cy="484.37676"
inkscape:cx="650.93837"
inkscape:cy="527.80453"
inkscape:document-units="px"
inkscape:current-layer="layer4"
inkscape:current-layer="layer6"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
@@ -114,11 +115,11 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(522.78594,97.359194)"
style="display:inline"
sodipodi:insensitive="true">
style="display:inline">
<g
id="g4271"
style="fill:#000000;fill-opacity:1;stroke:none">
style="fill:#000000;fill-opacity:1;stroke:none"
transform="translate(0,85.407996)">
<path
sodipodi:nodetypes="cczcccccccc"
inkscape:connector-curvature="0"
@@ -137,13 +138,13 @@
</g>
<path
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 454.66443,267.09487 c -1.36013,24.01275 -2.08377,48.50286 -4.67196,71.59456 -2.99078,6.00192 -6.27359,9.95971 -9.59645,13.63706 l -17.17259,0 7.07107,-84.85281 z"
d="m 454.66443,352.50287 c -1.36013,24.01275 -2.08377,48.50286 -4.67196,71.59456 -2.99078,6.00192 -6.27359,9.95971 -9.59645,13.63706 l -17.17259,0 7.07107,-84.85281 z"
id="path4251"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
<path
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 438.62826,355.73575 -0.37881,7.82869 8.9651,7.3236 -2.77792,38.13326 -11.36421,12.12183 -0.37881,36.61803 -3.03046,4.54569 -18.43528,0 0,-106.69736 z"
d="m 438.62826,441.14375 -0.37881,7.82869 8.9651,7.3236 -2.77792,38.13326 -11.36421,12.12183 -0.37881,36.61803 -3.03046,4.54569 -18.43528,0 0,-106.69736 z"
id="path4253"
inkscape:connector-curvature="0" />
<use
@@ -151,14 +152,14 @@
y="0"
xlink:href="#path4251"
id="use4275"
transform="matrix(-1,0,0,1,580.95786,0)"
transform="matrix(-1,0,0,1,580.95786,4.8707099e-7)"
width="100%"
height="100%" />
<ellipse
style="fill:#000000;fill-opacity:1;stroke:#ff0000;stroke-opacity:1"
id="path4243"
cx="290.47894"
cy="145.66577"
cy="231.07376"
rx="57.5"
ry="36.875" />
<use
@@ -166,23 +167,23 @@
y="0"
xlink:href="#path4253"
id="use4277"
transform="matrix(-1,0,0,1,580.95786,0)"
transform="matrix(-1,0,0,1,580.95786,4.8707099e-7)"
width="100%"
height="100%" />
<path
style="fill:#282828;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 287.12424,172.69727 0.33399,-51.40625 c -49.49582,9.30987 -55.75059,5.0826 -65.29102,1.07031 -24.72942,18.12217 -56.91711,38.05902 -92.98242,48.79297 -3.12319,24.73221 -3.43113,59.04672 -2.64063,84.07422 24.02292,13.33912 22.23564,42.84183 24.32227,61.05859 2.08662,18.21675 9.10156,119.0332 9.10156,119.0332 l -3.28125,27.4375 29.4375,54.3711 c -0.20477,8.84869 -0.59006,18.78502 -3.83008,47.24609 -9.03868,2.58062 -17.44268,1.97853 -25.29101,-1.39258 0.11517,13.78573 -0.8627,27.56815 0.71875,41.27539 14.20182,16.9502 20.70885,34.21986 70.98828,70.96485 l 8.20703,14.6914 c 16.51245,9.42952 29.26306,14.71639 53.5625,18.88477 24.29944,-4.16838 37.05005,-9.45525 53.5625,-18.88477 l 8.20703,-14.6914 c 50.27943,-36.74499 56.78646,-54.01465 70.98828,-70.96485 1.58145,-13.70724 0.60163,-27.48966 0.7168,-41.27539 -7.84833,3.37111 -16.25038,3.9732 -25.28906,1.39258 -3.24002,-28.46107 -3.62531,-38.3974 -3.83008,-47.24609 l 29.43555,-54.3711 -3.2793,-27.4375 c 0,0 7.01494,-100.81645 9.10156,-119.0332 2.08663,-18.21676 0.29739,-47.71947 24.32031,-61.05859 0.7905,-25.0275 0.48452,-59.34201 -2.63867,-84.07422 -36.06531,-10.73395 -68.25495,-30.6708 -92.98437,-48.79297 -9.54043,4.01229 -15.79325,8.23956 -65.28907,-1.07031 l 0.33399,51.40625 z"
d="m 287.12424,258.10527 0.33399,-51.40625 c -49.49582,9.30987 -55.75059,5.0826 -65.29102,1.07031 -24.72942,18.12217 -56.91711,38.05902 -92.98242,48.79297 -3.12319,24.73221 -3.43113,59.04672 -2.64063,84.07422 24.02292,13.33912 22.23564,42.84183 24.32227,61.05859 2.08662,18.21675 9.10156,119.0332 9.10156,119.0332 l -3.28125,27.4375 29.4375,54.3711 c -0.20477,8.84869 -0.59006,18.78502 -3.83008,47.24609 -9.03868,2.58062 -17.44268,1.97853 -25.29101,-1.39258 0.11517,13.78573 -0.8627,27.56815 0.71875,41.27539 14.20182,16.9502 20.70885,34.21986 70.98828,70.96485 l 8.20703,14.6914 c 16.51245,9.42952 29.26306,14.71639 53.5625,18.88477 24.29944,-4.16838 37.05005,-9.45525 53.5625,-18.88477 l 8.20703,-14.6914 c 50.27943,-36.74499 56.78646,-54.01465 70.98828,-70.96485 1.58145,-13.70724 0.60163,-27.48966 0.7168,-41.27539 -7.84833,3.37111 -16.25038,3.9732 -25.28906,1.39258 -3.24002,-28.46107 -3.62531,-38.3974 -3.83008,-47.24609 l 29.43555,-54.3711 -3.2793,-27.4375 c 0,0 7.01494,-100.81645 9.10156,-119.0332 2.08663,-18.21676 0.29739,-47.71947 24.32031,-61.05859 0.7905,-25.0275 0.48452,-59.34201 -2.63867,-84.07422 -36.06531,-10.73395 -68.25495,-30.6708 -92.98437,-48.79297 -9.54043,4.01229 -15.79325,8.23956 -65.28907,-1.07031 l 0.33399,51.40625 z"
id="path3441"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccscccccccccccccccccscccccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 290.44411,172.36782 0,148.84598"
d="m 290.44411,257.77582 0,148.84598"
id="path4289"
inkscape:connector-curvature="0" />
<path
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 300.46818,383.07617 16.60743,25.35742 30.71289,0 -24.28516,-81.07226 -33.02344,-17.13086 -33.02539,17.13086 -24.28515,81.07226 30.71484,0 16.60742,-25.35742 z"
d="m 300.46818,468.48417 16.60743,25.35742 30.71289,0 -24.28516,-81.07226 -33.02344,-17.13086 -33.02539,17.13086 -24.28515,81.07226 30.71484,0 16.60742,-25.35742 z"
id="path4247"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
@@ -192,7 +193,7 @@
width="31.607143"
height="75.178574"
x="274.67535"
y="179.50507"
y="264.91306"
rx="3.25"
ry="3.25" />
</g>
@@ -201,11 +202,10 @@
id="layer3"
inkscape:label="Actions"
style="display:inline"
transform="translate(647.36582,205.64997)"
sodipodi:insensitive="true">
transform="translate(647.36582,205.64997)">
<path
style="fill:url(#linearGradient4616);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 152.84766,24.875 C 135.03662,27.904338 116.27195,31.045507 98.603516,25.521484 72.674241,44.350548 44.372083,60.275381 13.880859,70.394531 11.612881,94.013866 11.08668,117.84454 12.033203,141.4707 c 18.144518,13.21721 22.915716,37.18855 23.587891,58.32032 1.804576,24.12767 4.185653,48.26187 6.046875,72.41992 l 118.802731,0.0762 0,-125.89453 -7.125,0 c -1.8005,0 -3.25,-1.4495 -3.25,-3.25 l 0,-68.677736 c 0,-1.8005 1.4495,-3.25 3.25,-3.25 l 2.79297,0 c -3.65158,-6.86961 -3.48047,-22.710991 -3.48047,-29.125 0,-8.307342 0.18214,-11.475988 0.18946,-17.214844 z"
style="fill:url(#linearGradient4219);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 152.84766,110.283 c -17.81104,3.02933 -36.57571,6.1705 -54.244144,0.64648 -25.929275,18.82906 -54.231433,34.7539 -84.722657,44.87305 -2.267978,23.61933 -2.794179,47.45001 -1.847656,71.07617 18.144518,13.21721 22.915716,37.18855 23.587891,58.32032 1.804576,24.12767 4.185653,48.26187 6.046875,72.41992 l 118.802731,0.0762 0,-125.89453 -7.125,0 c -1.8005,0 -3.25,-1.4495 -3.25,-3.25 l 0,-68.67774 c 0,-1.8005 1.4495,-3.25 3.25,-3.25 l 2.79297,0 c -3.65158,-6.86961 -3.48047,-22.71099 -3.48047,-29.125 0,-8.30734 0.18214,-11.47599 0.18946,-17.21484 z"
id="path4311"
inkscape:connector-curvature="0" />
<use
@@ -213,43 +213,43 @@
y="0"
xlink:href="#path4311"
id="use4348"
transform="matrix(-1,0,0,1,332.05619,0)"
transform="matrix(-1,0,0,1,332.05619,4.8707099e-7)"
width="100%"
height="100%" />
<circle
style="fill:#898989;fill-opacity:1;stroke:none;stroke-opacity:1"
id="path4352"
cx="165.89903"
cy="108.80357"
cy="194.21156"
r="13.13577" />
<path
style="fill:#898989;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 137.89648,223.23047 c -7.08138,23.63737 -14.16276,47.27474 -21.24414,70.91211 6.46875,0 12.9375,0 19.40625,0 5.5381,-8.45225 11.07362,-16.9062 16.61329,-25.35742 8.81901,0 17.63802,0 26.45703,0 5.53967,8.45122 11.07518,16.90517 16.61328,25.35742 6.4681,0 12.9362,0 19.40429,0 -7.08138,-23.63802 -14.16276,-47.27604 -21.24414,-70.91406 -9.33398,-4.84245 -18.66797,-9.6849 -28.00195,-14.52735 -9.33463,4.8431 -18.66927,9.6862 -28.00391,14.5293 z"
d="m 137.89648,308.63847 c -7.08138,23.63737 -14.16276,47.27474 -21.24414,70.91211 6.46875,0 12.9375,0 19.40625,0 5.5381,-8.45225 11.07362,-16.9062 16.61329,-25.35742 8.81901,0 17.63802,0 26.45703,0 5.53967,8.45122 11.07518,16.90517 16.61328,25.35742 6.4681,0 12.9362,0 19.40429,0 -7.08138,-23.63802 -14.16276,-47.27604 -21.24414,-70.91406 -9.33398,-4.84245 -18.66797,-9.6849 -28.00195,-14.52735 -9.33463,4.8431 -18.66927,9.6862 -28.00391,14.5293 z"
id="path4357"
inkscape:connector-curvature="0" />
<path
style="fill:#898989;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 10.537109,162.63672 c -2.2402592,0.0287 -3.9856276,0.53324 -4.490234,2.23242 l 0.1484375,2.74414 c 1.566854,20.99222 0.9583123,42.50038 4.9707035,63.15039 2.505291,3.63263 4.593974,10.22639 10.0625,9.10547 2.27923,-0.28382 5.935234,1.35787 7.783203,-0.11133 -0.110687,-1.42127 -0.227935,-3.00203 -0.335938,-4.37109 -1.747534,-15.80777 -2.957208,-31.72139 -4.207031,-47.62695 -0.981314,-8.30104 -2.720121,-16.92373 -6.697266,-24.52539 -2.423075,-0.21119 -5.059619,-0.62548 -7.234375,-0.59766 z"
d="m 10.537109,248.04472 c -2.2402592,0.0287 -3.9856276,0.53324 -4.490234,2.23242 l 0.1484375,2.74414 c 1.566854,20.99222 0.9583123,42.50038 4.9707035,63.15039 2.505291,3.63263 4.593974,10.22639 10.0625,9.10547 2.27923,-0.28382 5.935234,1.35787 7.783203,-0.11133 -0.110687,-1.42127 -0.227935,-3.00203 -0.335938,-4.37109 -1.747534,-15.80777 -2.957208,-31.72139 -4.207031,-47.62695 -0.981314,-8.30104 -2.720121,-16.92373 -6.697266,-24.52539 -2.423075,-0.21119 -5.059619,-0.62548 -7.234375,-0.59766 z"
id="use4396"
inkscape:connector-curvature="0" />
<path
style="fill:#898989;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 29.908203,251.38867 c -2.498699,0.0115 -4.997394,0.0237 -7.496094,0.0352 1.076291,6.12748 -5.106457,9.59114 -8.654297,13.10351 -0.801383,7.60601 1.388334,15.20355 1.240235,22.90625 0.386982,5.74471 -0.452066,12.90012 5.291015,16.36133 4.914007,3.76099 8.544715,9.60791 7.142579,15.97266 0.546689,9.90826 -1.025444,20.199 1.144531,29.53125 1.282147,0.72035 2.637282,0.97704 4.027344,1.01562 l 2.785156,-23.28515 c 0,0 -2.865754,-41.1439 -5.480469,-75.64063 z"
d="m 29.908203,336.79667 c -2.498699,0.0115 -4.997394,0.0237 -7.496094,0.0352 1.076291,6.12748 -5.106457,9.59114 -8.654297,13.10351 -0.801383,7.60601 1.388334,15.20355 1.240235,22.90625 0.386982,5.74471 -0.452066,12.90012 5.291015,16.36133 4.914007,3.76099 8.544715,9.60791 7.142579,15.97266 0.546689,9.90826 -1.025444,20.199 1.144531,29.53125 1.282147,0.72035 2.637282,0.97704 4.027344,1.01562 l 2.785156,-23.28515 c 0,0 -2.865754,-41.1439 -5.480469,-75.64063 z"
id="use4398"
inkscape:connector-curvature="0" />
<path
style="fill:#898989;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 325.85938,162.87109 c -3.91081,0.0612 -7.82162,0.12234 -11.73243,0.1836 -3.99052,7.54373 -5.75751,16.10502 -6.7539,24.36914 l -4.36914,52.40039 c 4.98584,0.0372 11.46228,2.25512 14.20312,-3.56055 7.33121,-8.30294 4.7292,-20.04995 6.30078,-30.04492 0.96913,-14.44425 1.56431,-28.8791 2.35157,-43.34766 z"
d="m 325.85938,248.27909 c -3.91081,0.0612 -7.82162,0.12234 -11.73243,0.1836 -3.99052,7.54373 -5.75751,16.10502 -6.7539,24.36914 l -4.36914,52.40039 c 4.98584,0.0372 11.46228,2.25512 14.20312,-3.56055 7.33121,-8.30294 4.7292,-20.04995 6.30078,-30.04492 0.96913,-14.44425 1.56431,-28.8791 2.35157,-43.34766 z"
id="path4404"
inkscape:connector-curvature="0" />
<path
style="fill:#898989;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 305.09766,251.18164 c -1.06262,0.008 -2.13053,0.0756 -3.20118,0.15039 -2.61591,34.50868 -5.48437,75.69727 -5.48437,75.69727 l 2.78906,23.33203 c 1.63662,-0.029 3.18696,-0.39571 4.5293,-1.54883 1.37166,-12.4594 -0.25013,-25.66177 1.20508,-38.00586 4.53808,-5.87556 13.22025,-10.32447 11.56445,-19.05078 0.39672,-9.20118 1.90359,-18.85755 1.6582,-27.79492 -4.1312,-2.80281 -9.9803,-6.58258 -8.65039,-12.34961 -1.44987,-0.34149 -2.92443,-0.44095 -4.41015,-0.42969 z"
d="m 305.09766,336.58964 c -1.06262,0.008 -2.13053,0.0756 -3.20118,0.15039 -2.61591,34.50868 -5.48437,75.69727 -5.48437,75.69727 l 2.78906,23.33203 c 1.63662,-0.029 3.18696,-0.39571 4.5293,-1.54883 1.37166,-12.4594 -0.25013,-25.66177 1.20508,-38.00586 4.53808,-5.87556 13.22025,-10.32447 11.56445,-19.05078 0.39672,-9.20118 1.90359,-18.85755 1.6582,-27.79492 -4.1312,-2.80281 -9.9803,-6.58258 -8.65039,-12.34961 -1.44987,-0.34149 -2.92443,-0.44095 -4.41015,-0.42969 z"
id="path4406"
inkscape:connector-curvature="0" />
<path
style="fill:url(#linearGradient4618);fill-opacity:1;stroke:none;stroke-opacity:1"
d="m 165.89904,72.108343 -3.21162,5.563908 -3.21159,5.560593 3.66282,0 0,11.761513 2.76039,-1.592532 2.76039,1.592532 0,-11.761513 3.66282,0 -3.21161,-5.560593 -3.2116,-5.563908 z"
style="fill:url(#linearGradient4215);fill-opacity:1;stroke:none;stroke-opacity:1"
d="m 165.89904,157.51634 -3.21162,5.56391 -3.21159,5.56059 3.66282,0 0,11.76151 2.76039,-1.59253 2.76039,1.59253 0,-11.76151 3.66282,0 -3.21161,-5.56059 -3.2116,-5.56391 z"
id="path4441"
inkscape:connector-curvature="0" />
<use
@@ -257,7 +257,7 @@
y="0"
xlink:href="#path4441"
id="use4460"
transform="matrix(1,0,0,-1,-4.295044e-6,217.48411)"
transform="matrix(1,0,0,-1,-4.295044e-6,388.30011)"
width="100%"
height="100%" />
</g>
@@ -270,65 +270,58 @@
<path
inkscape:connector-curvature="0"
id="path4556"
d="m 60.863184,670.48348 -3.21162,5.56391 -3.21159,5.56059 3.66282,0 0,11.76151 2.76039,-1.59253 2.76039,1.59253 0,-11.76151 3.66282,0 -3.21161,-5.56059 -3.2116,-5.56391 z"
d="m 395.13239,501.14005 -3.21162,5.56391 -3.21159,5.56059 3.66282,0 0,11.76151 2.76039,-1.59253 2.76039,1.59253 0,-11.76151 3.66282,0 -3.21161,-5.56059 -3.2116,-5.56391 z"
style="display:inline;fill:url(#linearGradient4562);fill-opacity:1;stroke:none;stroke-opacity:1" />
<use
style="display:inline"
height="100%"
width="100%"
transform="matrix(1.0000001,0,0,-1.0000001,-105.03587,821.51613)"
transform="matrix(1.0000001,0,0,-1.0000001,229.23333,737.5807)"
id="use4558"
xlink:href="#path4441"
y="0"
x="0" />
<path
transform="translate(-1.4139904e-6,3.480231e-6)"
style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 164.75586,242.51221 115.08162,-115.08161 151.31733,0"
d="m 164.75586,327.92021 115.08162,-115.08161 95.36037,0"
id="path4546"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
transform="translate(-1.4139904e-6,3.480231e-6)"
style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 77.1295,86.12178 32.95296,-62.60592"
d="M 77.129499,171.52978 32.952959,22.802079"
id="path4211"
inkscape:connector-curvature="0" />
<path
transform="translate(-1.4139904e-6,3.480231e-6)"
style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 165.48259,109.68261 32.39613,0 0,-238.55334"
d="m 165.48259,195.09061 32.39613,0 0,-238.553341"
id="path4213"
inkscape:connector-curvature="0" />
<path
transform="translate(-1.4139904e-6,3.480231e-6)"
style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 256.78078,74.34137 333.77774,-59.02128"
d="M 256.78078,159.74937 333.77774,26.386719"
id="path4215"
inkscape:connector-curvature="0" />
<path
transform="translate(-1.4139904e-6,3.480231e-6)"
style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 431.111,206.09773 -117.63699,0"
d="m 375.15404,291.50573 -61.68003,0"
id="path4221"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
transform="translate(-1.4139904e-6,3.480231e-6)"
style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 431.24018,278.97674 -120.13434,0"
d="m 375.28322,364.38474 -64.17738,0"
id="path4225"
inkscape:connector-curvature="0" />
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
transform="translate(-1.4139904e-6,3.480231e-6)"
style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M -175.41308,360.75263 16.01861,196.56314"
d="M -175.41308,446.16063 16.018609,281.97114"
id="path4227"
inkscape:connector-curvature="0" />
<path
transform="translate(-1.4139904e-6,3.480231e-6)"
style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M -177.6219,441.00668 23.38137,281.23485"
d="M -177.6219,526.41468 23.381369,366.64285"
id="path4229"
inkscape:connector-curvature="0" />
</g>
@@ -342,21 +335,21 @@
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40.00000381px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="27.097548"
y="-68.740425"
y="16.66757"
id="text4473"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
x="27.097548"
y="-68.740425"
y="16.66757"
id="tspan4217">Button0</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4477"
y="-63.554081"
y="21.853914"
x="336.33337"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="-63.554081"
y="21.853914"
x="336.33337"
id="tspan4479"
sodipodi:role="line">Button1</tspan></text>
@@ -364,21 +357,21 @@
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40.00000381px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="196.44098"
y="-136.41295"
y="-51.004951"
id="text4481"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4483"
x="196.44098"
y="-136.41295">Button2</tspan></text>
y="-51.004951">Button2</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4485"
y="360.60565"
y="446.01364"
x="-176.11456"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40.00000381px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="360.60565"
y="446.01364"
x="-176.11456"
id="tspan4487"
sodipodi:role="line">Button3</tspan></text>
@@ -386,71 +379,71 @@
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40.00000381px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:end;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:end;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="-177.07159"
y="440.89215"
y="526.30017"
id="text4489"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4491"
x="-177.07159"
y="440.89215">Button4</tspan></text>
y="526.30017">Button4</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4493"
y="127.2711"
x="431.31293"
y="212.67909"
x="375.72412"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="127.2711"
x="431.31293"
y="212.67909"
x="375.72412"
id="tspan4495"
sodipodi:role="line">Button5</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="431.31293"
y="203.40361"
x="375.72412"
y="288.81161"
id="text4497"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4499"
x="431.31293"
y="203.40361">Button6</tspan></text>
x="375.72412"
y="288.81161">Button6</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4501"
y="279.00879"
x="431.31293"
y="364.41678"
x="375.72412"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="279.00879"
x="431.31293"
y="364.41678"
x="375.72412"
id="tspan4503"
sodipodi:role="line">Button7</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="83.054512"
y="695.77332"
x="417.32373"
y="526.42987"
id="text4505"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4507"
x="83.054512"
y="695.77332">Button8</tspan></text>
x="417.32373"
y="526.42987">Button8</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4509"
y="752.49896"
x="83.054512"
y="583.15552"
x="417.32373"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="752.49896"
x="83.054512"
y="583.15552"
x="417.32373"
id="tspan4511"
sodipodi:role="line">Button9</tspan></text>
<g
id="g4602"
transform="translate(-140.12576,-219.76978)">
transform="translate(-140.12576,-153.50496)">
<text
sodipodi:linespacing="125%"
id="text4572"
@@ -524,8 +517,37 @@
width="323.85489"
height="479.4184"
x="-615.48309"
y="-182.907"
y="-116.64217"
rx="10.321068"
ry="10.321068" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family: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="-591.40881"
y="625.81189"
id="text4211"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4213"
x="-591.40881"
y="625.81189">Current Profile</tspan></text>
</g>
<g
inkscape:groupmode="layer"
id="layer6"
inkscape:label="Title">
<text
transform="translate(647.36582,205.64997)"
xml:space="preserve"
style="display:inline;font-style:normal;font-weight:normal;font-size:40px;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="-271.95749"
y="-131.81583"
id="text4223"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4225"
x="-271.95749"
y="-131.81583"
style="font-size:70.00000763px">Etekcity Scroll Alpha</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -71,10 +71,10 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.70710678"
inkscape:cx="705.88437"
inkscape:cy="617.7106"
inkscape:cx="672.09896"
inkscape:cy="504.57351"
inkscape:document-units="px"
inkscape:current-layer="layer5"
inkscape:current-layer="layer2"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
@@ -368,4 +368,22 @@
rx="10.321068"
ry="10.321068" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Title">
<text
transform="translate(647.36582,205.64997)"
xml:space="preserve"
style="display:inline;font-style:normal;font-weight:normal;font-size:40px;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="-261.24213"
y="-97.912132"
id="text4223"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4225"
x="-261.24213"
y="-97.912132"
style="font-size:70.00000763px">Logitech MX Master</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -52,6 +52,8 @@
#define ETEKCITY_CONFIG_SETTINGS 0x10
#define ETEKCITY_CONFIG_KEY_MAPPING 0x20
#define ETEKCITY_MAX_MACRO_LENGTH 50
struct etekcity_settings_report {
uint8_t reportID;
uint8_t twentyHeight;
@@ -75,13 +77,13 @@ struct etekcity_macro {
uint8_t heightytwo;
uint8_t profile;
uint8_t button_index;
uint8_t one;
uint8_t active;
char name[24];
uint8_t length;
struct {
uint8_t keycode;
uint8_t flag;
} keys[50];
} keys[ETEKCITY_MAX_MACRO_LENGTH];
} __attribute__((packed));
struct etekcity_data {
@@ -464,7 +466,7 @@ etekcity_read_profile(struct ratbag_profile *profile, unsigned int index)
struct etekcity_settings_report *setting_report;
uint8_t *buf;
unsigned int report_rate;
unsigned int i, j;
unsigned int i;
int dpi_x, dpi_y, hz;
int rc;
@@ -521,35 +523,6 @@ etekcity_read_profile(struct ratbag_profile *profile, unsigned int index)
msleep(10);
for (i = 0; i < ETEKCITY_BUTTON_MAX; i++) {
const struct ratbag_button_action *action;
struct etekcity_macro *macro;
action = etekcity_button_to_action(profile, i);
if (!action || action->type != RATBAG_BUTTON_ACTION_TYPE_MACRO)
continue;
etekcity_set_config_profile(device, index, i);
macro = &drv_data->macros[index][i];
buf = (uint8_t*)macro;
rc = ratbag_hidraw_raw_request(device, ETEKCITY_REPORT_ID_MACRO,
buf, ETEKCITY_REPORT_SIZE_MACRO,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
log_info(device->ratbag,
"macro on button %d of profile %d is named '%s', and contains %d events:\n",
i, profile->index,
macro->name, macro->length);
for (j = 0; j < macro->length; j++) {
log_info(device->ratbag,
" - %s %s\n",
libevdev_event_code_get_name(EV_KEY, macro_mapping[macro->keys[j].keycode]),
macro->keys[j].flag & 0x80 ? "released" : "pressed");
}
}
msleep(10);
if (rc < ETEKCITY_REPORT_SIZE_PROFILE)
return;
@@ -592,6 +565,12 @@ static void
etekcity_read_button(struct ratbag_button *button)
{
const struct ratbag_button_action *action;
struct ratbag_device *device;
struct etekcity_macro *macro;
struct etekcity_data *drv_data;
uint8_t *buf;
unsigned j;
int rc;
action = etekcity_button_to_action(button->profile, button->index);
if (action)
@@ -602,6 +581,104 @@ etekcity_read_button(struct ratbag_button *button)
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_KEY);
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_SPECIAL);
ratbag_button_enable_action_type(button, RATBAG_BUTTON_ACTION_TYPE_MACRO);
if (action && action->type == RATBAG_BUTTON_ACTION_TYPE_MACRO) {
device = button->profile->device;
drv_data = ratbag_get_drv_data(device);
etekcity_set_config_profile(device,
button->profile->index,
button->index);
macro = &drv_data->macros[button->profile->index][button->index];
buf = (uint8_t*)macro;
rc = ratbag_hidraw_raw_request(device, ETEKCITY_REPORT_ID_MACRO,
buf, ETEKCITY_REPORT_SIZE_MACRO,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
if (rc != ETEKCITY_REPORT_SIZE_MACRO) {
log_error(device->ratbag,
"Unable to retrieve the macro for button %d of profile %d: %s (%d)\n",
button->index, button->profile->index,
rc < 0 ? strerror(-rc) : "not read enough", rc);
} else {
ratbag_button_set_macro(button, macro->name);
log_raw(device->ratbag,
"macro on button %d of profile %d is named '%s', and contains %d events:\n",
button->index, button->profile->index,
macro->name, macro->length);
for (j = 0; j < macro->length; j++) {
ratbag_button_set_macro_event(button,
j,
macro->keys[j].flag & 0x80 ? RATBAG_MACRO_EVENT_KEY_RELEASED : RATBAG_MACRO_EVENT_KEY_PRESSED,
macro_mapping[macro->keys[j].keycode]);
log_raw(device->ratbag,
" - %s %s\n",
libevdev_event_code_get_name(EV_KEY, macro_mapping[macro->keys[j].keycode]),
macro->keys[j].flag & 0x80 ? "released" : "pressed");
}
}
msleep(10);
}
}
static int
etekcity_write_macro(struct ratbag_button *button,
const struct ratbag_button_action *action)
{
struct ratbag_device *device;
struct etekcity_macro *macro;
struct etekcity_data *drv_data;
uint8_t *buf;
unsigned i, j, count = 0;
int rc;
if (action->type != RATBAG_BUTTON_ACTION_TYPE_MACRO)
return 0;
device = button->profile->device;
drv_data = ratbag_get_drv_data(device);
macro = &drv_data->macros[button->profile->index][button->index];
buf = (uint8_t*)macro;
for (i = 0; i < MAX_MACRO_EVENTS && count < ETEKCITY_MAX_MACRO_LENGTH; i++) {
if (action->macro->events[i].type == RATBAG_MACRO_EVENT_INVALID)
return -EINVAL; /* should not happen, ever */
if (action->macro->events[i].type == RATBAG_MACRO_EVENT_NONE)
break;
/* ignore timeout events */
if (action->macro->events[i].type == RATBAG_MACRO_EVENT_WAIT)
continue;
for (j = 0; j < ARRAY_LENGTH(macro_mapping); j++) {
if (macro_mapping[j] == action->macro->events[i].event.key)
macro->keys[count].keycode = j;
}
if (action->macro->events[i].type == RATBAG_MACRO_EVENT_KEY_PRESSED)
macro->keys[count].flag = 0x00;
else
macro->keys[count].flag = 0x80;
count++;
}
macro->reportID = ETEKCITY_REPORT_ID_MACRO;
macro->heightytwo = 0x82;
macro->profile = button->profile->index;
macro->button_index = button->index;
macro->active = 0x01;
strncpy(macro->name, action->macro->name, 23);
macro->length = count;
etekcity_set_config_profile(device,
button->profile->index,
button->index);
rc = ratbag_hidraw_raw_request(device, ETEKCITY_REPORT_ID_MACRO,
buf, ETEKCITY_REPORT_SIZE_MACRO,
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
if (rc < 0)
return rc;
return rc == ETEKCITY_REPORT_SIZE_MACRO ? 0 : -EIO;
}
static int
@@ -622,7 +699,13 @@ etekcity_write_button(struct ratbag_button *button,
*data = rc;
return 0;
rc = etekcity_write_macro(button, action);
if (rc)
log_error(device->ratbag,
"unable to write the macro to the device: '%s' (%d)\n",
strerror(-rc), rc);
return rc;
}
static int

View File

@@ -247,6 +247,21 @@ struct ratbag_profile {
{ .type = RATBAG_BUTTON_ACTION_TYPE_MACRO, \
/* FIXME: add the macro keys */ }
struct ratbag_macro_event {
enum ratbag_macro_event_type type;
union ratbag_macro_evnt {
unsigned int key;
unsigned int timeout;
} event;
};
#define MAX_MACRO_EVENTS 64
struct ratbag_macro {
char *name;
char *group;
struct ratbag_macro_event events[MAX_MACRO_EVENTS];
};
struct ratbag_button_action {
enum ratbag_button_action_type type;
union ratbag_btn_action {
@@ -256,8 +271,8 @@ struct ratbag_button_action {
unsigned int key; /* action_type == key */
/* FIXME: modifiers */
} key;
/* FIXME: MACRO */
} action;
struct ratbag_macro *macro; /* dynamically allocated, so kept aside */
};
struct ratbag_button {
@@ -338,7 +353,7 @@ ratbag_button_action_match(const struct ratbag_button_action *action,
case RATBAG_BUTTON_ACTION_TYPE_SPECIAL:
return match->action.special == action->action.special;
case RATBAG_BUTTON_ACTION_TYPE_MACRO:
/* FIXME: currently, do nothing */
return 1;
default:
break;
}

View File

@@ -1204,6 +1204,11 @@ static void
ratbag_button_destroy(struct ratbag_button *button)
{
list_remove(&button->link);
if (button->action.macro) {
if (button->action.macro->name)
free(button->action.macro->name);
free(button->action.macro);
}
free(button);
}
@@ -1284,3 +1289,117 @@ ratbag_resolution_get_user_data(const struct ratbag_resolution *ratbag_resolutio
{
return ratbag_resolution->userdata;
}
LIBRATBAG_EXPORT int
ratbag_button_set_macro(struct ratbag_button *button, const char *name)
{
struct ratbag_macro *macro;
if (!button->action.macro)
button->action.macro = zalloc(sizeof(*macro));
else {
if (button->action.macro->name)
free(button->action.macro->name);
memset(button->action.macro, 0, sizeof(*macro));
}
button->action.type = RATBAG_BUTTON_ACTION_TYPE_MACRO;
button->action.macro->name = name ? strdup(name) : NULL;
return 0;
}
LIBRATBAG_EXPORT int
ratbag_button_set_macro_event(struct ratbag_button *button,
unsigned int index,
enum ratbag_macro_event_type type,
unsigned int data)
{
struct ratbag_macro *macro;
if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_MACRO ||
index >= MAX_MACRO_EVENTS)
return -EINVAL;
macro = button->action.macro;
switch (type) {
case RATBAG_MACRO_EVENT_KEY_PRESSED:
case RATBAG_MACRO_EVENT_KEY_RELEASED:
macro->events[index].type = type;
macro->events[index].event.key = data;
break;
case RATBAG_MACRO_EVENT_WAIT:
macro->events[index].type = type;
macro->events[index].event.timeout = data;
break;
case RATBAG_MACRO_EVENT_NONE:
macro->events[index].type = type;
break;
default:
return -EINVAL;
}
return 0;
}
LIBRATBAG_EXPORT int
ratbag_button_write_macro(struct ratbag_button *button)
{
return button->profile->device->driver->write_button(button, &button->action);
}
LIBRATBAG_EXPORT enum ratbag_macro_event_type
ratbag_button_get_macro_event_type(struct ratbag_button *button, unsigned int index)
{
if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_MACRO ||
index >= MAX_MACRO_EVENTS)
return RATBAG_MACRO_EVENT_INVALID;
return button->action.macro->events[index].type;
}
LIBRATBAG_EXPORT int
ratbag_button_get_macro_event_key(struct ratbag_button *button, unsigned int index)
{
struct ratbag_macro *macro;
if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_MACRO ||
index >= MAX_MACRO_EVENTS)
return -EINVAL;
macro = button->action.macro;
if (macro->events[index].type != RATBAG_MACRO_EVENT_KEY_PRESSED &&
macro->events[index].type != RATBAG_MACRO_EVENT_KEY_RELEASED)
return -EINVAL;
return macro->events[index].event.key;
}
LIBRATBAG_EXPORT int
ratbag_button_get_macro_event_timeout(struct ratbag_button *button, unsigned int index)
{
struct ratbag_macro *macro;
if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_MACRO ||
index >= MAX_MACRO_EVENTS)
return -EINVAL;
macro = button->action.macro;
if (macro->events[index].type != RATBAG_MACRO_EVENT_WAIT)
return -EINVAL;
return macro->events[index].event.timeout;
}
LIBRATBAG_EXPORT const char *
ratbag_button_get_macro_name(struct ratbag_button *button)
{
if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_MACRO)
return NULL;
return button->action.macro->name;
}

View File

@@ -1259,18 +1259,113 @@ ratbag_button_disable(struct ratbag_button *button);
/**
* @ingroup button
*
* FIXME: no idea at this point
* Macro event types describing the event.
*/
unsigned int
ratbag_button_get_macro(struct ratbag_button *button);
enum ratbag_macro_event_type {
RATBAG_MACRO_EVENT_INVALID = -1,
RATBAG_MACRO_EVENT_NONE = 0,
RATBAG_MACRO_EVENT_KEY_PRESSED,
RATBAG_MACRO_EVENT_KEY_RELEASED,
RATBAG_MACRO_EVENT_WAIT,
};
/**
* @ingroup button
*
* FIXME: no idea at this point
* If a button's action is @ref RATBAG_BUTTON_ACTION_TYPE_MACRO,
* this function returns the macro name.
*
* If the button's action type is not @ref RATBAG_BUTTON_ACTION_TYPE_MACRO,
* this function returns NULL.
*
* @param button A previously initialized ratbag button
*
* @return The name of the macro associated to the button.
*/
unsigned int
ratbag_button_set_macro(struct ratbag_button *button);
const char *
ratbag_button_get_macro_name(struct ratbag_button *button);
/**
* @ingroup button
*
* If a button's action is @ref RATBAG_BUTTON_ACTION_TYPE_MACRO,
* this function returns the macro event type configured for the event at the
* given index.
*
* If the button's action type is not @ref RATBAG_BUTTON_ACTION_TYPE_MACRO,
* this function returns @ref RATBAG_MACRO_EVENT_INVALID.
*
* @param button A previously initialized ratbag button
* @param index An index of the event within the macro we are interested in.
*
* @return The type of the event at the given index
*/
enum ratbag_macro_event_type
ratbag_button_get_macro_event_type(struct ratbag_button *button, unsigned int index);
/**
* @ingroup button
*
* If a button's action is @ref RATBAG_BUTTON_ACTION_TYPE_MACRO, and if the
* event stored at the given index is @ref RATBAG_MACRO_EVENT_KEY_PRESSED or
* @ref RATBAG_MACRO_EVENT_KEY_RELEASED, this function returns the key code
* configured for the event at the given index.
*
* If the button's action type is not @ref RATBAG_BUTTON_ACTION_TYPE_MACRO,
* or if the event stored at the given index is not
* @ref RATBAG_MACRO_EVENT_KEY_PRESSED or @ref RATBAG_MACRO_EVENT_KEY_RELEASED,
* this function returns -EINVAL.
*
* @param button A previously initialized ratbag button
* @param index An index of the event within the macro we are interested in.
*
* @return The key of the event at the given index
*/
int
ratbag_button_get_macro_event_key(struct ratbag_button *button, unsigned int index);
/**
* @ingroup button
*
* If a button's action is @ref RATBAG_BUTTON_ACTION_TYPE_MACRO, and if the
* event stored at the given index is @ref RATBAG_MACRO_EVENT_WAIT, this
* function returns the timeout configured for the event at the given index.
*
* If the button's action type is not @ref RATBAG_BUTTON_ACTION_TYPE_MACRO,
* or if the event stored at the given index is not
* @ref RATBAG_MACRO_EVENT_WAIT, this function returns -EINVAL.
*
* @param button A previously initialized ratbag button
* @param index An index of the event within the macro we are interested in.
*
* @return The tiemout of the event at the given index
*/
int
ratbag_button_get_macro_event_timeout(struct ratbag_button *button, unsigned int index);
/**
* @ingroup button
*
* Sets the button's action to @ref RATBAG_BUTTON_ACTION_TYPE_MACRO and
* allocates the required memory to store the macro.
*/
int
ratbag_button_set_macro(struct ratbag_button *button, const char *name);
int
ratbag_button_write_macro(struct ratbag_button *button);
/**
* @ingroup button
*
* Sets the macro's event at the given index to the given type with the
* key code or timeout given.
*/
int
ratbag_button_set_macro_event(struct ratbag_button *button,
unsigned int index,
enum ratbag_macro_event_type type,
unsigned int data);
/**
* @ingroup button

View File

@@ -8,15 +8,22 @@ global:
ratbag_button_get_type;
ratbag_button_get_button;
ratbag_button_get_key;
ratbag_button_get_macro_event_type;
ratbag_button_get_macro_event_key;
ratbag_button_get_macro_event_timeout;
ratbag_button_get_macro_name;
ratbag_button_get_special;
ratbag_button_get_user_data;
ratbag_button_has_action_type;
ratbag_button_ref;
ratbag_button_set_button;
ratbag_button_set_key;
ratbag_button_set_macro;
ratbag_button_set_macro_event;
ratbag_button_set_special;
ratbag_button_set_user_data;
ratbag_button_unref;
ratbag_button_write_macro;
ratbag_device_get_name;
ratbag_device_get_num_buttons;
ratbag_device_get_num_profiles;

View File

@@ -362,6 +362,53 @@ static const struct ratbag_cmd cmd_switch_etekcity = {
.help = "Switch the Etekcity mouse active profile",
};
struct macro {
const char *name;
struct {
enum ratbag_macro_event_type type;
unsigned data;
} events[64];
};
static int
str_to_macro(const char *action_arg, struct macro *m)
{
if (!action_arg)
return -EINVAL;
if (action_arg[0] == 'f') {
m->name = "foo";
m->events[0].type = RATBAG_MACRO_EVENT_KEY_PRESSED;
m->events[0].data = KEY_F;
m->events[1].type = RATBAG_MACRO_EVENT_KEY_RELEASED;
m->events[1].data = KEY_F;
m->events[2].type = RATBAG_MACRO_EVENT_KEY_PRESSED;
m->events[2].data = KEY_O;
m->events[3].type = RATBAG_MACRO_EVENT_KEY_RELEASED;
m->events[3].data = KEY_O;
m->events[4].type = RATBAG_MACRO_EVENT_KEY_PRESSED;
m->events[4].data = KEY_O;
m->events[5].type = RATBAG_MACRO_EVENT_KEY_RELEASED;
m->events[5].data = KEY_O;
} else if (action_arg[0] == 'b') {
m->name = "bar";
m->events[0].type = RATBAG_MACRO_EVENT_KEY_PRESSED;
m->events[0].data = KEY_B;
m->events[1].type = RATBAG_MACRO_EVENT_KEY_RELEASED;
m->events[1].data = KEY_B;
m->events[2].type = RATBAG_MACRO_EVENT_KEY_PRESSED;
m->events[2].data = KEY_A;
m->events[3].type = RATBAG_MACRO_EVENT_KEY_RELEASED;
m->events[3].data = KEY_A;
m->events[4].type = RATBAG_MACRO_EVENT_KEY_PRESSED;
m->events[4].data = KEY_R;
m->events[5].type = RATBAG_MACRO_EVENT_KEY_RELEASED;
m->events[5].data = KEY_R;
}
return 0;
}
static int
ratbag_cmd_change_button(struct ratbag *ratbag, uint32_t flags, int argc, char **argv)
{
@@ -374,6 +421,7 @@ ratbag_cmd_change_button(struct ratbag *ratbag, uint32_t flags, int argc, char *
int rc = 1;
unsigned int btnkey;
enum ratbag_button_action_special special;
struct macro macro = {0};
int i;
if (argc != 4) {
@@ -402,6 +450,12 @@ ratbag_cmd_change_button(struct ratbag *ratbag, uint32_t flags, int argc, char *
error("Invalid special command '%s'\n", action_arg);
return 1;
}
} else if (streq(action_str, "macro")) {
action_type = RATBAG_BUTTON_ACTION_TYPE_MACRO;
if (str_to_macro(action_arg, &macro)) {
error("Invalid special command '%s'\n", action_arg);
return 1;
}
} else {
usage();
return 1;
@@ -449,6 +503,19 @@ ratbag_cmd_change_button(struct ratbag *ratbag, uint32_t flags, int argc, char *
case RATBAG_BUTTON_ACTION_TYPE_SPECIAL:
rc = ratbag_button_set_special(button, special);
break;
case RATBAG_BUTTON_ACTION_TYPE_MACRO:
rc = ratbag_button_set_macro(button, macro.name);
for (i = 0; i < ARRAY_LENGTH(macro.events); i++) {
if (macro.events[i].type == RATBAG_MACRO_EVENT_NONE)
break;
ratbag_button_set_macro_event(button,
i,
macro.events[i].type,
macro.events[i].data);
}
rc = ratbag_button_write_macro(button);
break;
default:
error("well, that shouldn't have happened\n");
abort();
@@ -481,7 +548,7 @@ out:
static const struct ratbag_cmd cmd_change_button = {
.name = "change-button",
.cmd = ratbag_cmd_change_button,
.args = "X <button|key|special> <number|KEY_FOO|special>",
.args = "X <button|key|special|macro> <number|KEY_FOO|special|macro name:KEY_FOO,KEY_BAR,...>",
.help = "Remap button X to the given action in the active profile",
};

View File

@@ -145,6 +145,51 @@ button_action_key_to_str(struct ratbag_button *button)
return strdup(str);
}
static const char *strip_ev_key(int key)
{
const char *str = libevdev_event_code_get_name(EV_KEY, key);
if (!strncmp(str, "KEY_", 4))
return str + 4;
return str;
};
char *
button_action_macro_to_str(struct ratbag_button *button)
{
char str[4096] = {0};
const char *name;
int offset;
unsigned int i;
name = ratbag_button_get_macro_name(button);
offset = snprintf(str, sizeof(str), "macro \"%s\":",
name ? name : "UNKNOWN");
for (i = 0; i < MAX_MACRO_EVENTS; i++) {
enum ratbag_macro_event_type type = ratbag_button_get_macro_event_type(button, i);
int key = ratbag_button_get_macro_event_key(button, i);
int timeout = ratbag_button_get_macro_event_timeout(button, i);
if (type == RATBAG_MACRO_EVENT_NONE)
break;
switch (type) {
case RATBAG_MACRO_EVENT_KEY_PRESSED:
offset += snprintf(str + offset, sizeof(str) - offset, " %s↓", strip_ev_key(key));
break;
case RATBAG_MACRO_EVENT_KEY_RELEASED:
offset += snprintf(str + offset, sizeof(str) - offset, " %s↑", strip_ev_key(key));
break;
case RATBAG_MACRO_EVENT_WAIT:
offset += snprintf(str + offset, sizeof(str) - offset, " %d.%d⏱", timeout / 1000, timeout % 1000);
default:
offset += snprintf(str + offset, sizeof(str) - offset, " ###");
}
}
return strdup(str);
}
char *
button_action_to_str(struct ratbag_button *button)
{
@@ -157,7 +202,7 @@ button_action_to_str(struct ratbag_button *button)
case RATBAG_BUTTON_ACTION_TYPE_BUTTON: str = button_action_button_to_str(button); break;
case RATBAG_BUTTON_ACTION_TYPE_KEY: str = button_action_key_to_str(button); break;
case RATBAG_BUTTON_ACTION_TYPE_SPECIAL: str = strdup(button_action_special_to_str(button)); break;
case RATBAG_BUTTON_ACTION_TYPE_MACRO: str = strdup("macro"); break;
case RATBAG_BUTTON_ACTION_TYPE_MACRO: str = button_action_macro_to_str(button); break;
case RATBAG_BUTTON_ACTION_TYPE_NONE: str = strdup("none"); break;
default:
error("type %d unknown\n", type);

View File

@@ -37,6 +37,8 @@
#include <libratbag-util.h>
#include <libevdev/libevdev.h>
#define MAX_MACRO_EVENTS 64
LIBRATBAG_ATTRIBUTE_PRINTF(1, 2)
static inline void
error(const char *format, ...)