mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-03-22 02:10:40 +01:00
Merge branch 'wip/button-debouncing-v3'
This commit is contained in:
commit
0e0dfe9bdf
19 changed files with 2305 additions and 727 deletions
843
doc/button-debouncing-state-machine.svg
Normal file
843
doc/button-debouncing-state-machine.svg
Normal file
|
|
@ -0,0 +1,843 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1108px" height="2101px" version="1.1" content="<mxfile userAgent="Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0" version="7.7.1" editor="www.draw.io" type="google"><diagram id="27c35eac-9917-780f-69cd-550de3271581" name="Page-1">7V1bc5u6Fv41mXP2gzOIq/ToxM7enWnTTJ1OZz91MMg2ZxPkAVwn+9cfcRE2ElDq2AglzUNryxjkdV+ftJaujNun5z9jd7v5RHwcXuma/3xlzK50HZi6Sf/LRl7KEYTKkXUc+OXYYWAR/IvLQa0c3QU+TmoXpoSEabCtD3okirCX1sbcOCb7+mUrEtafunXXWBhYeG4ojn4L/HRTjELdPoz/hYP1hj0Z2Kj45MllF5e/JNm4PtkfDRnzK+M2JiQtXj093+Iwox6jS/G9u5ZPq4nFOEr7fEFfLj3PRo6FVi72XGOiF3f44Ya78sd+WHz/+lDONn1hJIjJLvJxdhdwZdzsN0GKF1vXyz7dU67TsU36FJYfr4IwvCUhifPvGr6FoW/S8SSNyT/46BOoLw3bpp+Us8Bxip9bfxqoCEZFDZMnnMYv9JLyCwaTllLKJlb5fn9gGbDLsc0Ru8xyzC2lZF3d+kBI+qKkZU+6mgJdl7s0JdGVbof0uTfLmL5aZ6+2MU4Sgd5UULbZyw1+dtf0azX6NpF/i+OAThvHhy89HIbOQmC7TmBTpG8Tea1LkNcWCIZ9qrLlWxKnG0IJ4Ibzw+jNQYS1Ojn/h9P0pbQ67i4ldOhwh4+EbMvrimdmD+qmIJ0X2cUe7la51I3XOO0SH5ETMQ7dNPhRf/5ZCesIcjv7/O3++7fph8cP938qaBZ0VJdaw5BpFgAQ6Ptl/nE+Xcy/P8zvZ2qSGGh1ElsNlmFAEhsCiVNqBskuvbiR5ag/n9o356KxafLG1xrM+gJkeAAjByIbQsOdiASOSBqsXkTf1ubzqB3DboJFhuRiymIsvc4Qxq2n53UWZ16vQrL3Nm6cXvtu6rZwjGPJ3d0MnYslFmdZoCmypFKNY57YF+CJGG/8Kk9a4hCVOGJwSkJ5JI8jqDNEiUg0ppjE6RGTFIZ1gKCEp2SDRadJShaXDO0saYKZukGU239wJisCJaYtAqVNlYSWycWx1DbLjgyhtQWh/WVvqEIOKC8MAY5KwtpgYZtFRoaswhFTsk2xun1VixhfnpRIUPs3kH1Yda23kTytr5DUMcpqa77fqfZIkqzqootSFfwFnIQCB0kMoxjE9LZ8v8MB7A1A2mAIBBAINh4j0Ja+dNkAQ2sm/cVtgGH1FlVlFiqq1bYRuCuje6VCQXdVSIwMUR1zvN+mV51RqiOLklBQ+neJ4HJwIWyCXoaCCw0xcWArQ+ouvllcWIZkgltm/6hMGVfHx2RAa1iEGMrXmbpKBhr93NWZsqIy822uYXLgIai27MgQ1jEHZm2oUmdcBmUJq0roIQt9uiipy8JhTTEG+DT9+2b+ffHw9cuHz18XCoYA0LbrSg9gw6LsUDEAsyRKyCojQKeLkgUeWuJOpjeAcQENcuIq00dZ3QHVqLY5tslHp8t6rfDmX53GsftydMGWBFGaHN35IRs44jEAdR4jR+O4VNzywLNqbqex0VDJ6PQINSxZq2uWiFZWcTFvdZINpdLFbQ7nU9H01rm5O48tQmhMpkilcLmXDMuCMW2VQhCrAca0TBPBFYQ+QkgzoDV5rTVoMdOaY16bNrAMWPzLa4PDiXkxx/IuHH9eZ8DtMQMbzez4yZKz+doCgxaemdyeWEcbjkkiZpJsd3FAdonoHHDkLsOMV3eihzgRwcZekAS5R+mBYqP87zx+wuYyLMvuCWMDnjlnMW/ipoKIjFh92sSoM26V5TrEdZu3G/7Y+oigbVbQqYQI94G2bVloodNaATUTSDx+dIvfvS0X3XLGHKe0GbMuKXVkJZqOSpi20yPiM2X5LEfEtJVfdbUZuDWGzByqlE/2EVVHFqQNRdf08GW+WChcmmuzmIlJqtkgqYP5J6gSEOr0iKKgLP8E+2/bVGj1BXLowQFOkGFXVUI8YQ+7CmUhnlCljZuwAfEcTVgKOwCAYTP9c+4Lsvl9QVLVXoxX32Elvc1bYrspbhislF6lELeXKZaFviCVCmdgD4QAykoWkEpYC2yIZS1HszXfgyt7udIQNC60jAe5TfbA4TOLyy0JoTG3M2jb8zvKnYlIzDdYdcJs/nH69/Dg7QVacVQryqxujG0WlZErI5XSjz6LZui16UeLfeFKTBzWkWIA8yI2y3vBYuBHBTKtM4fGh8G/2QJ0ybdyxxq92rq5smZ0xA2DNY3ZZx7lQh5+Z4IdeG44LT94Cnw/3+4Xuksc3rjeP+tcFo5UZZX/dalG2S+1nMlVVTdZ436jXLbq0ES7NhxYB51Yc6pXctow63dldbXsDmS1SvC5eQw0ERR8u2uuJq9MDQ20BmvvoqkUYaEesEEpSxLcN9BUQl4rnRvjHgygvcGKecsek96rFPn003tZyCvQVIJeK9UaZ0M3TQRf83iD1/osPIhFsodhsE3wz1MhN9kWPexXwXPGk0sir4bNLw+KKJ81mN6PeY9VW4P3br2XBfMBoBJiWmlW5wYWaaQUEwDV1b7KkVknJ0ei2gOVwnzW86pT7eU1HwRKhfm9muPJa4rZ0ME1V3ytTPMHNgBn3VsN61iK2WAAnAYDwJfcnIfOSsWoTe1Hm+FQGTKri86KpJtMLNsWry+cnCYFY7RrHRq1vwYPB2bW3DlTQssVD0jtU6yP2cOd1Ki4jfoDCLhSHk7v4+HkGQsRyXqXxgJwS9Qy+0UCfczo12n9jXVp8JeuVGih94C/pHV5AroIf71La8GfxCS1LhHoYwbNTilMLOVMhoQbSoFm+pg7mQHjdyJSKD3fmF5mqRgwxpyJnFIrVsqZFAlXKhMxehBTorX4nYkU+BrfLFFmJQQYde/6U7bdA2m964FSzetBU/f60ey8Bw3t69+ltUD6iBrEgYYG9m+gNs0yxpTtmSplKL2yvVe3AD2dliqVQoE+xJQXvynV+b9Pd0ggD2czfx/lfHXoyTuOAlTAjL4SAg76NLl/fQvI04mpUl5R6eNFaydPp6VYg/QuY2G+zFTi4YRAqQMxeh2ibco6qaw61/O9y7dh1LdsSq3QsFQKnXtVaFiyTnoC7IyH934Wn86dZIb6djG+SLyn1JENlZHsFnFdmoiLwfNoKKf/nHLy0mpL3IHMtH8DmPbPo2I6SeqmmD59Sl+Xx3jfFi9nn7/di1aDjdBZHW7GBrdsYJoku6dtmjc2n7KnZHNO8jckpkykZMfxhFmn7KFulI1+fvxr/oX+f/P18fHzfcauHzg/mUWjXMr+DffuS/Z2GxOPZqz5rZZ4RfJPqZfPrvHSnZsRqbj9NX21YE9lc9lm4YDGnl9Mzc0+D6J1mF2wDLJt2//d0V9155N99Ec5y+Nr2M3o06uHs7En19sEUTGdmGSpdXmBj38E3oEcu9Uq8AL6G6+PiLttpe2CSl3a8bB9QA1fxUwtn1jFTm3pFgTLf3Nxi4IE/0nYTy5Y8dLKivwZuQjGuNjanhOKal12Rzc9mhW9zT47Zec21yhh0p4b5bzLbzXZFTM7JmWE98dM7BDGI3pxRkNspFBvD1Ja5WMnVQ4l1I1RRtMB6/DuMTcmE11rcXaE+rPMK2ZxYOD7OBIs/lniurrbm+gNfq/aclTr3g8v4vh+55MFybkGaA2FkYOF26M+MUbYEtrDo5ZSJsOl2iqlLpU2dp4iPlRc13bQzJGpKI5VaWiMUh3EwtP+5OqoM+g40Ax+uwUQs2rYoObnML0COXWFJLPPISlDrezp/hI60LJ8HSEITTzpzt1GfWriMBqff/VXj03kS6pYLey5Tk0U2NjdvG/cbDT7VFG9tvDnJDZCZ2A2qrTY07DU01wfN4S7bVxjqrnbKhlsRVdGey4Bf7al07DR8Vy9FunbmJD0WKQzyPMT8XF2xf8B</diagram></mxfile>">
|
||||
<defs/>
|
||||
<g transform="translate(0.5,0.5)">
|
||||
<rect x="271" y="220" width="160" height="40" rx="6" ry="6" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/>
|
||||
<g transform="translate(333.5,233.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="35" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 36px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
IS_UP</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="18" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
IS_UP</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 336 310 L 366 310 L 381 335 L 366 360 L 336 360 L 321 335 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(333.5,321.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
button<br/>
|
||||
press</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 351 260 L 351 303.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 351 308.88 L 347.5 301.88 L 351 303.63 L 354.5 301.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<rect x="251" y="600" width="160" height="40" rx="6" ry="6" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/>
|
||||
<g transform="translate(283.5,613.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="95" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 96px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
DOWN_WAITING</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="48" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
DOWN_WAITING</text>
|
||||
</switch>
|
||||
</g>
|
||||
<rect x="61" y="810" width="160" height="40" rx="6" ry="6" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/>
|
||||
<g transform="translate(81.5,823.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="118" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 119px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
RELEASE_PENDING</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="59" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
RELEASE_PENDING</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 416 675 L 446 675 L 461 700 L 446 725 L 416 725 L 401 700 Z" fill="#ea6b66" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(410.5,693.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="40" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 41px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
timeout</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="20" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
timeout</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 570.61 1120.1 C 571.78 1116.9 573.67 1115.04 575.67 1115.12 L 645.53 1115.12 C 647.13 1115.08 648.65 1115.63 649.65 1116.61 C 650.64 1117.59 650.99 1118.88 650.6 1120.1 L 631.36 1169.9 C 630.19 1173.1 628.3 1174.96 626.3 1174.88 L 555.42 1174.88 C 554.01 1174.69 552.77 1174.05 551.99 1173.1 C 551.22 1172.15 551 1170.99 551.37 1169.9 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(579.5,1123.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="41" height="41" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 42px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
notify<br/>
|
||||
button<br/>
|
||||
release</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="21" y="27" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 320.61 500.1 C 321.78 496.9 323.67 495.04 325.67 495.12 L 395.53 495.12 C 397.13 495.08 398.65 495.63 399.65 496.61 C 400.64 497.59 400.99 498.88 400.6 500.1 L 381.36 549.9 C 380.19 553.1 378.3 554.96 376.3 554.88 L 305.42 554.88 C 304.01 554.69 302.77 554.05 301.99 553.1 C 301.22 552.15 301 550.99 301.37 549.9 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(333.5,503.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="41" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
notify<br/>
|
||||
button<br/>
|
||||
press</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="27" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 356 640 L 405.76 679.81" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 409.86 683.09 L 402.2 681.45 L 405.76 679.81 L 406.58 675.98 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<rect x="541" y="220" width="160" height="40" rx="6" ry="6" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/>
|
||||
<g transform="translate(592.5,233.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="56" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 57px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
IS_DOWN</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="28" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
IS_DOWN</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 441.33 675 L 610.31 265.89" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 612.31 261.03 L 612.87 268.84 L 610.31 265.89 L 606.41 266.17 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 336 675 L 366 675 L 381 700 L 366 725 L 336 725 L 321 700 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(330.5,686.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="41" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 42px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
button<br/>
|
||||
release</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="21" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
button<br>release</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 336 640 L 343.21 668.82" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 344.48 673.92 L 339.39 667.97 L 343.21 668.82 L 346.18 666.28 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 329.13 713.54 L 178.72 806.65" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 174.26 809.41 L 178.37 802.75 L 178.72 806.65 L 182.05 808.7 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 26 965 L 56 965 L 71 990 L 56 1015 L 26 1015 L 11 990 Z" fill="#ea6b66" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(20.5,983.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="40" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 41px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
timeout</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="20" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
timeout</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 128.5 850 L 59.68 960.11" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 56.9 964.56 L 57.64 956.77 L 59.68 960.11 L 63.58 960.48 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<rect x="111" y="2060" width="160" height="40" rx="6" ry="6" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/>
|
||||
<g transform="translate(173.5,2073.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="35" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 36px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
IS_UP</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="18" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
IS_UP</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 686 300 L 716 300 L 731 325 L 716 350 L 686 350 L 671 325 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(680.5,311.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="41" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 42px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
button<br/>
|
||||
release</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="21" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
button<br>release</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 639.82 260 L 678.31 300.9" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 681.91 304.72 L 674.57 302.02 L 678.31 300.9 L 679.66 297.22 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 196 965 L 226 965 L 241 990 L 226 1015 L 196 1015 L 181 990 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(193.5,976.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
button<br/>
|
||||
press</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 149.75 850 L 197.51 959.17" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 199.61 963.98 L 193.6 958.97 L 197.51 959.17 L 200.02 956.16 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 219.11 965 L 322.55 646.06" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 324.17 641.06 L 325.34 648.8 L 322.55 646.06 L 318.68 646.64 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 20.61 1125.1 C 21.78 1121.9 23.67 1120.04 25.67 1120.12 L 95.53 1120.12 C 97.13 1120.08 98.65 1120.63 99.65 1121.61 C 100.64 1122.59 100.99 1123.88 100.6 1125.1 L 81.36 1174.9 C 80.19 1178.1 78.3 1179.96 76.3 1179.88 L 5.42 1179.88 C 4.01 1179.69 2.77 1179.05 1.99 1178.1 C 1.22 1177.15 1 1175.99 1.37 1174.9 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(29.5,1128.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="41" height="41" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 42px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
notify<br/>
|
||||
button<br/>
|
||||
release</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="21" y="27" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<rect x="511" y="1220" width="160" height="40" rx="6" ry="6" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/>
|
||||
<g transform="translate(534.5,1233.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="113" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 114px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
RELEASE_WAITING</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="57" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
RELEASE_WAITING</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 686 1315 L 716 1315 L 731 1340 L 716 1365 L 686 1365 L 671 1340 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(683.5,1326.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
button<br/>
|
||||
press</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 613 1260 L 676.88 1318.07" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 680.76 1321.6 L 673.23 1319.48 L 676.88 1318.07 L 677.94 1314.3 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 436 1580 L 466 1580 L 481 1605 L 466 1630 L 436 1630 L 421 1605 Z" fill="#ea6b66" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(430.5,1598.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="40" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 41px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
timeout</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="20" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
timeout</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 42.56 1015 L 48.73 1113.64" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 49.06 1118.88 L 45.13 1112.12 L 48.73 1113.64 L 52.11 1111.68 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 55.52 1180 L 187.04 2053.7" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 187.82 2058.89 L 183.32 2052.49 L 187.04 2053.7 L 190.24 2051.45 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<rect x="827" y="1455" width="160" height="40" rx="6" ry="6" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/>
|
||||
<g transform="translate(850.5,1468.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="112" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 113px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
MAYBE_SPURIOUS</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="56" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
MAYBE_SPURIOUS</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 722.53 1354.11 L 871.16 1451.51" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 875.55 1454.39 L 867.77 1453.48 L 871.16 1451.51 L 871.61 1447.62 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1062 1580 L 1092 1580 L 1107 1605 L 1092 1630 L 1062 1630 L 1047 1605 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(1056.5,1591.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="41" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 42px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
button<br/>
|
||||
release</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="21" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
button<br>release</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 1077 1580 L 1077 1240 L 677.37 1240" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 672.12 1240 L 679.12 1236.5 L 677.37 1240 L 679.12 1243.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 933.15 1495 L 1051.38 1585.41" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1055.55 1588.6 L 1047.86 1587.12 L 1051.38 1585.41 L 1052.11 1581.56 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 972 1580 L 1002 1580 L 1017 1605 L 1002 1630 L 972 1630 L 957 1605 Z" fill="#9ac7bf" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(966.5,1591.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="40" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 41px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
timeout<br/>
|
||||
short</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="20" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
timeout<br>short</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 919.31 1495 L 968.47 1574.89" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 971.22 1579.36 L 964.57 1575.24 L 968.47 1574.89 L 970.54 1571.57 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 997.42 1630 L 1019.17 1682.2" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1021.19 1687.04 L 1015.26 1681.93 L 1019.17 1682.2 L 1021.72 1679.24 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1025.62 1763.35 L 991.94 1873.91" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 990.41 1878.93 L 989.1 1871.21 L 991.94 1873.91 L 995.79 1873.25 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 677 830 L 727 880 L 677 930 L 627 880 Z" fill="#999999" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(650.5,865.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="52" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 53px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
spurious<br/>
|
||||
enabled?</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="26" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
spurious<br>enabled?</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 662.66 930 L 611.36 1108.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 609.91 1113.93 L 608.48 1106.23 L 611.36 1108.88 L 615.21 1108.16 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(629.5,1016.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="12" height="11" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">
|
||||
no</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="6" y="11" fill="#000000" text-anchor="middle" font-size="11px" font-family="Helvetica">
|
||||
no</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 596 1315 L 626 1315 L 641 1340 L 626 1365 L 596 1365 L 581 1340 Z" fill="#9ac7bf" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(590.5,1326.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="40" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 41px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
timeout<br/>
|
||||
short</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="20" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
timeout<br>short</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 595 1260 L 604.75 1308.76" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 605.78 1313.9 L 600.98 1307.73 L 604.75 1308.76 L 607.84 1306.35 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<rect x="541" y="1455" width="160" height="40" rx="6" ry="6" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/>
|
||||
<g transform="translate(588.5,1468.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="65" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 66px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
RELEASED</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="33" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
RELEASED</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 612.85 1365 L 619.05 1448.65" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 619.44 1453.89 L 615.43 1447.16 L 619.05 1448.65 L 622.41 1446.65 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 594.85 1495 L 476.62 1585.41" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 472.45 1588.6 L 475.89 1581.56 L 476.62 1585.41 L 480.14 1587.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 627 1580 L 657 1580 L 672 1605 L 657 1630 L 627 1630 L 612 1605 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(624.5,1591.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
button<br/>
|
||||
press</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 624.23 1495 L 636.95 1573.71" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 637.78 1578.9 L 633.21 1572.54 L 636.95 1573.71 L 640.12 1571.43 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<rect x="606" y="1680" width="160" height="40" rx="6" ry="6" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/>
|
||||
<g transform="translate(634.5,1693.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="103" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 104px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
PRESS_PENDING</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="52" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
PRESS_PENDING</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 653.58 1630 L 674.06 1674.22" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 676.27 1678.99 L 670.15 1674.1 L 674.06 1674.22 L 676.5 1671.16 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 866 1760 L 896 1760 L 911 1785 L 896 1810 L 866 1810 L 851 1785 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(860.5,1771.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="41" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 42px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
button<br/>
|
||||
release</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="21" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
button<br>release</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 731.88 1720 L 851.38 1772.09" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 856.19 1774.19 L 848.38 1774.6 L 851.38 1772.09 L 851.18 1768.18 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 863.51 1764.15 L 641.87 1499.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 638.49 1495.86 L 645.67 1498.97 L 641.87 1499.88 L 640.31 1503.47 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 636 1760 L 666 1760 L 681 1785 L 666 1810 L 636 1810 L 621 1785 Z" fill="#ea6b66" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(630.5,1778.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="40" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 41px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
timeout</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="20" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
timeout</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 670.61 1885.1 C 671.78 1881.9 673.67 1880.04 675.67 1880.12 L 745.53 1880.12 C 747.13 1880.08 748.65 1880.63 749.65 1881.61 C 750.64 1882.59 750.99 1883.88 750.6 1885.1 L 731.36 1934.9 C 730.19 1938.1 728.3 1939.96 726.3 1939.88 L 655.42 1939.88 C 654.01 1939.69 652.77 1939.05 651.99 1938.1 C 651.22 1937.15 651 1935.99 651.37 1934.9 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(683.5,1888.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="41" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
notify<br/>
|
||||
button<br/>
|
||||
press</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="27" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 677.76 1720 L 663.72 1754.11" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 661.72 1758.97 L 661.15 1751.16 L 663.72 1754.11 L 667.62 1753.83 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 661 1810 L 686.63 1874.09" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 688.58 1878.96 L 682.74 1873.76 L 686.63 1874.09 L 689.23 1871.16 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 707.35 1940 L 731.45 2053.77" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 732.53 2058.91 L 727.66 2052.78 L 731.45 2053.77 L 734.51 2051.33 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 437.32 1630 L 205 2054.41" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 202.48 2059.02 L 202.78 2051.2 L 205 2054.41 L 208.92 2054.56 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<rect x="331" y="908" width="160" height="40" rx="6" ry="6" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/>
|
||||
<g transform="translate(350.5,921.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="120" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 121px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
RELEASE_DELAYED</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="60" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
RELEASE_DELAYED</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 627 889.02 L 497.27 912.43" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 492.1 913.37 L 498.37 908.68 L 497.27 912.43 L 499.61 915.57 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(608.5,873.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="19" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;">
|
||||
yes</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="10" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
yes</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 426 995 L 456 995 L 471 1020 L 456 1045 L 426 1045 L 411 1020 Z" fill="#9ac7bf" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(420.5,1006.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="40" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 41px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
timeout<br/>
|
||||
short</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="20" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
timeout<br>short</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 417.52 948 L 430.87 988.95" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 432.5 993.94 L 427 988.37 L 430.87 988.95 L 433.66 986.2 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 461.43 1035.96 L 557.58 1111.08" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 561.72 1114.31 L 554.05 1112.76 L 557.58 1111.08 L 558.36 1107.24 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 536 995 L 566 995 L 581 1020 L 566 1045 L 536 1045 L 521 1020 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(533.5,1006.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
button<br/>
|
||||
press</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 441.43 948 L 524.16 1002.36" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 528.55 1005.25 L 520.78 1004.33 L 524.16 1002.36 L 524.62 998.48 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 553.24 995 L 618.64 266.34" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 619.11 261.11 L 621.97 268.4 L 618.64 266.34 L 614.99 267.77 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<ellipse cx="351" cy="435" rx="25" ry="25" fill="#ea6b66" stroke="#000000" pointer-events="none"/>
|
||||
<g transform="translate(337.5,421.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="27" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 28px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
set<br/>
|
||||
timer</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="14" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 351 360 L 351 403.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 351 408.88 L 347.5 401.88 L 351 403.63 L 354.5 401.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 351 460 L 351 488.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 351 493.88 L 347.5 486.88 L 351 488.63 L 354.5 486.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<ellipse cx="691" cy="665" rx="25" ry="25" fill="#ea6b66" stroke="#000000" pointer-events="none"/>
|
||||
<g transform="translate(677.5,651.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="27" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 28px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
set<br/>
|
||||
timer</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="14" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 700.26 350 L 691.92 633.65" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 691.77 638.89 L 688.48 631.79 L 691.92 633.65 L 695.47 632 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 688.68 689.89 L 684.14 733.84" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 683.6 739.06 L 680.84 731.74 L 684.14 733.84 L 687.8 732.46 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<ellipse cx="680" cy="775" rx="35" ry="35" fill="#9ac7bf" stroke="#000000" pointer-events="none"/>
|
||||
<g transform="translate(656.5,761.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="46" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 47px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
set short<br/>
|
||||
timer</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="23" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
set short<br>timer</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 679.36 809.99 L 678.73 823.64" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 678.48 828.88 L 675.31 821.73 L 678.73 823.64 L 682.3 822.05 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 498 675 L 524 675 L 541 700 L 524 725 L 498 725 L 481 700 Z" fill="#e1d5e7" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(493.5,686.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
other<br/>
|
||||
button</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 376 640 L 481.5 686.89" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 486.29 689.02 L 478.48 689.37 L 481.5 686.89 L 481.32 682.98 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 516.98 675 L 614.74 266.19" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 615.96 261.09 L 617.73 268.71 L 614.74 266.19 L 610.93 267.08 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 118 965 L 144 965 L 161 990 L 144 1015 L 118 1015 L 101 990 Z" fill="#e1d5e7" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(113.5,976.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
other<br/>
|
||||
button</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 139.75 850 L 132.96 958.64" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 132.63 963.88 L 129.58 956.68 L 132.96 958.64 L 136.56 957.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 118.5 1015 L 68.85 1114.3" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 66.5 1119 L 66.5 1111.17 L 68.85 1114.3 L 72.76 1114.3 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 418 1315 L 444 1315 L 461 1340 L 444 1365 L 418 1365 L 401 1340 Z" fill="#e1d5e7" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(413.5,1326.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
other<br/>
|
||||
button</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 559 1260 L 458.22 1322.99" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 453.77 1325.77 L 457.85 1319.09 L 458.22 1322.99 L 461.56 1325.03 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 422.89 1365 L 199.45 2053.94" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 197.83 2058.94 L 196.66 2051.2 L 199.45 2053.94 L 203.32 2053.36 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 528 1580 L 554 1580 L 571 1605 L 554 1630 L 528 1630 L 511 1605 Z" fill="#e1d5e7" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(523.5,1591.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
other<br/>
|
||||
button</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 608.69 1495 L 559.53 1574.89" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 556.78 1579.36 L 557.46 1571.57 L 559.53 1574.89 L 563.43 1575.24 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 524.46 1627.44 L 209.51 2054.87" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 206.4 2059.1 L 207.73 2051.39 L 209.51 2054.87 L 213.37 2055.54 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 744 1760 L 770 1760 L 787 1785 L 770 1810 L 744 1810 L 727 1785 Z" fill="#e1d5e7" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(739.5,1771.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
other<br/>
|
||||
button</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 702.71 1720 L 735.46 1759.21" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 738.82 1763.24 L 731.65 1760.11 L 735.46 1759.21 L 737.02 1755.62 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 745.8 1810 L 717.04 1874.19" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 714.9 1878.98 L 714.56 1871.16 L 717.04 1874.19 L 720.95 1874.02 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 904 1580 L 930 1580 L 947 1605 L 930 1630 L 904 1630 L 887 1605 Z" fill="#e1d5e7" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(899.5,1591.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
other<br/>
|
||||
button</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 506 1315 L 536 1315 L 551 1340 L 536 1365 L 506 1365 L 491 1340 Z" fill="#ea6b66" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(500.5,1333.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="40" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 41px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
timeout</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="20" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
timeout</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 577 1260 L 540.81 1311.71" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 537.79 1316.01 L 538.94 1308.27 L 540.81 1311.71 L 544.68 1312.28 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 509.85 1365 L 202.51 2054.18" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 200.37 2058.98 L 200.03 2051.16 L 202.51 2054.18 L 206.42 2054.01 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 908.54 1495 L 914.59 1573.65" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 914.99 1578.89 L 910.96 1572.17 L 914.59 1573.65 L 917.94 1571.64 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 950.61 1885.1 C 951.78 1881.9 953.67 1880.04 955.67 1880.12 L 1025.53 1880.12 C 1027.13 1880.08 1028.65 1880.63 1029.65 1881.61 C 1030.64 1882.59 1030.99 1883.88 1030.6 1885.1 L 1011.36 1934.9 C 1010.19 1938.1 1008.3 1939.96 1006.3 1939.88 L 935.42 1939.88 C 934.01 1939.69 932.77 1939.05 931.99 1938.1 C 931.22 1937.15 931 1935.99 931.37 1934.9 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(963.5,1888.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="41" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
notify<br/>
|
||||
button<br/>
|
||||
press</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="27" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 922.25 1630 L 973.4 1873.77" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 974.48 1878.91 L 969.61 1872.77 L 973.4 1873.77 L 976.46 1871.34 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 937.94 1940 L 770.93 2056.36" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 766.62 2059.36 L 770.37 2052.49 L 770.93 2056.36 L 774.37 2058.23 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 818 300 L 844 300 L 861 325 L 844 350 L 818 350 L 801 325 Z" fill="#e1d5e7" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(813.5,311.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
other<br/>
|
||||
button</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 670.41 260 L 800.96 312.84" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 805.83 314.81 L 798.02 315.43 L 800.96 312.84 L 800.65 308.94 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 313 995 L 339 995 L 356 1020 L 339 1045 L 313 1045 L 296 1020 Z" fill="#e1d5e7" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(308.5,1006.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
other<br/>
|
||||
button</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 392.52 948 L 348.51 995.64" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 344.95 999.49 L 347.13 991.98 L 348.51 995.64 L 352.27 996.73 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 190.61 1235.1 C 191.78 1231.9 193.67 1230.04 195.67 1230.12 L 265.53 1230.12 C 267.13 1230.08 268.65 1230.63 269.65 1231.61 C 270.64 1232.59 270.99 1233.88 270.6 1235.1 L 251.36 1284.9 C 250.19 1288.1 248.3 1289.96 246.3 1289.88 L 175.42 1289.88 C 174.01 1289.69 172.77 1289.05 171.99 1288.1 C 171.22 1287.15 171 1285.99 171.37 1284.9 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(199.5,1238.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="41" height="41" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 42px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
notify<br/>
|
||||
button<br/>
|
||||
release</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="21" y="27" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 315.06 1045 L 236.68 1224.17" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 234.57 1228.98 L 234.17 1221.16 L 236.68 1224.17 L 240.59 1223.97 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 219.9 1290 L 191.96 2053.64" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 191.77 2058.88 L 188.53 2051.76 L 191.96 2053.64 L 195.53 2052.02 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(295.5,-0.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="430" height="169" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; overflow: hidden; max-height: 190px; max-width: 430px; width: 430px; white-space: normal; overflow-wrap: normal;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
<h1>
|
||||
Entry states: IS_UP, IS_DOWN<br/>
|
||||
</h1>
|
||||
<p>
|
||||
Assumption: state is stored per-button, and OTHER BUTTON events are always processed before the actual button. Stored state per button is a single bit (up/down), a single state for the state machine across the device is sufficient.</p>
|
||||
<p>
|
||||
Start the state machine with IS_UP or IS_DOWN based on the button's bit, any OTHER BUTTON event will reset it to that state anyway, so the state can be re-used for the new button.<br/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="215" y="91" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 468 310 L 494 310 L 511 335 L 494 360 L 468 360 L 451 335 Z" fill="#e1d5e7" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g transform="translate(463.5,321.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="34" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 35px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
other<br/>
|
||||
button</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="17" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
[Not supported by viewer]</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 378.37 260 L 455 316" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 459.24 319.1 L 451.52 317.8 L 455 316 L 455.66 312.14 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 460.14 319.76 L 383.51 263.76" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 379.27 260.66 L 386.99 261.96 L 383.51 263.76 L 382.86 267.62 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<ellipse cx="1037" cy="1725" rx="40" ry="40" fill="#ffffff" stroke="#000000" pointer-events="none"/>
|
||||
<g transform="translate(1013.5,1711.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="47" height="27" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 48px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
enable<br/>
|
||||
spurious</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="24" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
enable<br>spurious</text>
|
||||
</switch>
|
||||
</g>
|
||||
<path d="M 597.84 1175 L 593.77 1213.67" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 593.22 1218.89 L 590.47 1211.56 L 593.77 1213.67 L 597.44 1212.29 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 481 310 L 481 240 L 437.37 240" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 432.12 240 L 439.12 236.5 L 437.37 240 L 439.12 243.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 831 300 L 831 240 L 707.37 240" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 702.12 240 L 709.12 236.5 L 707.37 240 L 709.12 243.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 344.68 555 L 336.52 593.77" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 335.44 598.91 L 333.46 591.34 L 336.52 593.77 L 340.31 592.78 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<rect x="657" y="2060" width="160" height="40" rx="6" ry="6" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/>
|
||||
<g transform="translate(708.5,2073.5)">
|
||||
<switch>
|
||||
<foreignObject style="overflow:visible;" pointer-events="all" width="56" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; vertical-align: top; width: 57px; white-space: nowrap; overflow-wrap: normal; text-align: center;">
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">
|
||||
IS_DOWN</div>
|
||||
</div>
|
||||
</foreignObject>
|
||||
<text x="28" y="12" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">
|
||||
IS_DOWN</text>
|
||||
</switch>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 73 KiB |
50
doc/button-debouncing-wave-diagram.txt
Normal file
50
doc/button-debouncing-wave-diagram.txt
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# Source for the button debouncing wave diagram
|
||||
# Paste into http://wavedrom.com/editor.html
|
||||
{signal: [
|
||||
{name:'current mode', wave: '3............', data: ['normal button press and release']},
|
||||
{name:'physical button', wave: '01......0....'},
|
||||
{name:'application ', wave: '01......0....'},
|
||||
{},
|
||||
['bounce mode',
|
||||
{name:'current mode', wave: '4............', data: ['debounced button press']},
|
||||
{name:'physical button', wave: '0101...0.....'},
|
||||
{name: 'timeouts', wave: '01...0.1...0.'},
|
||||
{name:'application ', wave: '01.....0.....'},
|
||||
{},
|
||||
{name:'current mode', wave: '4............', data: ['debounced button release']},
|
||||
{name:'physical button', wave: '1...010......'},
|
||||
{name: 'timeouts', wave: '0...1...0....'},
|
||||
{name:'application ', wave: '1...0........'},
|
||||
{},
|
||||
{name:'current mode', wave: '5............', data: ['delayed button press']},
|
||||
{name:'physical button', wave: '1...01.......'},
|
||||
{name: 'timeouts', wave: '0...1...0....'},
|
||||
{name:'application ', wave: '1...0...1....'},
|
||||
{},
|
||||
{name:'current mode', wave: '5............', data: ['delayed button release']},
|
||||
{name:'physical button', wave: '0...10.......'},
|
||||
{name: 'timeouts', wave: '0...1...0....'},
|
||||
{name:'application ', wave: '0...1...0....'},
|
||||
],
|
||||
{},
|
||||
['spurious mode',
|
||||
{name:'current mode', wave: '3............', data: ['first spurious button release ']},
|
||||
{name:'physical button', wave: '1.......01...'},
|
||||
{name:'application ', wave: '1.......01...'},
|
||||
{},
|
||||
{name:'current mode', wave: '3............', data: ['later spurious button release ']},
|
||||
{name:'physical button', wave: '1....01......'},
|
||||
{name: 'timeouts', wave: '0....1..0....'},
|
||||
{name:'application ', wave: '1............'},
|
||||
{},
|
||||
{name:'current mode', wave: '3............', data: ['delayed release in spurious mode ']},
|
||||
{name:'physical button', wave: '1....0.......'},
|
||||
{name: 'timeouts', wave: '0....1..0....'},
|
||||
{name:'application ', wave: '1.......0....'}
|
||||
],
|
||||
|
||||
],
|
||||
head:{
|
||||
text:'Button Debouncing Scenarios',
|
||||
},
|
||||
}
|
||||
|
|
@ -9,12 +9,25 @@ though the user only pressed or clicked the button once. This effect can be
|
|||
counteracted by "debouncing" the buttons, usually by ignoring erroneous
|
||||
events.
|
||||
|
||||
libinput has a built-in debouncing for hardware defects. This feature is
|
||||
available for all button-base devices but not active by default. When
|
||||
libinput detects a faulty button on a device, debouncing is enabled and a
|
||||
warning is printed to the log. Subsequent button events are handled
|
||||
correctly in that bouncing button events are ignored, a user should thus see
|
||||
the expected behavior.
|
||||
libinput provides two methods of debouncing buttons, referred to as the
|
||||
"bounce" and "spurious" methods:
|
||||
|
||||
- In the "bounce" method, libinput monitors hardware bouncing on button
|
||||
state changes, i.e. when a user clicks or releases a button. For example,
|
||||
if a user presses a button but the hardware generates a
|
||||
press-release-press sequence in quick succession, libinput ignores the
|
||||
release and second press event. This method is always enabled.
|
||||
- in the "spurious" method, libinput detects spurious releases of a button
|
||||
while the button is physically held down by the user. These releases are
|
||||
immediately followed by a press event. libinput monitors for these events
|
||||
and ignores the release and press event. This method is disabled by
|
||||
default and enables once libinput detects the first faulty event sequence.
|
||||
|
||||
The "bounce" method guarantees that all press events are delivered
|
||||
immediately and most release events are delivered immediately. The
|
||||
"spurious" method requires that release events are delayed, libinput thus
|
||||
does not enable this method unless a faulty event sequence is detected. A
|
||||
message is printed to the log when spurious deboucing was detected.
|
||||
|
||||
Note that libinput's debouncing intended to correct hardware damage or
|
||||
substandard hardware. Debouncing is also used as an accessibility feature
|
||||
|
|
@ -23,4 +36,12 @@ physical key presses, usually caused by involuntary muscle movement, must be
|
|||
filtered to only one key press. This feature must be implemented higher in
|
||||
the stack, libinput is limited to hardware debouncing.
|
||||
|
||||
Below is an illustration of the button debouncing modes to show the relation
|
||||
of the physical button state and the application state. Where applicable, an
|
||||
extra line is added to show the timeouts used by libinput that
|
||||
affect the button state handling. The waveform's high and low states
|
||||
correspond to the buttons 'pressed' and 'released' states, respectively.
|
||||
|
||||
@image html button-debouncing-wave-diagram.svg "Diagram illustrating button debouncing"
|
||||
|
||||
*/
|
||||
|
|
|
|||
4
doc/svg/button-debouncing-wave-diagram.svg
Normal file
4
doc/svg/button-debouncing-wave-diagram.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 105 KiB |
|
|
@ -156,7 +156,9 @@ src_libinput = [
|
|||
'src/libinput-private.h',
|
||||
'src/evdev.c',
|
||||
'src/evdev.h',
|
||||
'src/evdev-debounce.c',
|
||||
'src/evdev-fallback.c',
|
||||
'src/evdev-fallback.h',
|
||||
'src/evdev-middle-button.c',
|
||||
'src/evdev-mt-touchpad.c',
|
||||
'src/evdev-mt-touchpad.h',
|
||||
|
|
@ -298,6 +300,7 @@ if get_option('documentation')
|
|||
meson.source_root() + '/doc/dot/libinput-stack-gnome.gv',
|
||||
meson.source_root() + '/doc/dot/evemu.gv',
|
||||
# svgs
|
||||
meson.source_root() + '/doc/svg/button-debouncing-wave-diagram.svg',
|
||||
meson.source_root() + '/doc/svg/button-scrolling.svg',
|
||||
meson.source_root() + '/doc/svg/clickfinger.svg',
|
||||
meson.source_root() + '/doc/svg/clickfinger-distance.svg',
|
||||
|
|
|
|||
564
src/evdev-debounce.c
Normal file
564
src/evdev-debounce.c
Normal file
|
|
@ -0,0 +1,564 @@
|
|||
/*
|
||||
* Copyright © 2017 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "evdev-fallback.h"
|
||||
|
||||
/* Debounce cases to handle
|
||||
P ... button press
|
||||
R ... button release
|
||||
---| timeout duration
|
||||
|
||||
'normal' .... event sent when it happens
|
||||
'filtered' .. event is not sent (but may be sent later)
|
||||
'delayed' ... event is sent with wall-clock delay
|
||||
|
||||
|
||||
1) P---| R P normal, R normal
|
||||
2) R---| P R normal, P normal
|
||||
3) P---R--| P P normal, R filtered, delayed, P normal
|
||||
4) R---P--| R R normal, P filtered, delayed, R normal
|
||||
4.1) P---| R--P--| P normal, R filtered
|
||||
5) P--R-P-| R P normal, R filtered, P filtered, R normal
|
||||
6) R--P-R-| P R normal, P filtered, R filtered, P normal
|
||||
7) P--R--|
|
||||
---P-| P normal, R filtered, P filtered
|
||||
8) R--P--|
|
||||
---R-| R normal, P filtered, R filtered
|
||||
|
||||
1, 2 are the normal click cases without debouncing taking effect
|
||||
3, 4 are fast clicks where the second event is delivered with a delay
|
||||
5, 6 are contact bounces, fast
|
||||
7, 8 are contact bounces, slow
|
||||
|
||||
4.1 is a special case with the same event sequence as 4 but we want to
|
||||
filter the *release* event out, it's a button losing contact while being
|
||||
held down.
|
||||
|
||||
7 and 8 are cases where the first event happens within the first timeout
|
||||
but the second event is outside that timeout (but within the timeout of
|
||||
the second event). These cases are currently unhandled.
|
||||
*/
|
||||
|
||||
|
||||
enum debounce_event {
|
||||
DEBOUNCE_EVENT_PRESS = 50,
|
||||
DEBOUNCE_EVENT_RELEASE,
|
||||
DEBOUNCE_EVENT_TIMEOUT,
|
||||
DEBOUNCE_EVENT_TIMEOUT_SHORT,
|
||||
DEBOUNCE_EVENT_OTHERBUTTON,
|
||||
};
|
||||
|
||||
static inline const char *
|
||||
debounce_state_to_str(enum debounce_state state)
|
||||
{
|
||||
switch(state) {
|
||||
CASE_RETURN_STRING(DEBOUNCE_STATE_IS_UP);
|
||||
CASE_RETURN_STRING(DEBOUNCE_STATE_IS_DOWN);
|
||||
CASE_RETURN_STRING(DEBOUNCE_STATE_DOWN_WAITING);
|
||||
CASE_RETURN_STRING(DEBOUNCE_STATE_RELEASE_PENDING);
|
||||
CASE_RETURN_STRING(DEBOUNCE_STATE_RELEASE_DELAYED);
|
||||
CASE_RETURN_STRING(DEBOUNCE_STATE_RELEASE_WAITING);
|
||||
CASE_RETURN_STRING(DEBOUNCE_STATE_MAYBE_SPURIOUS);
|
||||
CASE_RETURN_STRING(DEBOUNCE_STATE_RELEASED);
|
||||
CASE_RETURN_STRING(DEBOUNCE_STATE_PRESS_PENDING);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline const char*
|
||||
debounce_event_to_str(enum debounce_event event)
|
||||
{
|
||||
switch(event) {
|
||||
CASE_RETURN_STRING(DEBOUNCE_EVENT_PRESS);
|
||||
CASE_RETURN_STRING(DEBOUNCE_EVENT_RELEASE);
|
||||
CASE_RETURN_STRING(DEBOUNCE_EVENT_TIMEOUT);
|
||||
CASE_RETURN_STRING(DEBOUNCE_EVENT_TIMEOUT_SHORT);
|
||||
CASE_RETURN_STRING(DEBOUNCE_EVENT_OTHERBUTTON);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
log_debounce_bug(struct fallback_dispatch *fallback, enum debounce_event event)
|
||||
{
|
||||
evdev_log_bug_libinput(fallback->device,
|
||||
"invalid debounce event %s in state %s\n",
|
||||
debounce_event_to_str(event),
|
||||
debounce_state_to_str(fallback->debounce.state));
|
||||
|
||||
}
|
||||
|
||||
static inline void
|
||||
debounce_set_state(struct fallback_dispatch *fallback,
|
||||
enum debounce_state new_state)
|
||||
{
|
||||
assert(new_state >= DEBOUNCE_STATE_IS_UP &&
|
||||
new_state <= DEBOUNCE_STATE_PRESS_PENDING);
|
||||
|
||||
fallback->debounce.state = new_state;
|
||||
}
|
||||
|
||||
static inline void
|
||||
debounce_set_timer(struct fallback_dispatch *fallback,
|
||||
uint64_t time)
|
||||
{
|
||||
const int DEBOUNCE_TIMEOUT_BOUNCE = ms2us(25);
|
||||
|
||||
libinput_timer_set(&fallback->debounce.timer,
|
||||
time + DEBOUNCE_TIMEOUT_BOUNCE);
|
||||
}
|
||||
|
||||
static inline void
|
||||
debounce_set_timer_short(struct fallback_dispatch *fallback,
|
||||
uint64_t time)
|
||||
{
|
||||
const int DEBOUNCE_TIMEOUT_SPURIOUS = ms2us(12);
|
||||
|
||||
libinput_timer_set(&fallback->debounce.timer_short,
|
||||
time + DEBOUNCE_TIMEOUT_SPURIOUS);
|
||||
}
|
||||
|
||||
static inline void
|
||||
debounce_cancel_timer(struct fallback_dispatch *fallback)
|
||||
{
|
||||
libinput_timer_cancel(&fallback->debounce.timer);
|
||||
}
|
||||
|
||||
static inline void
|
||||
debounce_cancel_timer_short(struct fallback_dispatch *fallback)
|
||||
{
|
||||
libinput_timer_cancel(&fallback->debounce.timer_short);
|
||||
}
|
||||
|
||||
static inline void
|
||||
debounce_enable_spurious(struct fallback_dispatch *fallback)
|
||||
{
|
||||
if (fallback->debounce.spurious_enabled)
|
||||
evdev_log_bug_libinput(fallback->device,
|
||||
"tried to enable spurious debouncing twice\n");
|
||||
|
||||
fallback->debounce.spurious_enabled = true;
|
||||
evdev_log_info(fallback->device,
|
||||
"Enabling spurious button debouncing, "
|
||||
"see %sbutton_debouncing.html for details\n",
|
||||
HTTP_DOC_LINK);
|
||||
}
|
||||
|
||||
static void
|
||||
debounce_notify_button(struct fallback_dispatch *fallback,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
struct evdev_device *device = fallback->device;
|
||||
unsigned int code = fallback->debounce.button_code;
|
||||
uint64_t time = fallback->debounce.button_time;
|
||||
|
||||
code = evdev_to_left_handed(device, code);
|
||||
|
||||
evdev_pointer_notify_physical_button(device, time, code, state);
|
||||
}
|
||||
|
||||
static void
|
||||
debounce_is_up_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
|
||||
{
|
||||
switch (event) {
|
||||
case DEBOUNCE_EVENT_PRESS:
|
||||
fallback->debounce.button_time = time;
|
||||
debounce_set_timer(fallback, time);
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_DOWN_WAITING);
|
||||
debounce_notify_button(fallback,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_RELEASE:
|
||||
case DEBOUNCE_EVENT_TIMEOUT:
|
||||
case DEBOUNCE_EVENT_TIMEOUT_SHORT:
|
||||
log_debounce_bug(fallback, event);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_OTHERBUTTON:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
debounce_is_down_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
|
||||
{
|
||||
switch (event) {
|
||||
case DEBOUNCE_EVENT_PRESS:
|
||||
log_debounce_bug(fallback, event);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_RELEASE:
|
||||
fallback->debounce.button_time = time;
|
||||
debounce_set_timer(fallback, time);
|
||||
debounce_set_timer_short(fallback, time);
|
||||
if (fallback->debounce.spurious_enabled) {
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_RELEASE_DELAYED);
|
||||
} else {
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_RELEASE_WAITING);
|
||||
debounce_notify_button(fallback,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
break;
|
||||
case DEBOUNCE_EVENT_TIMEOUT:
|
||||
case DEBOUNCE_EVENT_TIMEOUT_SHORT:
|
||||
log_debounce_bug(fallback, event);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_OTHERBUTTON:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
debounce_down_waiting_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
|
||||
{
|
||||
switch (event) {
|
||||
case DEBOUNCE_EVENT_PRESS:
|
||||
log_debounce_bug(fallback, event);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_RELEASE:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_RELEASE_PENDING);
|
||||
/* Note: In the debouncing RPR case, we use the last
|
||||
* release's time stamp */
|
||||
fallback->debounce.button_time = time;
|
||||
break;
|
||||
case DEBOUNCE_EVENT_TIMEOUT:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_TIMEOUT_SHORT:
|
||||
log_debounce_bug(fallback, event);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_OTHERBUTTON:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
debounce_release_pending_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
|
||||
{
|
||||
switch (event) {
|
||||
case DEBOUNCE_EVENT_PRESS:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_DOWN_WAITING);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_RELEASE:
|
||||
case DEBOUNCE_EVENT_TIMEOUT_SHORT:
|
||||
log_debounce_bug(fallback, event);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_TIMEOUT:
|
||||
case DEBOUNCE_EVENT_OTHERBUTTON:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP);
|
||||
debounce_notify_button(fallback,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
debounce_release_delayed_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
|
||||
{
|
||||
switch (event) {
|
||||
case DEBOUNCE_EVENT_PRESS:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN);
|
||||
debounce_cancel_timer(fallback);
|
||||
debounce_cancel_timer_short(fallback);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_RELEASE:
|
||||
case DEBOUNCE_EVENT_TIMEOUT:
|
||||
log_debounce_bug(fallback, event);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_TIMEOUT_SHORT:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_RELEASE_WAITING);
|
||||
debounce_notify_button(fallback,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_OTHERBUTTON:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP);
|
||||
debounce_notify_button(fallback,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
debounce_release_waiting_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
|
||||
{
|
||||
switch (event) {
|
||||
case DEBOUNCE_EVENT_PRESS:
|
||||
/* Note: in a bouncing PRP case, we use the last press
|
||||
* event time */
|
||||
fallback->debounce.button_time = time;
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_MAYBE_SPURIOUS);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_RELEASE:
|
||||
log_debounce_bug(fallback, event);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_TIMEOUT:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_TIMEOUT_SHORT:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_RELEASED);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_OTHERBUTTON:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
debounce_maybe_spurious_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
|
||||
{
|
||||
switch (event) {
|
||||
case DEBOUNCE_EVENT_PRESS:
|
||||
log_debounce_bug(fallback, event);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_RELEASE:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_RELEASE_WAITING);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_TIMEOUT:
|
||||
log_debounce_bug(fallback, event);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_TIMEOUT_SHORT:
|
||||
debounce_cancel_timer(fallback);
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN);
|
||||
debounce_enable_spurious(fallback);
|
||||
debounce_notify_button(fallback,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_OTHERBUTTON:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN);
|
||||
debounce_notify_button(fallback,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
debounce_released_handle_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
|
||||
{
|
||||
switch (event) {
|
||||
case DEBOUNCE_EVENT_PRESS:
|
||||
/* Note: in a debouncing PRP case, we use the last press'
|
||||
* time */
|
||||
fallback->debounce.button_time = time;
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_PRESS_PENDING);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_RELEASE:
|
||||
case DEBOUNCE_EVENT_TIMEOUT_SHORT:
|
||||
log_debounce_bug(fallback, event);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_TIMEOUT:
|
||||
case DEBOUNCE_EVENT_OTHERBUTTON:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
debounce_press_pending_event(struct fallback_dispatch *fallback, enum debounce_event event, uint64_t time)
|
||||
{
|
||||
switch (event) {
|
||||
case DEBOUNCE_EVENT_PRESS:
|
||||
log_debounce_bug(fallback, event);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_RELEASE:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_RELEASED);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_TIMEOUT_SHORT:
|
||||
log_debounce_bug(fallback, event);
|
||||
break;
|
||||
case DEBOUNCE_EVENT_TIMEOUT:
|
||||
case DEBOUNCE_EVENT_OTHERBUTTON:
|
||||
debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN);
|
||||
debounce_notify_button(fallback,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
debounce_handle_event(struct fallback_dispatch *fallback,
|
||||
enum debounce_event event,
|
||||
uint64_t time)
|
||||
{
|
||||
enum debounce_state current = fallback->debounce.state;
|
||||
|
||||
if (event == DEBOUNCE_EVENT_OTHERBUTTON) {
|
||||
debounce_cancel_timer(fallback);
|
||||
debounce_cancel_timer_short(fallback);
|
||||
}
|
||||
|
||||
switch(current) {
|
||||
case DEBOUNCE_STATE_IS_UP:
|
||||
debounce_is_up_handle_event(fallback, event, time);
|
||||
break;
|
||||
case DEBOUNCE_STATE_IS_DOWN:
|
||||
debounce_is_down_handle_event(fallback, event, time);
|
||||
break;
|
||||
case DEBOUNCE_STATE_DOWN_WAITING:
|
||||
debounce_down_waiting_handle_event(fallback, event, time);
|
||||
break;
|
||||
case DEBOUNCE_STATE_RELEASE_PENDING:
|
||||
debounce_release_pending_handle_event(fallback, event, time);
|
||||
break;
|
||||
case DEBOUNCE_STATE_RELEASE_DELAYED:
|
||||
debounce_release_delayed_handle_event(fallback, event, time);
|
||||
break;
|
||||
case DEBOUNCE_STATE_RELEASE_WAITING:
|
||||
debounce_release_waiting_handle_event(fallback, event, time);
|
||||
break;
|
||||
case DEBOUNCE_STATE_MAYBE_SPURIOUS:
|
||||
debounce_maybe_spurious_handle_event(fallback, event, time);
|
||||
break;
|
||||
case DEBOUNCE_STATE_RELEASED:
|
||||
debounce_released_handle_event(fallback, event, time);
|
||||
break;
|
||||
case DEBOUNCE_STATE_PRESS_PENDING:
|
||||
debounce_press_pending_event(fallback, event, time);
|
||||
break;
|
||||
}
|
||||
|
||||
evdev_log_debug(fallback->device,
|
||||
"debounce state: %s → %s → %s\n",
|
||||
debounce_state_to_str(current),
|
||||
debounce_event_to_str(event),
|
||||
debounce_state_to_str(fallback->debounce.state));
|
||||
}
|
||||
|
||||
void
|
||||
fallback_debounce_handle_state(struct fallback_dispatch *dispatch,
|
||||
uint64_t time)
|
||||
{
|
||||
unsigned int changed[16] = {0}; /* event codes of changed buttons */
|
||||
size_t nchanged = 0;
|
||||
bool flushed = false;
|
||||
|
||||
for (unsigned int code = 0; code <= KEY_MAX; code++) {
|
||||
if (get_key_type(code) != KEY_TYPE_BUTTON)
|
||||
continue;
|
||||
|
||||
if (hw_key_has_changed(dispatch, code))
|
||||
changed[nchanged++] = code;
|
||||
|
||||
/* If you manage to press more than 16 buttons in the same
|
||||
* frame, we just quietly ignore the rest of them */
|
||||
if (nchanged == ARRAY_LENGTH(changed))
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we have more than one button this frame or a different button,
|
||||
* flush the state machine with otherbutton */
|
||||
if (nchanged > 1 ||
|
||||
changed[0] != dispatch->debounce.button_code) {
|
||||
debounce_handle_event(dispatch,
|
||||
DEBOUNCE_EVENT_OTHERBUTTON,
|
||||
time);
|
||||
flushed = true;
|
||||
}
|
||||
|
||||
/* The state machine has some pre-conditions:
|
||||
* - the IS_DOWN and IS_UP states are neutral entry states without
|
||||
* any timeouts
|
||||
* - a OTHERBUTTON event always flushes the state to IS_DOWN or
|
||||
* IS_UP
|
||||
*/
|
||||
|
||||
for (size_t i = 0; i < nchanged; i++) {
|
||||
bool is_down = hw_is_key_down(dispatch, changed[i]);
|
||||
|
||||
if (flushed) {
|
||||
debounce_set_state(dispatch,
|
||||
!is_down ?
|
||||
DEBOUNCE_STATE_IS_DOWN :
|
||||
DEBOUNCE_STATE_IS_UP);
|
||||
flushed = false;
|
||||
}
|
||||
|
||||
|
||||
dispatch->debounce.button_code = changed[i];
|
||||
debounce_handle_event(dispatch,
|
||||
is_down ?
|
||||
DEBOUNCE_EVENT_PRESS :
|
||||
DEBOUNCE_EVENT_RELEASE,
|
||||
time);
|
||||
|
||||
/* if we have more than one event, we flush the state
|
||||
* machine immediately after the event itself */
|
||||
if (nchanged > 1) {
|
||||
debounce_handle_event(dispatch,
|
||||
DEBOUNCE_EVENT_OTHERBUTTON,
|
||||
time);
|
||||
flushed = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
debounce_timeout(uint64_t now, void *data)
|
||||
{
|
||||
struct evdev_device *device = data;
|
||||
struct fallback_dispatch *dispatch =
|
||||
fallback_dispatch(device->dispatch);
|
||||
|
||||
debounce_handle_event(dispatch, DEBOUNCE_EVENT_TIMEOUT, now);
|
||||
}
|
||||
|
||||
static void
|
||||
debounce_timeout_short(uint64_t now, void *data)
|
||||
{
|
||||
struct evdev_device *device = data;
|
||||
struct fallback_dispatch *dispatch =
|
||||
fallback_dispatch(device->dispatch);
|
||||
|
||||
debounce_handle_event(dispatch, DEBOUNCE_EVENT_TIMEOUT_SHORT, now);
|
||||
}
|
||||
|
||||
void
|
||||
fallback_init_debounce(struct fallback_dispatch *dispatch)
|
||||
{
|
||||
struct evdev_device *device = dispatch->device;
|
||||
char timer_name[64];
|
||||
|
||||
dispatch->debounce.state = DEBOUNCE_STATE_IS_UP;
|
||||
|
||||
snprintf(timer_name,
|
||||
sizeof(timer_name),
|
||||
"%s debounce short",
|
||||
evdev_device_get_sysname(device));
|
||||
libinput_timer_init(&dispatch->debounce.timer_short,
|
||||
evdev_libinput_context(device),
|
||||
timer_name,
|
||||
debounce_timeout_short,
|
||||
device);
|
||||
|
||||
snprintf(timer_name,
|
||||
sizeof(timer_name),
|
||||
"%s debounce",
|
||||
evdev_device_get_sysname(device));
|
||||
libinput_timer_init(&dispatch->debounce.timer,
|
||||
evdev_libinput_context(device),
|
||||
timer_name,
|
||||
debounce_timeout,
|
||||
device);
|
||||
}
|
||||
|
|
@ -28,124 +28,10 @@
|
|||
|
||||
#include <mtdev-plumbing.h>
|
||||
|
||||
#include "evdev.h"
|
||||
#include "evdev-fallback.h"
|
||||
|
||||
#define DEBOUNCE_TIME ms2us(12)
|
||||
|
||||
struct fallback_dispatch {
|
||||
struct evdev_dispatch base;
|
||||
struct evdev_device *device;
|
||||
|
||||
struct libinput_device_config_calibration calibration;
|
||||
|
||||
struct {
|
||||
bool is_enabled;
|
||||
int angle;
|
||||
struct matrix matrix;
|
||||
struct libinput_device_config_rotation config;
|
||||
} rotation;
|
||||
|
||||
struct {
|
||||
struct device_coords point;
|
||||
int32_t seat_slot;
|
||||
|
||||
struct {
|
||||
struct device_coords min, max;
|
||||
struct ratelimit range_warn_limit;
|
||||
} warning_range;
|
||||
} abs;
|
||||
|
||||
struct {
|
||||
int slot;
|
||||
struct mt_slot *slots;
|
||||
size_t slots_len;
|
||||
bool want_hysteresis;
|
||||
struct device_coords hysteresis_margin;
|
||||
} mt;
|
||||
|
||||
struct device_coords rel;
|
||||
|
||||
struct {
|
||||
/* The struct for the tablet mode switch device itself */
|
||||
struct {
|
||||
int state;
|
||||
} sw;
|
||||
/* The struct for other devices listening to the tablet mode
|
||||
switch */
|
||||
struct {
|
||||
struct evdev_device *sw_device;
|
||||
struct libinput_event_listener listener;
|
||||
} other;
|
||||
} tablet_mode;
|
||||
|
||||
/* Bitmask of pressed keys used to ignore initial release events from
|
||||
* the kernel. */
|
||||
unsigned long hw_key_mask[NLONGS(KEY_CNT)];
|
||||
|
||||
enum evdev_event_type pending_event;
|
||||
|
||||
/* true if we're reading events (i.e. not suspended) but we're
|
||||
ignoring them */
|
||||
bool ignore_events;
|
||||
|
||||
struct {
|
||||
enum evdev_debounce_state state;
|
||||
unsigned int button_code;
|
||||
uint64_t button_up_time;
|
||||
struct libinput_timer timer;
|
||||
} debounce;
|
||||
|
||||
struct {
|
||||
enum switch_reliability reliability;
|
||||
|
||||
bool is_closed;
|
||||
bool is_closed_client_state;
|
||||
|
||||
/* We allow up to 3 paired keyboards for the lid switch
|
||||
* listener. Only one keyboard should exist, but that can
|
||||
* have more than one event node.
|
||||
*
|
||||
* Note: this is a sparse list, any element may have a
|
||||
* non-NULL device.
|
||||
*/
|
||||
struct paired_keyboard {
|
||||
struct evdev_device *device;
|
||||
struct libinput_event_listener listener;
|
||||
} paired_keyboard[3];
|
||||
} lid;
|
||||
};
|
||||
|
||||
static inline struct fallback_dispatch*
|
||||
fallback_dispatch(struct evdev_dispatch *dispatch)
|
||||
{
|
||||
evdev_verify_dispatch_type(dispatch, DISPATCH_FALLBACK);
|
||||
|
||||
return container_of(dispatch, struct fallback_dispatch, base);
|
||||
}
|
||||
enum key_type {
|
||||
KEY_TYPE_NONE,
|
||||
KEY_TYPE_KEY,
|
||||
KEY_TYPE_BUTTON,
|
||||
};
|
||||
|
||||
static void
|
||||
hw_set_key_down(struct fallback_dispatch *dispatch, int code, int pressed)
|
||||
{
|
||||
long_set_bit_state(dispatch->hw_key_mask, code, pressed);
|
||||
}
|
||||
|
||||
static bool
|
||||
hw_is_key_down(struct fallback_dispatch *dispatch, int code)
|
||||
{
|
||||
return long_bit_is_set(dispatch->hw_key_mask, code);
|
||||
}
|
||||
|
||||
static int
|
||||
get_key_down_count(struct evdev_device *device, int code)
|
||||
{
|
||||
return device->key_count[code];
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_keyboard_notify_key(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
|
|
@ -317,6 +203,58 @@ fallback_flush_relative_motion(struct fallback_dispatch *dispatch,
|
|||
pointer_notify_motion(base, time, &accel, &raw);
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_flush_wheels(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
uint64_t time)
|
||||
{
|
||||
struct normalized_coords wheel_degrees = { 0.0, 0.0 };
|
||||
struct discrete_coords discrete = { 0.0, 0.0 };
|
||||
enum libinput_pointer_axis_source source;
|
||||
|
||||
if (!(device->seat_caps & EVDEV_DEVICE_POINTER))
|
||||
return;
|
||||
|
||||
|
||||
if (dispatch->wheel.y != 0) {
|
||||
wheel_degrees.y = -1 * dispatch->wheel.y *
|
||||
device->scroll.wheel_click_angle.y;
|
||||
discrete.y = -1 * dispatch->wheel.y;
|
||||
|
||||
source = device->scroll.is_tilt.vertical ?
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL;
|
||||
|
||||
evdev_notify_axis(
|
||||
device,
|
||||
time,
|
||||
AS_MASK(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL),
|
||||
source,
|
||||
&wheel_degrees,
|
||||
&discrete);
|
||||
dispatch->wheel.y = 0;
|
||||
}
|
||||
|
||||
if (dispatch->wheel.x != 0) {
|
||||
wheel_degrees.x = dispatch->wheel.x *
|
||||
device->scroll.wheel_click_angle.x;
|
||||
discrete.x = dispatch->wheel.x;
|
||||
|
||||
source = device->scroll.is_tilt.horizontal ?
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL;
|
||||
|
||||
evdev_notify_axis(
|
||||
device,
|
||||
time,
|
||||
AS_MASK(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL),
|
||||
source,
|
||||
&wheel_degrees,
|
||||
&discrete);
|
||||
dispatch->wheel.x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_flush_absolute_motion(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
|
|
@ -514,267 +452,14 @@ fallback_flush_st_up(struct fallback_dispatch *dispatch,
|
|||
return true;
|
||||
}
|
||||
|
||||
static enum evdev_event_type
|
||||
fallback_flush_pending_event(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
uint64_t time)
|
||||
{
|
||||
enum evdev_event_type sent_event;
|
||||
int slot_idx;
|
||||
|
||||
sent_event = dispatch->pending_event;
|
||||
|
||||
switch (dispatch->pending_event) {
|
||||
case EVDEV_NONE:
|
||||
break;
|
||||
case EVDEV_RELATIVE_MOTION:
|
||||
fallback_flush_relative_motion(dispatch, device, time);
|
||||
break;
|
||||
case EVDEV_ABSOLUTE_MT_DOWN:
|
||||
slot_idx = dispatch->mt.slot;
|
||||
if (!fallback_flush_mt_down(dispatch,
|
||||
device,
|
||||
slot_idx,
|
||||
time))
|
||||
sent_event = EVDEV_NONE;
|
||||
break;
|
||||
case EVDEV_ABSOLUTE_MT_MOTION:
|
||||
slot_idx = dispatch->mt.slot;
|
||||
if (!fallback_flush_mt_motion(dispatch,
|
||||
device,
|
||||
slot_idx,
|
||||
time))
|
||||
sent_event = EVDEV_NONE;
|
||||
break;
|
||||
case EVDEV_ABSOLUTE_MT_UP:
|
||||
slot_idx = dispatch->mt.slot;
|
||||
if (!fallback_flush_mt_up(dispatch,
|
||||
device,
|
||||
slot_idx,
|
||||
time))
|
||||
sent_event = EVDEV_NONE;
|
||||
break;
|
||||
case EVDEV_ABSOLUTE_TOUCH_DOWN:
|
||||
if (!fallback_flush_st_down(dispatch, device, time))
|
||||
sent_event = EVDEV_NONE;
|
||||
break;
|
||||
case EVDEV_ABSOLUTE_MOTION:
|
||||
if (device->seat_caps & EVDEV_DEVICE_TOUCH) {
|
||||
if (fallback_flush_st_motion(dispatch,
|
||||
device,
|
||||
time))
|
||||
sent_event = EVDEV_ABSOLUTE_MT_MOTION;
|
||||
else
|
||||
sent_event = EVDEV_NONE;
|
||||
} else if (device->seat_caps & EVDEV_DEVICE_POINTER) {
|
||||
fallback_flush_absolute_motion(dispatch,
|
||||
device,
|
||||
time);
|
||||
}
|
||||
break;
|
||||
case EVDEV_ABSOLUTE_TOUCH_UP:
|
||||
if (!fallback_flush_st_up(dispatch, device, time))
|
||||
sent_event = EVDEV_NONE;
|
||||
break;
|
||||
default:
|
||||
assert(0 && "Unknown pending event type");
|
||||
break;
|
||||
}
|
||||
|
||||
dispatch->pending_event = EVDEV_NONE;
|
||||
|
||||
return sent_event;
|
||||
}
|
||||
|
||||
static enum key_type
|
||||
get_key_type(uint16_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case BTN_TOOL_PEN:
|
||||
case BTN_TOOL_RUBBER:
|
||||
case BTN_TOOL_BRUSH:
|
||||
case BTN_TOOL_PENCIL:
|
||||
case BTN_TOOL_AIRBRUSH:
|
||||
case BTN_TOOL_MOUSE:
|
||||
case BTN_TOOL_LENS:
|
||||
case BTN_TOOL_QUINTTAP:
|
||||
case BTN_TOOL_DOUBLETAP:
|
||||
case BTN_TOOL_TRIPLETAP:
|
||||
case BTN_TOOL_QUADTAP:
|
||||
case BTN_TOOL_FINGER:
|
||||
case BTN_TOUCH:
|
||||
return KEY_TYPE_NONE;
|
||||
}
|
||||
|
||||
if (code >= KEY_ESC && code <= KEY_MICMUTE)
|
||||
return KEY_TYPE_KEY;
|
||||
if (code >= BTN_MISC && code <= BTN_GEAR_UP)
|
||||
return KEY_TYPE_BUTTON;
|
||||
if (code >= KEY_OK && code <= KEY_LIGHTS_TOGGLE)
|
||||
return KEY_TYPE_KEY;
|
||||
if (code >= BTN_DPAD_UP && code <= BTN_DPAD_RIGHT)
|
||||
return KEY_TYPE_BUTTON;
|
||||
if (code >= KEY_ALS_TOGGLE && code <= KEY_ONSCREEN_KEYBOARD)
|
||||
return KEY_TYPE_KEY;
|
||||
if (code >= BTN_TRIGGER_HAPPY && code <= BTN_TRIGGER_HAPPY40)
|
||||
return KEY_TYPE_BUTTON;
|
||||
return KEY_TYPE_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_process_touch_button(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
uint64_t time, int value)
|
||||
{
|
||||
if (dispatch->pending_event != EVDEV_NONE &&
|
||||
dispatch->pending_event != EVDEV_ABSOLUTE_MOTION)
|
||||
fallback_flush_pending_event(dispatch, device, time);
|
||||
|
||||
dispatch->pending_event = (value ?
|
||||
dispatch->pending_event |= (value) ?
|
||||
EVDEV_ABSOLUTE_TOUCH_DOWN :
|
||||
EVDEV_ABSOLUTE_TOUCH_UP);
|
||||
}
|
||||
|
||||
static inline void
|
||||
fallback_flush_debounce(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
int code = dispatch->debounce.button_code;
|
||||
int button;
|
||||
|
||||
if (dispatch->debounce.state != DEBOUNCE_ACTIVE)
|
||||
return;
|
||||
|
||||
if (hw_is_key_down(dispatch, code)) {
|
||||
button = evdev_to_left_handed(device, code);
|
||||
evdev_pointer_notify_physical_button(device,
|
||||
dispatch->debounce.button_up_time,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
hw_set_key_down(dispatch, code, 0);
|
||||
}
|
||||
|
||||
dispatch->debounce.state = DEBOUNCE_ON;
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_debounce_timeout(uint64_t now, void *data)
|
||||
{
|
||||
struct evdev_device *device = data;
|
||||
struct fallback_dispatch *dispatch =
|
||||
fallback_dispatch(device->dispatch);
|
||||
|
||||
fallback_flush_debounce(dispatch, device);
|
||||
}
|
||||
|
||||
static bool
|
||||
fallback_filter_debounce_press(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
struct input_event *e,
|
||||
uint64_t time)
|
||||
{
|
||||
bool filter = false;
|
||||
uint64_t tdelta;
|
||||
|
||||
/* If other button is pressed while we're holding back the release,
|
||||
* flush the pending release (if any) and continue. We don't handle
|
||||
* this situation, if you have a mouse that needs per-button
|
||||
* debouncing, consider writing to santa for a new mouse.
|
||||
*/
|
||||
if (e->code != dispatch->debounce.button_code) {
|
||||
if (dispatch->debounce.state == DEBOUNCE_ACTIVE) {
|
||||
libinput_timer_cancel(&dispatch->debounce.timer);
|
||||
fallback_flush_debounce(dispatch, device);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
tdelta = time - dispatch->debounce.button_up_time;
|
||||
assert((int64_t)tdelta >= 0);
|
||||
|
||||
if (tdelta < DEBOUNCE_TIME) {
|
||||
switch (dispatch->debounce.state) {
|
||||
case DEBOUNCE_INIT:
|
||||
/* This is the first time we debounce, enable proper debouncing
|
||||
from now on but filter this press event */
|
||||
filter = true;
|
||||
evdev_log_info(device,
|
||||
"Enabling button debouncing, "
|
||||
"see %sbutton_debouncing.html for details\n",
|
||||
HTTP_DOC_LINK);
|
||||
dispatch->debounce.state = DEBOUNCE_NEEDED;
|
||||
break;
|
||||
case DEBOUNCE_NEEDED:
|
||||
case DEBOUNCE_ON:
|
||||
break;
|
||||
/* If a release event is pending and, filter press
|
||||
* events until we flushed the release */
|
||||
case DEBOUNCE_ACTIVE:
|
||||
filter = true;
|
||||
break;
|
||||
}
|
||||
} else if (dispatch->debounce.state == DEBOUNCE_ACTIVE) {
|
||||
/* call libinput_dispatch() more frequently */
|
||||
evdev_log_bug_client(device,
|
||||
"Debouncing still active past timeout\n");
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
static bool
|
||||
fallback_filter_debounce_release(struct fallback_dispatch *dispatch,
|
||||
struct input_event *e,
|
||||
uint64_t time)
|
||||
{
|
||||
bool filter = false;
|
||||
|
||||
dispatch->debounce.button_code = e->code;
|
||||
dispatch->debounce.button_up_time = time;
|
||||
|
||||
switch (dispatch->debounce.state) {
|
||||
case DEBOUNCE_INIT:
|
||||
break;
|
||||
case DEBOUNCE_NEEDED:
|
||||
filter = true;
|
||||
dispatch->debounce.state = DEBOUNCE_ON;
|
||||
break;
|
||||
case DEBOUNCE_ON:
|
||||
libinput_timer_set(&dispatch->debounce.timer,
|
||||
time + DEBOUNCE_TIME);
|
||||
filter = true;
|
||||
dispatch->debounce.state = DEBOUNCE_ACTIVE;
|
||||
break;
|
||||
case DEBOUNCE_ACTIVE:
|
||||
filter = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
static bool
|
||||
fallback_filter_debounce(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
struct input_event *e, uint64_t time)
|
||||
{
|
||||
bool filter = false;
|
||||
|
||||
/* Behavior: we monitor the time deltas between release and press
|
||||
* events. Proper debouncing is disabled on init, but the first
|
||||
* time we see a bouncing press event we enable it.
|
||||
*
|
||||
* The first bounced event is simply discarded, which ends up in the
|
||||
* button being released sooner than it should be. Subsequent button
|
||||
* presses are timer-based and thus released a bit later because we
|
||||
* then wait for a timeout before we post the release event.
|
||||
*/
|
||||
if (e->value)
|
||||
filter = fallback_filter_debounce_press(dispatch, device, e, time);
|
||||
else
|
||||
filter = fallback_filter_debounce_release(dispatch, e, time);
|
||||
|
||||
return filter;
|
||||
EVDEV_ABSOLUTE_TOUCH_UP;
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -797,8 +482,6 @@ fallback_process_key(struct fallback_dispatch *dispatch,
|
|||
return;
|
||||
}
|
||||
|
||||
fallback_flush_pending_event(dispatch, device, time);
|
||||
|
||||
type = get_key_type(e->code);
|
||||
|
||||
/* Ignore key release events from the kernel for keys that libinput
|
||||
|
|
@ -808,43 +491,16 @@ fallback_process_key(struct fallback_dispatch *dispatch,
|
|||
case KEY_TYPE_NONE:
|
||||
break;
|
||||
case KEY_TYPE_KEY:
|
||||
case KEY_TYPE_BUTTON:
|
||||
if ((e->value && hw_is_key_down(dispatch, e->code)) ||
|
||||
(e->value == 0 && !hw_is_key_down(dispatch, e->code)))
|
||||
return;
|
||||
break;
|
||||
case KEY_TYPE_BUTTON:
|
||||
if (fallback_filter_debounce(dispatch, device, e, time))
|
||||
return;
|
||||
|
||||
if ((e->value && hw_is_key_down(dispatch, e->code)) ||
|
||||
(e->value == 0 && !hw_is_key_down(dispatch, e->code)))
|
||||
return;
|
||||
dispatch->pending_event |= EVDEV_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
hw_set_key_down(dispatch, e->code, e->value);
|
||||
|
||||
switch (type) {
|
||||
case KEY_TYPE_NONE:
|
||||
break;
|
||||
case KEY_TYPE_KEY:
|
||||
fallback_keyboard_notify_key(
|
||||
dispatch,
|
||||
device,
|
||||
time,
|
||||
e->code,
|
||||
e->value ? LIBINPUT_KEY_STATE_PRESSED :
|
||||
LIBINPUT_KEY_STATE_RELEASED);
|
||||
break;
|
||||
case KEY_TYPE_BUTTON:
|
||||
evdev_pointer_notify_physical_button(
|
||||
device,
|
||||
time,
|
||||
evdev_to_left_handed(device, e->code),
|
||||
e->value ? LIBINPUT_BUTTON_STATE_PRESSED :
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -853,8 +509,9 @@ fallback_process_touch(struct fallback_dispatch *dispatch,
|
|||
struct input_event *e,
|
||||
uint64_t time)
|
||||
{
|
||||
switch (e->code) {
|
||||
case ABS_MT_SLOT:
|
||||
struct mt_slot *slot = &dispatch->mt.slots[dispatch->mt.slot];
|
||||
|
||||
if (e->code == ABS_MT_SLOT) {
|
||||
if ((size_t)e->value >= dispatch->mt.slots_len) {
|
||||
evdev_log_bug_libinput(device,
|
||||
"exceeded slot count (%d of max %zd)\n",
|
||||
|
|
@ -862,32 +519,36 @@ fallback_process_touch(struct fallback_dispatch *dispatch,
|
|||
dispatch->mt.slots_len);
|
||||
e->value = dispatch->mt.slots_len - 1;
|
||||
}
|
||||
fallback_flush_pending_event(dispatch, device, time);
|
||||
dispatch->mt.slot = e->value;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (e->code) {
|
||||
case ABS_MT_TRACKING_ID:
|
||||
if (dispatch->pending_event != EVDEV_NONE &&
|
||||
dispatch->pending_event != EVDEV_ABSOLUTE_MT_MOTION)
|
||||
fallback_flush_pending_event(dispatch, device, time);
|
||||
if (e->value >= 0)
|
||||
dispatch->pending_event = EVDEV_ABSOLUTE_MT_DOWN;
|
||||
else
|
||||
dispatch->pending_event = EVDEV_ABSOLUTE_MT_UP;
|
||||
if (e->value >= 0) {
|
||||
dispatch->pending_event |= EVDEV_ABSOLUTE_MT;
|
||||
slot->state = SLOT_STATE_BEGIN;
|
||||
} else {
|
||||
dispatch->pending_event |= EVDEV_ABSOLUTE_MT;
|
||||
slot->state = SLOT_STATE_END;
|
||||
}
|
||||
slot->dirty = true;
|
||||
break;
|
||||
case ABS_MT_POSITION_X:
|
||||
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
||||
dispatch->mt.slots[dispatch->mt.slot].point.x = e->value;
|
||||
if (dispatch->pending_event == EVDEV_NONE)
|
||||
dispatch->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
|
||||
dispatch->pending_event |= EVDEV_ABSOLUTE_MT;
|
||||
slot->dirty = true;
|
||||
break;
|
||||
case ABS_MT_POSITION_Y:
|
||||
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
||||
dispatch->mt.slots[dispatch->mt.slot].point.y = e->value;
|
||||
if (dispatch->pending_event == EVDEV_NONE)
|
||||
dispatch->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
|
||||
dispatch->pending_event |= EVDEV_ABSOLUTE_MT;
|
||||
slot->dirty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
fallback_process_absolute_motion(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
|
|
@ -897,14 +558,12 @@ fallback_process_absolute_motion(struct fallback_dispatch *dispatch,
|
|||
case ABS_X:
|
||||
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
||||
dispatch->abs.point.x = e->value;
|
||||
if (dispatch->pending_event == EVDEV_NONE)
|
||||
dispatch->pending_event = EVDEV_ABSOLUTE_MOTION;
|
||||
dispatch->pending_event |= EVDEV_ABSOLUTE_MOTION;
|
||||
break;
|
||||
case ABS_Y:
|
||||
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
||||
dispatch->abs.point.y = e->value;
|
||||
if (dispatch->pending_event == EVDEV_NONE)
|
||||
dispatch->pending_event = EVDEV_ABSOLUTE_MOTION;
|
||||
dispatch->pending_event |= EVDEV_ABSOLUTE_MOTION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -994,6 +653,8 @@ fallback_process_switch(struct fallback_dispatch *dispatch,
|
|||
enum libinput_switch_state state;
|
||||
bool is_closed;
|
||||
|
||||
/* TODO: this should to move to handle_state */
|
||||
|
||||
switch (e->code) {
|
||||
case SW_LID:
|
||||
is_closed = !!e->value;
|
||||
|
|
@ -1044,61 +705,25 @@ fallback_process_relative(struct fallback_dispatch *dispatch,
|
|||
struct evdev_device *device,
|
||||
struct input_event *e, uint64_t time)
|
||||
{
|
||||
struct normalized_coords wheel_degrees = { 0.0, 0.0 };
|
||||
struct discrete_coords discrete = { 0.0, 0.0 };
|
||||
enum libinput_pointer_axis_source source;
|
||||
|
||||
if (fallback_reject_relative(device, e, time))
|
||||
return;
|
||||
|
||||
switch (e->code) {
|
||||
case REL_X:
|
||||
if (dispatch->pending_event != EVDEV_RELATIVE_MOTION)
|
||||
fallback_flush_pending_event(dispatch, device, time);
|
||||
dispatch->rel.x += e->value;
|
||||
dispatch->pending_event = EVDEV_RELATIVE_MOTION;
|
||||
dispatch->pending_event |= EVDEV_RELATIVE_MOTION;
|
||||
break;
|
||||
case REL_Y:
|
||||
if (dispatch->pending_event != EVDEV_RELATIVE_MOTION)
|
||||
fallback_flush_pending_event(dispatch, device, time);
|
||||
dispatch->rel.y += e->value;
|
||||
dispatch->pending_event = EVDEV_RELATIVE_MOTION;
|
||||
dispatch->pending_event |= EVDEV_RELATIVE_MOTION;
|
||||
break;
|
||||
case REL_WHEEL:
|
||||
fallback_flush_pending_event(dispatch, device, time);
|
||||
wheel_degrees.y = -1 * e->value *
|
||||
device->scroll.wheel_click_angle.y;
|
||||
discrete.y = -1 * e->value;
|
||||
|
||||
source = device->scroll.is_tilt.vertical ?
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL;
|
||||
|
||||
evdev_notify_axis(
|
||||
device,
|
||||
time,
|
||||
AS_MASK(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL),
|
||||
source,
|
||||
&wheel_degrees,
|
||||
&discrete);
|
||||
dispatch->wheel.y += e->value;
|
||||
dispatch->pending_event |= EVDEV_WHEEL;
|
||||
break;
|
||||
case REL_HWHEEL:
|
||||
fallback_flush_pending_event(dispatch, device, time);
|
||||
wheel_degrees.x = e->value *
|
||||
device->scroll.wheel_click_angle.x;
|
||||
discrete.x = e->value;
|
||||
|
||||
source = device->scroll.is_tilt.horizontal ?
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
|
||||
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL;
|
||||
|
||||
evdev_notify_axis(
|
||||
device,
|
||||
time,
|
||||
AS_MASK(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL),
|
||||
source,
|
||||
&wheel_degrees,
|
||||
&discrete);
|
||||
dispatch->wheel.x += e->value;
|
||||
dispatch->pending_event |= EVDEV_WHEEL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1130,6 +755,120 @@ fallback_any_button_down(struct fallback_dispatch *dispatch,
|
|||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_handle_state(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
uint64_t time)
|
||||
{
|
||||
bool need_touch_frame = false;
|
||||
|
||||
/* Relative motion */
|
||||
if (dispatch->pending_event & EVDEV_RELATIVE_MOTION)
|
||||
fallback_flush_relative_motion(dispatch, device, time);
|
||||
|
||||
/* Single touch or absolute pointer devices */
|
||||
if (dispatch->pending_event & EVDEV_ABSOLUTE_TOUCH_DOWN) {
|
||||
if (fallback_flush_st_down(dispatch, device, time))
|
||||
need_touch_frame = true;
|
||||
}
|
||||
|
||||
if (dispatch->pending_event & EVDEV_ABSOLUTE_MOTION) {
|
||||
if (device->seat_caps & EVDEV_DEVICE_TOUCH) {
|
||||
if (fallback_flush_st_motion(dispatch,
|
||||
device,
|
||||
time))
|
||||
need_touch_frame = true;
|
||||
} else if (device->seat_caps & EVDEV_DEVICE_POINTER) {
|
||||
fallback_flush_absolute_motion(dispatch,
|
||||
device,
|
||||
time);
|
||||
}
|
||||
}
|
||||
|
||||
if (dispatch->pending_event & EVDEV_ABSOLUTE_TOUCH_UP) {
|
||||
if (fallback_flush_st_up(dispatch, device, time))
|
||||
need_touch_frame = true;
|
||||
}
|
||||
|
||||
/* Multitouch devices */
|
||||
if (dispatch->pending_event & EVDEV_ABSOLUTE_MT) {
|
||||
bool sent = false;
|
||||
for (size_t i = 0; i < dispatch->mt.slots_len; i++) {
|
||||
struct mt_slot *slot = &dispatch->mt.slots[i];
|
||||
|
||||
if (!slot->dirty)
|
||||
continue;
|
||||
|
||||
if (slot->state == SLOT_STATE_BEGIN) {
|
||||
sent = fallback_flush_mt_down(dispatch,
|
||||
device,
|
||||
i,
|
||||
time);
|
||||
slot->state = SLOT_STATE_UPDATE;
|
||||
} else if (slot->state == SLOT_STATE_UPDATE) {
|
||||
sent = fallback_flush_mt_motion(dispatch,
|
||||
device,
|
||||
i,
|
||||
time);
|
||||
} else if (slot->state == SLOT_STATE_END) {
|
||||
sent = fallback_flush_mt_up(dispatch,
|
||||
device,
|
||||
i,
|
||||
time);
|
||||
slot->state = SLOT_STATE_NONE;
|
||||
}
|
||||
|
||||
|
||||
slot->dirty = false;
|
||||
}
|
||||
|
||||
need_touch_frame = sent;
|
||||
}
|
||||
|
||||
if (need_touch_frame)
|
||||
touch_notify_frame(&device->base, time);
|
||||
|
||||
fallback_flush_wheels(dispatch, device, time);
|
||||
|
||||
/* Buttons and keys */
|
||||
if (dispatch->pending_event & EVDEV_KEY) {
|
||||
bool want_debounce = false;
|
||||
for (unsigned int code = 0; code <= KEY_MAX; code++) {
|
||||
bool new_state;
|
||||
|
||||
if (!hw_key_has_changed(dispatch, code))
|
||||
continue;
|
||||
|
||||
new_state = hw_is_key_down(dispatch, code);
|
||||
|
||||
switch (get_key_type(code)) {
|
||||
case KEY_TYPE_NONE:
|
||||
break;
|
||||
case KEY_TYPE_KEY:
|
||||
fallback_keyboard_notify_key(
|
||||
dispatch,
|
||||
device,
|
||||
time,
|
||||
code,
|
||||
new_state ?
|
||||
LIBINPUT_KEY_STATE_PRESSED :
|
||||
LIBINPUT_KEY_STATE_RELEASED);
|
||||
break;
|
||||
case KEY_TYPE_BUTTON:
|
||||
want_debounce = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (want_debounce)
|
||||
fallback_debounce_handle_state(dispatch, time);
|
||||
|
||||
hw_key_update_last_state(dispatch);
|
||||
}
|
||||
|
||||
dispatch->pending_event = EVDEV_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_interface_process(struct evdev_dispatch *evdev_dispatch,
|
||||
struct evdev_device *device,
|
||||
|
|
@ -1137,7 +876,6 @@ fallback_interface_process(struct evdev_dispatch *evdev_dispatch,
|
|||
uint64_t time)
|
||||
{
|
||||
struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch);
|
||||
enum evdev_event_type sent;
|
||||
|
||||
if (dispatch->ignore_events)
|
||||
return;
|
||||
|
|
@ -1156,20 +894,7 @@ fallback_interface_process(struct evdev_dispatch *evdev_dispatch,
|
|||
fallback_process_switch(dispatch, device, event, time);
|
||||
break;
|
||||
case EV_SYN:
|
||||
sent = fallback_flush_pending_event(dispatch, device, time);
|
||||
switch (sent) {
|
||||
case EVDEV_ABSOLUTE_TOUCH_DOWN:
|
||||
case EVDEV_ABSOLUTE_TOUCH_UP:
|
||||
case EVDEV_ABSOLUTE_MT_DOWN:
|
||||
case EVDEV_ABSOLUTE_MT_MOTION:
|
||||
case EVDEV_ABSOLUTE_MT_UP:
|
||||
touch_notify_frame(&device->base, time);
|
||||
break;
|
||||
case EVDEV_ABSOLUTE_MOTION:
|
||||
case EVDEV_RELATIVE_MOTION:
|
||||
case EVDEV_NONE:
|
||||
break;
|
||||
}
|
||||
fallback_handle_state(dispatch, device, time);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1261,6 +986,7 @@ fallback_return_to_neutral_state(struct fallback_dispatch *dispatch,
|
|||
release_touches(dispatch, device, time);
|
||||
release_pressed_keys(dispatch, device, time);
|
||||
memset(dispatch->hw_key_mask, 0, sizeof(dispatch->hw_key_mask));
|
||||
memset(dispatch->hw_key_mask, 0, sizeof(dispatch->last_hw_key_mask));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1348,6 +1074,8 @@ fallback_interface_destroy(struct evdev_dispatch *evdev_dispatch)
|
|||
|
||||
libinput_timer_cancel(&dispatch->debounce.timer);
|
||||
libinput_timer_destroy(&dispatch->debounce.timer);
|
||||
libinput_timer_cancel(&dispatch->debounce.timer_short);
|
||||
libinput_timer_destroy(&dispatch->debounce.timer_short);
|
||||
free(dispatch->mt.slots);
|
||||
free(dispatch);
|
||||
}
|
||||
|
|
@ -1721,7 +1449,6 @@ fallback_dispatch_create(struct libinput_device *libinput_device)
|
|||
{
|
||||
struct evdev_device *device = evdev_device(libinput_device);
|
||||
struct fallback_dispatch *dispatch;
|
||||
char timer_name[64];
|
||||
|
||||
dispatch = zalloc(sizeof *dispatch);
|
||||
dispatch->device = evdev_device(libinput_device);
|
||||
|
|
@ -1771,14 +1498,7 @@ fallback_dispatch_create(struct libinput_device *libinput_device)
|
|||
want_config);
|
||||
}
|
||||
|
||||
snprintf(timer_name,
|
||||
sizeof(timer_name),
|
||||
"%s debounce",
|
||||
evdev_device_get_sysname(device));
|
||||
libinput_timer_init(&dispatch->debounce.timer,
|
||||
evdev_libinput_context(device),
|
||||
timer_name,
|
||||
fallback_debounce_timeout,
|
||||
device);
|
||||
fallback_init_debounce(dispatch);
|
||||
|
||||
return &dispatch->base;
|
||||
}
|
||||
|
|
|
|||
222
src/evdev-fallback.h
Normal file
222
src/evdev-fallback.h
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* Copyright © 2010 Intel Corporation
|
||||
* Copyright © 2013 Jonas Ådahl
|
||||
* Copyright © 2013-2017 Red Hat, Inc.
|
||||
* Copyright © 2017 James Ye <jye836@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef EVDEV_FALLBACK_H
|
||||
#define EVDEV_FALLBACK_H
|
||||
|
||||
#include "evdev.h"
|
||||
|
||||
enum debounce_state {
|
||||
DEBOUNCE_STATE_IS_UP = 100,
|
||||
DEBOUNCE_STATE_IS_DOWN,
|
||||
DEBOUNCE_STATE_DOWN_WAITING,
|
||||
DEBOUNCE_STATE_RELEASE_PENDING,
|
||||
DEBOUNCE_STATE_RELEASE_DELAYED,
|
||||
DEBOUNCE_STATE_RELEASE_WAITING,
|
||||
DEBOUNCE_STATE_MAYBE_SPURIOUS,
|
||||
DEBOUNCE_STATE_RELEASED,
|
||||
DEBOUNCE_STATE_PRESS_PENDING,
|
||||
};
|
||||
|
||||
struct fallback_dispatch {
|
||||
struct evdev_dispatch base;
|
||||
struct evdev_device *device;
|
||||
|
||||
struct libinput_device_config_calibration calibration;
|
||||
|
||||
struct {
|
||||
bool is_enabled;
|
||||
int angle;
|
||||
struct matrix matrix;
|
||||
struct libinput_device_config_rotation config;
|
||||
} rotation;
|
||||
|
||||
struct {
|
||||
struct device_coords point;
|
||||
int32_t seat_slot;
|
||||
} abs;
|
||||
|
||||
struct {
|
||||
int slot;
|
||||
struct mt_slot *slots;
|
||||
size_t slots_len;
|
||||
bool want_hysteresis;
|
||||
struct device_coords hysteresis_margin;
|
||||
} mt;
|
||||
|
||||
struct device_coords rel;
|
||||
struct device_coords wheel;
|
||||
|
||||
struct {
|
||||
/* The struct for the tablet mode switch device itself */
|
||||
struct {
|
||||
int state;
|
||||
} sw;
|
||||
/* The struct for other devices listening to the tablet mode
|
||||
switch */
|
||||
struct {
|
||||
struct evdev_device *sw_device;
|
||||
struct libinput_event_listener listener;
|
||||
} other;
|
||||
} tablet_mode;
|
||||
|
||||
/* Bitmask of pressed keys used to ignore initial release events from
|
||||
* the kernel. */
|
||||
unsigned long hw_key_mask[NLONGS(KEY_CNT)];
|
||||
unsigned long last_hw_key_mask[NLONGS(KEY_CNT)];
|
||||
|
||||
enum evdev_event_type pending_event;
|
||||
|
||||
/* true if we're reading events (i.e. not suspended) but we're
|
||||
ignoring them */
|
||||
bool ignore_events;
|
||||
|
||||
struct {
|
||||
#if 0
|
||||
enum evdev_debounce_state state;
|
||||
uint64_t button_up_time;
|
||||
#endif
|
||||
unsigned int button_code;
|
||||
uint64_t button_time;
|
||||
struct libinput_timer timer;
|
||||
struct libinput_timer timer_short;
|
||||
enum debounce_state state;
|
||||
bool spurious_enabled;
|
||||
} debounce;
|
||||
|
||||
struct {
|
||||
enum switch_reliability reliability;
|
||||
|
||||
bool is_closed;
|
||||
bool is_closed_client_state;
|
||||
|
||||
/* We allow up to 3 paired keyboards for the lid switch
|
||||
* listener. Only one keyboard should exist, but that can
|
||||
* have more than one event node.
|
||||
*
|
||||
* Note: this is a sparse list, any element may have a
|
||||
* non-NULL device.
|
||||
*/
|
||||
struct paired_keyboard {
|
||||
struct evdev_device *device;
|
||||
struct libinput_event_listener listener;
|
||||
} paired_keyboard[3];
|
||||
} lid;
|
||||
};
|
||||
|
||||
static inline struct fallback_dispatch*
|
||||
fallback_dispatch(struct evdev_dispatch *dispatch)
|
||||
{
|
||||
evdev_verify_dispatch_type(dispatch, DISPATCH_FALLBACK);
|
||||
|
||||
return container_of(dispatch, struct fallback_dispatch, base);
|
||||
}
|
||||
|
||||
enum key_type {
|
||||
KEY_TYPE_NONE,
|
||||
KEY_TYPE_KEY,
|
||||
KEY_TYPE_BUTTON,
|
||||
};
|
||||
|
||||
static inline enum key_type
|
||||
get_key_type(uint16_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case BTN_TOOL_PEN:
|
||||
case BTN_TOOL_RUBBER:
|
||||
case BTN_TOOL_BRUSH:
|
||||
case BTN_TOOL_PENCIL:
|
||||
case BTN_TOOL_AIRBRUSH:
|
||||
case BTN_TOOL_MOUSE:
|
||||
case BTN_TOOL_LENS:
|
||||
case BTN_TOOL_QUINTTAP:
|
||||
case BTN_TOOL_DOUBLETAP:
|
||||
case BTN_TOOL_TRIPLETAP:
|
||||
case BTN_TOOL_QUADTAP:
|
||||
case BTN_TOOL_FINGER:
|
||||
case BTN_TOUCH:
|
||||
return KEY_TYPE_NONE;
|
||||
}
|
||||
|
||||
if (code >= KEY_ESC && code <= KEY_MICMUTE)
|
||||
return KEY_TYPE_KEY;
|
||||
if (code >= BTN_MISC && code <= BTN_GEAR_UP)
|
||||
return KEY_TYPE_BUTTON;
|
||||
if (code >= KEY_OK && code <= KEY_LIGHTS_TOGGLE)
|
||||
return KEY_TYPE_KEY;
|
||||
if (code >= BTN_DPAD_UP && code <= BTN_DPAD_RIGHT)
|
||||
return KEY_TYPE_BUTTON;
|
||||
if (code >= KEY_ALS_TOGGLE && code <= KEY_ONSCREEN_KEYBOARD)
|
||||
return KEY_TYPE_KEY;
|
||||
if (code >= BTN_TRIGGER_HAPPY && code <= BTN_TRIGGER_HAPPY40)
|
||||
return KEY_TYPE_BUTTON;
|
||||
return KEY_TYPE_NONE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hw_set_key_down(struct fallback_dispatch *dispatch, int code, int pressed)
|
||||
{
|
||||
long_set_bit_state(dispatch->hw_key_mask, code, pressed);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hw_key_has_changed(struct fallback_dispatch *dispatch, int code)
|
||||
{
|
||||
return long_bit_is_set(dispatch->hw_key_mask, code) !=
|
||||
long_bit_is_set(dispatch->last_hw_key_mask, code);
|
||||
}
|
||||
|
||||
static inline void
|
||||
hw_key_update_last_state(struct fallback_dispatch *dispatch)
|
||||
{
|
||||
static_assert(sizeof(dispatch->hw_key_mask) ==
|
||||
sizeof(dispatch->last_hw_key_mask),
|
||||
"Mismatching key mask size");
|
||||
|
||||
memcpy(dispatch->last_hw_key_mask,
|
||||
dispatch->hw_key_mask,
|
||||
sizeof(dispatch->hw_key_mask));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hw_is_key_down(struct fallback_dispatch *dispatch, int code)
|
||||
{
|
||||
return long_bit_is_set(dispatch->hw_key_mask, code);
|
||||
}
|
||||
|
||||
static inline int
|
||||
get_key_down_count(struct evdev_device *device, int code)
|
||||
{
|
||||
return device->key_count[code];
|
||||
}
|
||||
|
||||
void fallback_init_debounce(struct fallback_dispatch *dispatch);
|
||||
void fallback_debounce_handle_state(struct fallback_dispatch *dispatch,
|
||||
uint64_t time);
|
||||
|
||||
#endif
|
||||
24
src/evdev.h
24
src/evdev.h
|
|
@ -41,13 +41,14 @@
|
|||
|
||||
enum evdev_event_type {
|
||||
EVDEV_NONE,
|
||||
EVDEV_ABSOLUTE_TOUCH_DOWN,
|
||||
EVDEV_ABSOLUTE_MOTION,
|
||||
EVDEV_ABSOLUTE_TOUCH_UP,
|
||||
EVDEV_ABSOLUTE_MT_DOWN,
|
||||
EVDEV_ABSOLUTE_MT_MOTION,
|
||||
EVDEV_ABSOLUTE_MT_UP,
|
||||
EVDEV_RELATIVE_MOTION,
|
||||
EVDEV_ABSOLUTE_TOUCH_DOWN = (1 << 0),
|
||||
EVDEV_ABSOLUTE_MOTION = (1 << 1),
|
||||
EVDEV_ABSOLUTE_TOUCH_UP = (1 << 2),
|
||||
EVDEV_ABSOLUTE_MT= (1 << 3),
|
||||
EVDEV_WHEEL = (1 << 4),
|
||||
EVDEV_KEY = (1 << 5),
|
||||
EVDEV_RELATIVE_MOTION = (1 << 6),
|
||||
EVDEV_BUTTON = (1 << 7),
|
||||
};
|
||||
|
||||
enum evdev_device_seat_capability {
|
||||
|
|
@ -150,7 +151,16 @@ enum evdev_debounce_state {
|
|||
DEBOUNCE_ACTIVE,
|
||||
};
|
||||
|
||||
enum mt_slot_state {
|
||||
SLOT_STATE_NONE,
|
||||
SLOT_STATE_BEGIN,
|
||||
SLOT_STATE_UPDATE,
|
||||
SLOT_STATE_END,
|
||||
};
|
||||
|
||||
struct mt_slot {
|
||||
bool dirty;
|
||||
enum mt_slot_state state;
|
||||
int32_t seat_slot;
|
||||
struct device_coords point;
|
||||
struct device_coords hysteresis_center;
|
||||
|
|
|
|||
|
|
@ -2018,7 +2018,10 @@ litest_hover_move_two_touches(struct litest_device *d,
|
|||
}
|
||||
|
||||
void
|
||||
litest_button_click(struct litest_device *d, unsigned int button, bool is_press)
|
||||
litest_button_click_debounced(struct litest_device *d,
|
||||
struct libinput *li,
|
||||
unsigned int button,
|
||||
bool is_press)
|
||||
{
|
||||
|
||||
struct input_event *ev;
|
||||
|
|
@ -2029,7 +2032,9 @@ litest_button_click(struct litest_device *d, unsigned int button, bool is_press)
|
|||
|
||||
ARRAY_FOR_EACH(click, ev)
|
||||
litest_event(d, ev->type, ev->code, ev->value);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_debounce();
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2039,7 +2044,7 @@ litest_button_scroll(struct litest_device *dev,
|
|||
{
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_button_click(dev, button, 1);
|
||||
litest_button_click_debounced(dev, li, button, 1);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_buttonscroll();
|
||||
|
|
@ -2049,7 +2054,7 @@ litest_button_scroll(struct litest_device *dev,
|
|||
litest_event(dev, EV_REL, REL_Y, dy);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
litest_button_click(dev, button, 0);
|
||||
litest_button_click_debounced(dev, li, button, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
|
@ -2057,7 +2062,14 @@ litest_button_scroll(struct litest_device *dev,
|
|||
void
|
||||
litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press)
|
||||
{
|
||||
litest_button_click(d, key, is_press);
|
||||
struct input_event *ev;
|
||||
struct input_event click[] = {
|
||||
{ .type = EV_KEY, .code = key, .value = is_press ? 1 : 0 },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
};
|
||||
|
||||
ARRAY_FOR_EACH(click, ev)
|
||||
litest_event(d, ev->type, ev->code, ev->value);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -3170,7 +3182,7 @@ litest_timeout_tapndrag(void)
|
|||
void
|
||||
litest_timeout_debounce(void)
|
||||
{
|
||||
msleep(15);
|
||||
msleep(30);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -597,9 +597,10 @@ litest_hover_move_two_touches(struct litest_device *d,
|
|||
int steps, int sleep_ms);
|
||||
|
||||
void
|
||||
litest_button_click(struct litest_device *d,
|
||||
unsigned int button,
|
||||
bool is_press);
|
||||
litest_button_click_debounced(struct litest_device *d,
|
||||
struct libinput *li,
|
||||
unsigned int button,
|
||||
bool is_press);
|
||||
|
||||
void
|
||||
litest_button_scroll(struct litest_device *d,
|
||||
|
|
|
|||
|
|
@ -463,7 +463,7 @@ START_TEST(device_disable_release_buttons)
|
|||
|
||||
device = dev->libinput_device;
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_drain_events(li);
|
||||
|
||||
status = libinput_device_config_send_events_set_mode(device,
|
||||
|
|
@ -497,7 +497,7 @@ START_TEST(device_disable_release_keys)
|
|||
|
||||
device = dev->libinput_device;
|
||||
|
||||
litest_button_click(dev, KEY_A, true);
|
||||
litest_button_click_debounced(dev, li, KEY_A, true);
|
||||
litest_drain_events(li);
|
||||
|
||||
status = libinput_device_config_send_events_set_mode(device,
|
||||
|
|
@ -616,7 +616,7 @@ START_TEST(device_disable_release_softbutton)
|
|||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 90, 90);
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
|
||||
/* make sure softbutton works */
|
||||
litest_assert_button_event(li,
|
||||
|
|
@ -633,7 +633,7 @@ START_TEST(device_disable_release_softbutton)
|
|||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
|
@ -669,8 +669,8 @@ START_TEST(device_disable_topsoftbutton)
|
|||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 90, 10);
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_wait_for_event(li);
|
||||
|
|
|
|||
|
|
@ -416,8 +416,8 @@ START_TEST(event_conversion_tablet)
|
|||
|
||||
litest_tablet_proximity_in(dev, 50, 50, axes);
|
||||
litest_tablet_motion(dev, 60, 50, axes);
|
||||
litest_button_click(dev, BTN_STYLUS, true);
|
||||
litest_button_click(dev, BTN_STYLUS, false);
|
||||
litest_button_click_debounced(dev, li, BTN_STYLUS, true);
|
||||
litest_button_click_debounced(dev, li, BTN_STYLUS, false);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
|
|
@ -458,7 +458,7 @@ START_TEST(event_conversion_tablet_pad)
|
|||
struct libinput_event *event;
|
||||
int events = 0;
|
||||
|
||||
litest_button_click(dev, BTN_0, true);
|
||||
litest_button_click_debounced(dev, li, BTN_0, true);
|
||||
litest_pad_ring_start(dev, 10);
|
||||
litest_pad_ring_end(dev);
|
||||
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ START_TEST(pad_time)
|
|||
if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
|
||||
continue;
|
||||
|
||||
litest_button_click(dev, code, 1);
|
||||
litest_button_click(dev, code, 0);
|
||||
litest_button_click_debounced(dev, li, code, 1);
|
||||
litest_button_click_debounced(dev, li, code, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
switch (code) {
|
||||
|
|
@ -98,8 +98,8 @@ START_TEST(pad_time)
|
|||
litest_drain_events(li);
|
||||
msleep(10);
|
||||
|
||||
litest_button_click(dev, code, 1);
|
||||
litest_button_click(dev, code, 0);
|
||||
litest_button_click_debounced(dev, li, code, 1);
|
||||
litest_button_click_debounced(dev, li, code, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
ev = libinput_get_event(li);
|
||||
|
|
@ -156,8 +156,8 @@ START_TEST(pad_button)
|
|||
if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
|
||||
continue;
|
||||
|
||||
litest_button_click(dev, code, 1);
|
||||
litest_button_click(dev, code, 0);
|
||||
litest_button_click_debounced(dev, li, code, 1);
|
||||
litest_button_click_debounced(dev, li, code, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
switch (code) {
|
||||
|
|
@ -207,8 +207,8 @@ START_TEST(pad_button_mode_groups)
|
|||
if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
|
||||
continue;
|
||||
|
||||
litest_button_click(dev, code, 1);
|
||||
litest_button_click(dev, code, 0);
|
||||
litest_button_click_debounced(dev, li, code, 1);
|
||||
litest_button_click_debounced(dev, li, code, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
switch (code) {
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@ test_button_event(struct litest_device *dev, unsigned int button, int state)
|
|||
{
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_button_click(dev, button, state);
|
||||
litest_button_click_debounced(dev, li, button, state);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
litest_assert_button_event(li, button,
|
||||
|
|
@ -500,7 +500,7 @@ START_TEST(pointer_recover_from_lost_button_count)
|
|||
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
|
|
@ -508,15 +508,15 @@ START_TEST(pointer_recover_from_lost_button_count)
|
|||
|
||||
/* Grab for the release to make libinput lose count */
|
||||
libevdev_grab(evdev, LIBEVDEV_GRAB);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
libevdev_grab(evdev, LIBEVDEV_UNGRAB);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
|
@ -802,7 +802,10 @@ START_TEST(pointer_seat_button_count)
|
|||
}
|
||||
|
||||
for (i = 0; i < num_devices; ++i)
|
||||
litest_button_click(devices[i], BTN_LEFT, true);
|
||||
litest_button_click_debounced(devices[i],
|
||||
libinput,
|
||||
BTN_LEFT,
|
||||
true);
|
||||
|
||||
libinput_dispatch(libinput);
|
||||
while ((ev = libinput_get_event(libinput))) {
|
||||
|
|
@ -832,7 +835,10 @@ START_TEST(pointer_seat_button_count)
|
|||
ck_assert_int_eq(seat_button_count, num_devices);
|
||||
|
||||
for (i = 0; i < num_devices; ++i)
|
||||
litest_button_click(devices[i], BTN_LEFT, false);
|
||||
litest_button_click_debounced(devices[i],
|
||||
libinput,
|
||||
BTN_LEFT,
|
||||
false);
|
||||
|
||||
libinput_dispatch(libinput);
|
||||
while ((ev = libinput_get_event(libinput))) {
|
||||
|
|
@ -921,8 +927,8 @@ START_TEST(pointer_left_handed)
|
|||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
|
|
@ -931,8 +937,8 @@ START_TEST(pointer_left_handed)
|
|||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_button_click(dev, BTN_RIGHT, 1);
|
||||
litest_button_click(dev, BTN_RIGHT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, 0);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
|
@ -941,8 +947,8 @@ START_TEST(pointer_left_handed)
|
|||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
if (libinput_device_pointer_has_button(d, BTN_MIDDLE)) {
|
||||
litest_button_click(dev, BTN_MIDDLE, 1);
|
||||
litest_button_click(dev, BTN_MIDDLE, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_MIDDLE, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_MIDDLE, 0);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
|
@ -961,14 +967,14 @@ START_TEST(pointer_left_handed_during_click)
|
|||
enum libinput_config_status status;
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
/* Change while button is down, expect correct release event */
|
||||
status = libinput_device_config_left_handed_set(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
|
|
@ -992,16 +998,16 @@ START_TEST(pointer_left_handed_during_click_multiple_buttons)
|
|||
litest_disable_middleemu(dev);
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_left_handed_set(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
/* No left-handed until all buttons were down */
|
||||
litest_button_click(dev, BTN_RIGHT, 1);
|
||||
litest_button_click(dev, BTN_RIGHT, 0);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
|
|
@ -1102,7 +1108,7 @@ START_TEST(pointer_scroll_button_no_event_before_timeout)
|
|||
BTN_LEFT);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_button_click(device, BTN_LEFT, true);
|
||||
litest_button_click_debounced(device, li, BTN_LEFT, true);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
|
|
@ -1113,7 +1119,7 @@ START_TEST(pointer_scroll_button_no_event_before_timeout)
|
|||
|
||||
litest_timeout_buttonscroll();
|
||||
libinput_dispatch(li);
|
||||
litest_button_click(device, BTN_LEFT, false);
|
||||
litest_button_click_debounced(device, li, BTN_LEFT, false);
|
||||
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
|
@ -1146,8 +1152,8 @@ START_TEST(pointer_scroll_button_middle_emulation)
|
|||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click(dev, BTN_RIGHT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, 1);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_buttonscroll();
|
||||
libinput_dispatch(li);
|
||||
|
|
@ -1159,8 +1165,8 @@ START_TEST(pointer_scroll_button_middle_emulation)
|
|||
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click(dev, BTN_RIGHT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -1);
|
||||
|
|
@ -1525,16 +1531,16 @@ START_TEST(middlebutton)
|
|||
litest_drain_events(li);
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(btn); i++) {
|
||||
litest_button_click(device, btn[i][0], true);
|
||||
litest_button_click(device, btn[i][1], true);
|
||||
litest_button_click_debounced(device, li, btn[i][0], true);
|
||||
litest_button_click_debounced(device, li, btn[i][1], true);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(device, btn[i][2], false);
|
||||
litest_button_click(device, btn[i][3], false);
|
||||
litest_button_click_debounced(device, li, btn[i][2], false);
|
||||
litest_button_click_debounced(device, li, btn[i][3], false);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
|
@ -1568,33 +1574,33 @@ START_TEST(middlebutton_nostart_while_down)
|
|||
if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED)
|
||||
return;
|
||||
|
||||
litest_button_click(device, BTN_MIDDLE, true);
|
||||
litest_button_click_debounced(device, li, BTN_MIDDLE, true);
|
||||
litest_drain_events(li);
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(btn); i++) {
|
||||
litest_button_click(device, btn[i][0], true);
|
||||
litest_button_click_debounced(device, li, btn[i][0], true);
|
||||
litest_assert_button_event(li,
|
||||
btn[i][0],
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_button_click(device, btn[i][1], true);
|
||||
litest_button_click_debounced(device, li, btn[i][1], true);
|
||||
litest_assert_button_event(li,
|
||||
btn[i][1],
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(device, btn[i][2], false);
|
||||
litest_button_click_debounced(device, li, btn[i][2], false);
|
||||
litest_assert_button_event(li,
|
||||
btn[i][2],
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_button_click(device, btn[i][3], false);
|
||||
litest_button_click_debounced(device, li, btn[i][3], false);
|
||||
litest_assert_button_event(li,
|
||||
btn[i][3],
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
|
||||
litest_button_click(device, BTN_MIDDLE, false);
|
||||
litest_button_click_debounced(device, li, BTN_MIDDLE, false);
|
||||
litest_drain_events(li);
|
||||
}
|
||||
END_TEST
|
||||
|
|
@ -1616,7 +1622,7 @@ START_TEST(middlebutton_timeout)
|
|||
|
||||
for (button = BTN_LEFT; button <= BTN_RIGHT; button++) {
|
||||
litest_drain_events(li);
|
||||
litest_button_click(device, button, true);
|
||||
litest_button_click_debounced(device, li, button, true);
|
||||
litest_assert_empty_queue(li);
|
||||
litest_timeout_middlebutton();
|
||||
|
||||
|
|
@ -1624,7 +1630,7 @@ START_TEST(middlebutton_timeout)
|
|||
button,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_button_click(device, button, false);
|
||||
litest_button_click_debounced(device, li, button, false);
|
||||
litest_assert_button_event(li,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
|
@ -1657,22 +1663,22 @@ START_TEST(middlebutton_doubleclick)
|
|||
litest_drain_events(li);
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(btn); i++) {
|
||||
litest_button_click(device, btn[i][0], true);
|
||||
litest_button_click(device, btn[i][1], true);
|
||||
litest_button_click_debounced(device, li, btn[i][0], true);
|
||||
litest_button_click_debounced(device, li, btn[i][1], true);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(device, btn[i][2], false);
|
||||
litest_button_click(device, btn[i][2], true);
|
||||
litest_button_click_debounced(device, li, btn[i][2], false);
|
||||
litest_button_click_debounced(device, li, btn[i][2], true);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_button_click(device, btn[i][3], false);
|
||||
litest_button_click_debounced(device, li, btn[i][3], false);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
|
|
@ -1705,8 +1711,8 @@ START_TEST(middlebutton_middleclick)
|
|||
for (button = BTN_LEFT; button <= BTN_RIGHT; button++) {
|
||||
/* release button before middle */
|
||||
litest_drain_events(li);
|
||||
litest_button_click(device, button, true);
|
||||
litest_button_click(device, BTN_MIDDLE, true);
|
||||
litest_button_click_debounced(device, li, button, true);
|
||||
litest_button_click_debounced(device, li, BTN_MIDDLE, true);
|
||||
litest_assert_button_event(li,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
|
@ -1714,19 +1720,19 @@ START_TEST(middlebutton_middleclick)
|
|||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_empty_queue(li);
|
||||
litest_button_click(device, button, false);
|
||||
litest_button_click_debounced(device, li, button, false);
|
||||
litest_assert_button_event(li,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_button_click(device, BTN_MIDDLE, false);
|
||||
litest_button_click_debounced(device, li, BTN_MIDDLE, false);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* release middle before button */
|
||||
litest_button_click(device, button, true);
|
||||
litest_button_click(device, BTN_MIDDLE, true);
|
||||
litest_button_click_debounced(device, li, button, true);
|
||||
litest_button_click_debounced(device, li, BTN_MIDDLE, true);
|
||||
litest_assert_button_event(li,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
|
@ -1734,11 +1740,11 @@ START_TEST(middlebutton_middleclick)
|
|||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_empty_queue(li);
|
||||
litest_button_click(device, BTN_MIDDLE, false);
|
||||
litest_button_click_debounced(device, li, BTN_MIDDLE, false);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_button_click(device, button, false);
|
||||
litest_button_click_debounced(device, li, button, false);
|
||||
litest_assert_button_event(li,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
|
@ -1770,14 +1776,14 @@ START_TEST(middlebutton_middleclick_during)
|
|||
|
||||
/* trigger emulation, then real middle */
|
||||
for (button = BTN_LEFT; button <= BTN_RIGHT; button++) {
|
||||
litest_button_click(device, BTN_LEFT, true);
|
||||
litest_button_click(device, BTN_RIGHT, true);
|
||||
litest_button_click_debounced(device, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(device, li, BTN_RIGHT, true);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_button_click(device, BTN_MIDDLE, true);
|
||||
litest_button_click_debounced(device, li, BTN_MIDDLE, true);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
|
@ -1788,23 +1794,23 @@ START_TEST(middlebutton_middleclick_during)
|
|||
litest_assert_empty_queue(li);
|
||||
|
||||
/* middle still down, release left/right */
|
||||
litest_button_click(device, button, false);
|
||||
litest_button_click_debounced(device, li, button, false);
|
||||
litest_assert_empty_queue(li);
|
||||
litest_button_click(device, button, true);
|
||||
litest_button_click_debounced(device, li, button, true);
|
||||
litest_assert_button_event(li,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* release both */
|
||||
litest_button_click(device, BTN_LEFT, false);
|
||||
litest_button_click(device, BTN_RIGHT, false);
|
||||
litest_button_click_debounced(device, li, BTN_LEFT, false);
|
||||
litest_button_click_debounced(device, li, BTN_RIGHT, false);
|
||||
litest_assert_button_event(li,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(device, BTN_MIDDLE, false);
|
||||
litest_button_click_debounced(device, li, BTN_MIDDLE, false);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
|
@ -2104,92 +2110,176 @@ START_TEST(pointer_time_usec)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(debounce)
|
||||
START_TEST(debounce_bounce)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
unsigned int button = _i; /* ranged test */
|
||||
|
||||
if (!libinput_device_pointer_has_button(dev->libinput_device,
|
||||
button))
|
||||
return;
|
||||
|
||||
litest_disable_middleemu(dev);
|
||||
disable_button_scrolling(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_KEY, button, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_KEY, button, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
/* expect debouncing on now, this event is ignored */
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_KEY, button, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_debounce();
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_event(dev, EV_KEY, button, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, button, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, button, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_debounce();
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(debounce_timer)
|
||||
START_TEST(debounce_bounce_check_immediate)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_disable_middleemu(dev);
|
||||
disable_button_scrolling(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* Press must be sent without delay */
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_timeout_debounce();
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* expect debouncing on now, this event is ignored */
|
||||
/* held down & past timeout, we expect releases to be immediate */
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_timeout_debounce();
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Triggers the event sequence that initializes the spurious
|
||||
* debouncing behavior */
|
||||
static inline void
|
||||
debounce_trigger_spurious(struct litest_device *dev, struct libinput *li)
|
||||
{
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_debounce();
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_timeout_debounce();
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
/* gets filtered now */
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_debounce();
|
||||
libinput_dispatch(li);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
|
||||
START_TEST(debounce_spurious)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
unsigned int button = _i; /* ranged test */
|
||||
|
||||
if (!libinput_device_pointer_has_button(dev->libinput_device,
|
||||
button))
|
||||
return;
|
||||
|
||||
litest_disable_middleemu(dev);
|
||||
disable_button_scrolling(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
debounce_trigger_spurious(dev, li);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_KEY, button, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_debounce();
|
||||
libinput_dispatch(li);
|
||||
|
||||
/* Not all devices can disable middle button emulation, time out on
|
||||
* middle button here to make sure the initial button press event
|
||||
* was flushed.
|
||||
*/
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_middlebutton();
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
/* bouncy bouncy bouncy */
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_KEY, button, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_KEY, button, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_KEY, button, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_debounce();
|
||||
libinput_dispatch(li);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
button,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
|
@ -2197,7 +2287,7 @@ START_TEST(debounce_timer)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(debounce_multibounce)
|
||||
START_TEST(debounce_spurious_multibounce)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
|
@ -2205,15 +2295,7 @@ START_TEST(debounce_multibounce)
|
|||
litest_disable_middleemu(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* enable debouncing */
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
debounce_trigger_spurious(dev, li);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* Let's assume our button has ventricular fibrilation and sends a
|
||||
|
|
@ -2224,6 +2306,8 @@ START_TEST(debounce_multibounce)
|
|||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_debounce();
|
||||
|
||||
/* Not all devices can disable middle button emulation, time out on
|
||||
* middle button here to make sure the initial button press event
|
||||
|
|
@ -2262,20 +2346,34 @@ START_TEST(debounce_multibounce)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(debounce_no_debounce_for_otherbutton)
|
||||
START_TEST(debounce_spurious_dont_enable_on_otherbutton)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
if (!libinput_device_config_middle_emulation_is_available(device))
|
||||
return;
|
||||
|
||||
litest_disable_middleemu(dev);
|
||||
disable_button_scrolling(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* Don't trigger spurious debouncing on otherbutton events */
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_debounce();
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_RIGHT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_RIGHT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
|
|
@ -2291,43 +2389,68 @@ START_TEST(debounce_no_debounce_for_otherbutton)
|
|||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* Expect release to be immediate */
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_debounce();
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(debounce_cancel_debounce_otherbutton)
|
||||
START_TEST(debounce_spurious_cancel_debounce_otherbutton)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
if (!libinput_device_config_middle_emulation_is_available(device))
|
||||
return;
|
||||
|
||||
litest_disable_middleemu(dev);
|
||||
disable_button_scrolling(dev);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
litest_drain_events(li);
|
||||
debounce_trigger_spurious(dev, li);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_debounce();
|
||||
libinput_dispatch(li);
|
||||
|
||||
/* spurious debouncing is on but the release should get flushed by
|
||||
* the other button */
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
/* release is now held back, press was ignored,
|
||||
* other button should flush the release */
|
||||
litest_event(dev, EV_KEY, BTN_RIGHT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_RIGHT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
|
|
@ -2343,6 +2466,12 @@ START_TEST(debounce_cancel_debounce_otherbutton)
|
|||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
|
@ -2351,31 +2480,28 @@ START_TEST(debounce_cancel_debounce_otherbutton)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(debounce_switch_to_otherbutton)
|
||||
START_TEST(debounce_spurious_switch_to_otherbutton)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
if (!libinput_device_config_middle_emulation_is_available(device))
|
||||
return;
|
||||
|
||||
litest_drain_events(li);
|
||||
debounce_trigger_spurious(dev, li);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_debounce();
|
||||
libinput_dispatch(li);
|
||||
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
/* release is now held back, press was ignored,
|
||||
/* release is now held back,
|
||||
* other button should flush the release */
|
||||
litest_event(dev, EV_KEY, BTN_RIGHT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
|
@ -2413,6 +2539,7 @@ litest_setup_tests_pointer(void)
|
|||
{
|
||||
struct range axis_range = {ABS_X, ABS_Y + 1};
|
||||
struct range compass = {0, 7}; /* cardinal directions */
|
||||
struct range buttons = {BTN_LEFT, BTN_TASK + 1};
|
||||
|
||||
litest_add("pointer:motion", pointer_motion_relative, LITEST_RELATIVE, LITEST_POINTINGSTICK);
|
||||
litest_add_for_device("pointer:motion", pointer_motion_relative_zero, LITEST_MOUSE);
|
||||
|
|
@ -2475,10 +2602,11 @@ litest_setup_tests_pointer(void)
|
|||
|
||||
litest_add("pointer:time", pointer_time_usec, LITEST_RELATIVE, LITEST_ANY);
|
||||
|
||||
litest_add("pointer:debounce", debounce, LITEST_BUTTON, LITEST_TOUCHPAD);
|
||||
litest_add("pointer:debounce", debounce_timer, LITEST_BUTTON, LITEST_TOUCHPAD);
|
||||
litest_add("pointer:debounce", debounce_multibounce, LITEST_BUTTON, LITEST_TOUCHPAD);
|
||||
litest_add("pointer:debounce_otherbutton", debounce_no_debounce_for_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD);
|
||||
litest_add("pointer:debounce_otherbutton", debounce_cancel_debounce_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD);
|
||||
litest_add("pointer:debounce_otherbutton", debounce_switch_to_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD);
|
||||
litest_add_ranged("pointer:debounce", debounce_bounce, LITEST_BUTTON, LITEST_TOUCHPAD, &buttons);
|
||||
litest_add("pointer:debounce", debounce_bounce_check_immediate, LITEST_BUTTON, LITEST_TOUCHPAD);
|
||||
litest_add_ranged("pointer:debounce", debounce_spurious, LITEST_BUTTON, LITEST_TOUCHPAD, &buttons);
|
||||
litest_add("pointer:debounce", debounce_spurious_multibounce, LITEST_BUTTON, LITEST_TOUCHPAD);
|
||||
litest_add("pointer:debounce_otherbutton", debounce_spurious_dont_enable_on_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD);
|
||||
litest_add("pointer:debounce_otherbutton", debounce_spurious_cancel_debounce_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD);
|
||||
litest_add("pointer:debounce_otherbutton", debounce_spurious_switch_to_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1041,7 +1041,7 @@ START_TEST(clickpad_finger_pin)
|
|||
litest_touch_move_to(dev, 0, 48, 48, 50, 50, 10, 1);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_move_to(dev, 0, 50, 50, 50 + dist, 50 + dist, 10, 1);
|
||||
|
|
@ -1050,7 +1050,7 @@ START_TEST(clickpad_finger_pin)
|
|||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
|
||||
|
||||
/* still pinned after release */
|
||||
|
|
@ -1490,7 +1490,7 @@ START_TEST(clickpad_softbutton_hover_into_buttons)
|
|||
|
||||
litest_touch_move_to(dev, 0, 90, 90, 91, 91, 1, 0);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
|
|
@ -1498,7 +1498,7 @@ START_TEST(clickpad_softbutton_hover_into_buttons)
|
|||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
|
|
|
|||
|
|
@ -332,8 +332,8 @@ START_TEST(touchpad_1fg_multitap_n_drag_click)
|
|||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
libinput_dispatch(li);
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
libinput_dispatch(li);
|
||||
|
||||
for (ntaps = 0; ntaps <= range; ntaps++) {
|
||||
|
|
@ -627,8 +627,8 @@ START_TEST(touchpad_1fg_multitap_n_drag_tap_click)
|
|||
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_down(dev, 0, 70, 50);
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
|
|
@ -799,8 +799,8 @@ START_TEST(touchpad_1fg_tap_n_drag_draglock_tap_click)
|
|||
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
|
|
|
|||
|
|
@ -842,7 +842,7 @@ START_TEST(touchpad_edge_scroll_buttonareas_click_stops_scroll)
|
|||
litest_touch_move_to(dev, 0, 20, 95, 70, 95, 10, 5);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
|
|
@ -865,7 +865,7 @@ START_TEST(touchpad_edge_scroll_buttonareas_click_stops_scroll)
|
|||
litest_touch_move_to(dev, 0, 70, 95, 90, 95, 10, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
|
||||
|
||||
|
|
@ -892,7 +892,7 @@ START_TEST(touchpad_edge_scroll_clickfinger_click_stops_scroll)
|
|||
litest_touch_move_to(dev, 0, 20, 95, 70, 95, 10, 5);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
|
|
@ -916,7 +916,7 @@ START_TEST(touchpad_edge_scroll_clickfinger_click_stops_scroll)
|
|||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
|
||||
|
||||
|
|
@ -1717,8 +1717,8 @@ START_TEST(touchpad_left_handed)
|
|||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
|
|
@ -1727,8 +1727,8 @@ START_TEST(touchpad_left_handed)
|
|||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_button_click(dev, BTN_RIGHT, 1);
|
||||
litest_button_click(dev, BTN_RIGHT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, 0);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
|
@ -1739,8 +1739,8 @@ START_TEST(touchpad_left_handed)
|
|||
if (libevdev_has_event_code(dev->evdev,
|
||||
EV_KEY,
|
||||
BTN_MIDDLE)) {
|
||||
litest_button_click(dev, BTN_MIDDLE, 1);
|
||||
litest_button_click(dev, BTN_MIDDLE, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_MIDDLE, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_MIDDLE, 0);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
|
@ -1779,8 +1779,8 @@ START_TEST(touchpad_left_handed_clickpad)
|
|||
|
||||
litest_drain_events(li);
|
||||
litest_touch_down(dev, 0, 10, 90);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
|
|
@ -1792,8 +1792,8 @@ START_TEST(touchpad_left_handed_clickpad)
|
|||
|
||||
litest_drain_events(li);
|
||||
litest_touch_down(dev, 0, 90, 90);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
|
|
@ -1805,8 +1805,8 @@ START_TEST(touchpad_left_handed_clickpad)
|
|||
|
||||
litest_drain_events(li);
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
|
|
@ -1833,8 +1833,8 @@ START_TEST(touchpad_left_handed_clickfinger)
|
|||
|
||||
litest_drain_events(li);
|
||||
litest_touch_down(dev, 0, 10, 90);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
/* Clickfinger is unaffected by left-handed setting */
|
||||
|
|
@ -1848,8 +1848,8 @@ START_TEST(touchpad_left_handed_clickfinger)
|
|||
litest_drain_events(li);
|
||||
litest_touch_down(dev, 0, 10, 90);
|
||||
litest_touch_down(dev, 1, 30, 90);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
|
||||
|
|
@ -1943,13 +1943,13 @@ START_TEST(touchpad_left_handed_delayed)
|
|||
return;
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_left_handed_set(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
|
|
@ -1959,18 +1959,18 @@ START_TEST(touchpad_left_handed_delayed)
|
|||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
/* left-handed takes effect now */
|
||||
litest_button_click(dev, BTN_RIGHT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, 1);
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_middlebutton();
|
||||
libinput_dispatch(li);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_left_handed_set(d, 0);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_button_click(dev, BTN_RIGHT, 0);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_RIGHT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
|
|
@ -1999,13 +1999,13 @@ START_TEST(touchpad_left_handed_clickpad_delayed)
|
|||
|
||||
litest_drain_events(li);
|
||||
litest_touch_down(dev, 0, 10, 90);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_left_handed_set(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
|
|
@ -2018,13 +2018,13 @@ START_TEST(touchpad_left_handed_clickpad_delayed)
|
|||
/* left-handed takes effect now */
|
||||
litest_drain_events(li);
|
||||
litest_touch_down(dev, 0, 90, 90);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_left_handed_set(d, 0);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
|
|
@ -2657,12 +2657,12 @@ START_TEST(touchpad_trackpoint_buttons)
|
|||
litest_drain_events(li);
|
||||
|
||||
ARRAY_FOR_EACH(buttons, b) {
|
||||
litest_button_click(touchpad, b->device_value, true);
|
||||
litest_button_click_debounced(touchpad, li, b->device_value, true);
|
||||
assert_btnevent_from_device(trackpoint,
|
||||
b->real_value,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
litest_button_click(touchpad, b->device_value, false);
|
||||
litest_button_click_debounced(touchpad, li, b->device_value, false);
|
||||
|
||||
assert_btnevent_from_device(trackpoint,
|
||||
b->real_value,
|
||||
|
|
@ -2683,7 +2683,7 @@ START_TEST(touchpad_trackpoint_mb_scroll)
|
|||
LITEST_TRACKPOINT);
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_button_click(touchpad, BTN_2, true); /* middle */
|
||||
litest_button_click_debounced(touchpad, li, BTN_2, true); /* middle */
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_buttonscroll();
|
||||
libinput_dispatch(li);
|
||||
|
|
@ -2695,7 +2695,7 @@ START_TEST(touchpad_trackpoint_mb_scroll)
|
|||
litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(trackpoint, EV_REL, REL_Y, -2);
|
||||
litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
|
||||
litest_button_click(touchpad, BTN_2, false);
|
||||
litest_button_click_debounced(touchpad, li, BTN_2, false);
|
||||
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
|
||||
|
||||
|
|
@ -2718,8 +2718,8 @@ START_TEST(touchpad_trackpoint_mb_click)
|
|||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_button_click(touchpad, BTN_2, true); /* middle */
|
||||
litest_button_click(touchpad, BTN_2, false);
|
||||
litest_button_click_debounced(touchpad, li, BTN_2, true); /* middle */
|
||||
litest_button_click_debounced(touchpad, li, BTN_2, false);
|
||||
|
||||
assert_btnevent_from_device(trackpoint,
|
||||
BTN_MIDDLE,
|
||||
|
|
@ -2743,11 +2743,11 @@ START_TEST(touchpad_trackpoint_buttons_softbuttons)
|
|||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(touchpad, 0, 95, 90);
|
||||
litest_button_click(touchpad, BTN_LEFT, true);
|
||||
litest_button_click(touchpad, BTN_1, true);
|
||||
litest_button_click(touchpad, BTN_LEFT, false);
|
||||
litest_button_click_debounced(touchpad, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(touchpad, li, BTN_1, true);
|
||||
litest_button_click_debounced(touchpad, li, BTN_LEFT, false);
|
||||
litest_touch_up(touchpad, 0);
|
||||
litest_button_click(touchpad, BTN_1, false);
|
||||
litest_button_click_debounced(touchpad, li, BTN_1, false);
|
||||
|
||||
assert_btnevent_from_device(touchpad,
|
||||
BTN_RIGHT,
|
||||
|
|
@ -2763,10 +2763,10 @@ START_TEST(touchpad_trackpoint_buttons_softbuttons)
|
|||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_touch_down(touchpad, 0, 95, 90);
|
||||
litest_button_click(touchpad, BTN_LEFT, true);
|
||||
litest_button_click(touchpad, BTN_1, true);
|
||||
litest_button_click(touchpad, BTN_1, false);
|
||||
litest_button_click(touchpad, BTN_LEFT, false);
|
||||
litest_button_click_debounced(touchpad, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(touchpad, li, BTN_1, true);
|
||||
litest_button_click_debounced(touchpad, li, BTN_1, false);
|
||||
litest_button_click_debounced(touchpad, li, BTN_LEFT, false);
|
||||
litest_touch_up(touchpad, 0);
|
||||
|
||||
assert_btnevent_from_device(touchpad,
|
||||
|
|
@ -2818,7 +2818,7 @@ START_TEST(touchpad_trackpoint_buttons_2fg_scroll)
|
|||
libinput_event_destroy(e);
|
||||
}
|
||||
|
||||
litest_button_click(touchpad, BTN_1, true);
|
||||
litest_button_click_debounced(touchpad, li, BTN_1, true);
|
||||
assert_btnevent_from_device(trackpoint,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
|
@ -2838,7 +2838,7 @@ START_TEST(touchpad_trackpoint_buttons_2fg_scroll)
|
|||
libinput_event_destroy(e);
|
||||
}
|
||||
|
||||
litest_button_click(touchpad, BTN_1, false);
|
||||
litest_button_click_debounced(touchpad, li, BTN_1, false);
|
||||
assert_btnevent_from_device(trackpoint,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
|
@ -2874,16 +2874,16 @@ START_TEST(touchpad_trackpoint_no_trackpoint)
|
|||
struct libinput *li = touchpad->libinput;
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_button_click(touchpad, BTN_0, true); /* left */
|
||||
litest_button_click(touchpad, BTN_0, false);
|
||||
litest_button_click_debounced(touchpad, li, BTN_0, true); /* left */
|
||||
litest_button_click_debounced(touchpad, li, BTN_0, false);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(touchpad, BTN_1, true); /* right */
|
||||
litest_button_click(touchpad, BTN_1, false);
|
||||
litest_button_click_debounced(touchpad, li, BTN_1, true); /* right */
|
||||
litest_button_click_debounced(touchpad, li, BTN_1, false);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(touchpad, BTN_2, true); /* middle */
|
||||
litest_button_click(touchpad, BTN_2, false);
|
||||
litest_button_click_debounced(touchpad, li, BTN_2, true); /* middle */
|
||||
litest_button_click_debounced(touchpad, li, BTN_2, false);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
|
@ -3679,8 +3679,8 @@ START_TEST(touchpad_dwt_click)
|
|||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
|
||||
|
||||
litest_touch_down(touchpad, 0, 50, 50);
|
||||
litest_button_click(touchpad, BTN_LEFT, true);
|
||||
litest_button_click(touchpad, BTN_LEFT, false);
|
||||
litest_button_click_debounced(touchpad, li, BTN_LEFT, true);
|
||||
litest_button_click_debounced(touchpad, li, BTN_LEFT, false);
|
||||
libinput_dispatch(li);
|
||||
litest_touch_up(touchpad, 0);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
|
||||
|
|
@ -4492,7 +4492,7 @@ START_TEST(touchpad_thumb_clickfinger)
|
|||
litest_touch_down(dev, 0, 50, 99);
|
||||
litest_touch_down(dev, 1, 60, 99);
|
||||
litest_touch_move_extended(dev, 0, 55, 99, axes);
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
|
|
@ -4503,7 +4503,7 @@ START_TEST(touchpad_thumb_clickfinger)
|
|||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
|
||||
|
|
@ -4512,7 +4512,7 @@ START_TEST(touchpad_thumb_clickfinger)
|
|||
litest_touch_down(dev, 0, 50, 99);
|
||||
litest_touch_down(dev, 1, 60, 99);
|
||||
litest_touch_move_extended(dev, 1, 65, 99, axes);
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
|
|
@ -4547,7 +4547,7 @@ START_TEST(touchpad_thumb_btnarea)
|
|||
|
||||
litest_touch_down(dev, 0, 90, 99);
|
||||
litest_touch_move_extended(dev, 0, 95, 99, axes);
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||
|
||||
/* button areas work as usual with a thumb */
|
||||
|
||||
|
|
|
|||
|
|
@ -43,9 +43,9 @@ START_TEST(trackpoint_middlebutton)
|
|||
litest_drain_events(li);
|
||||
|
||||
/* A quick middle button click should get reported normally */
|
||||
litest_button_click(dev, BTN_MIDDLE, 1);
|
||||
litest_button_click_debounced(dev, li, BTN_MIDDLE, 1);
|
||||
msleep(2);
|
||||
litest_button_click(dev, BTN_MIDDLE, 0);
|
||||
litest_button_click_debounced(dev, li, BTN_MIDDLE, 0);
|
||||
|
||||
litest_wait_for_event(li);
|
||||
|
||||
|
|
@ -173,7 +173,7 @@ START_TEST(trackpoint_topsoftbuttons_left_handed_trackpoint)
|
|||
|
||||
litest_touch_down(touchpad, 0, 5, 5);
|
||||
libinput_dispatch(li);
|
||||
litest_button_click(touchpad, BTN_LEFT, true);
|
||||
litest_button_click_debounced(touchpad, li, BTN_LEFT, true);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
|
|
@ -184,7 +184,7 @@ START_TEST(trackpoint_topsoftbuttons_left_handed_trackpoint)
|
|||
ck_assert(device == trackpoint->libinput_device);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
litest_button_click(touchpad, BTN_LEFT, false);
|
||||
litest_button_click_debounced(touchpad, li, BTN_LEFT, false);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
litest_is_button_event(event,
|
||||
|
|
@ -216,7 +216,7 @@ START_TEST(trackpoint_topsoftbuttons_left_handed_touchpad)
|
|||
|
||||
litest_touch_down(touchpad, 0, 5, 5);
|
||||
libinput_dispatch(li);
|
||||
litest_button_click(touchpad, BTN_LEFT, true);
|
||||
litest_button_click_debounced(touchpad, li, BTN_LEFT, true);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
|
|
@ -225,7 +225,7 @@ START_TEST(trackpoint_topsoftbuttons_left_handed_touchpad)
|
|||
ck_assert(device == trackpoint->libinput_device);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
litest_button_click(touchpad, BTN_LEFT, false);
|
||||
litest_button_click_debounced(touchpad, li, BTN_LEFT, false);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
litest_is_button_event(event,
|
||||
|
|
@ -260,7 +260,7 @@ START_TEST(trackpoint_topsoftbuttons_left_handed_both)
|
|||
|
||||
litest_touch_down(touchpad, 0, 5, 5);
|
||||
libinput_dispatch(li);
|
||||
litest_button_click(touchpad, BTN_LEFT, true);
|
||||
litest_button_click_debounced(touchpad, li, BTN_LEFT, true);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
|
|
@ -271,7 +271,7 @@ START_TEST(trackpoint_topsoftbuttons_left_handed_both)
|
|||
ck_assert(device == trackpoint->libinput_device);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
litest_button_click(touchpad, BTN_LEFT, false);
|
||||
litest_button_click_debounced(touchpad, li, BTN_LEFT, false);
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
litest_is_button_event(event,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue