mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-03-24 21:50:41 +01:00
Compare commits
26 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05a2da818b | ||
|
|
6e8beeb280 | ||
|
|
e961c1ff5c | ||
|
|
c77b6b4c96 | ||
|
|
8c55bc060d | ||
|
|
52cdbc1299 | ||
|
|
fc78e88870 | ||
|
|
5d78484891 | ||
|
|
16b290a785 | ||
|
|
01ae8bd6a2 | ||
|
|
c24c2af560 | ||
|
|
bd1ad68630 | ||
|
|
56bcb2999e | ||
|
|
4ec04fa960 | ||
|
|
e35c202df7 | ||
|
|
1593d7da32 | ||
|
|
73c9ed2cd9 | ||
|
|
ed17f8b637 | ||
|
|
15e40a42e7 | ||
|
|
5c989940b6 | ||
|
|
edd83fe99e | ||
|
|
e7be909838 | ||
|
|
03cd377e00 | ||
|
|
89660005a8 | ||
|
|
5b862de70d | ||
|
|
a83085e4f9 |
38 changed files with 2573 additions and 831 deletions
|
|
@ -41,6 +41,12 @@ libinput_jobs:
|
||||||
name: Build - No docs
|
name: Build - No docs
|
||||||
environment:
|
environment:
|
||||||
MESON_PARAMS: -Ddocumentation=false
|
MESON_PARAMS: -Ddocumentation=false
|
||||||
|
build_dist: &build_dist
|
||||||
|
run:
|
||||||
|
<<: *build_and_test_default
|
||||||
|
name: Build - ninja dist
|
||||||
|
environment:
|
||||||
|
NINJA_ARGS: dist
|
||||||
ninja_scan_build: &ninja_scan_build
|
ninja_scan_build: &ninja_scan_build
|
||||||
run:
|
run:
|
||||||
<<: *build_and_test_default
|
<<: *build_and_test_default
|
||||||
|
|
@ -88,6 +94,7 @@ fedora_build_all: &fedora_build_all
|
||||||
- *build_no_debug_gui
|
- *build_no_debug_gui
|
||||||
- *build_no_tests
|
- *build_no_tests
|
||||||
- *build_no_docs
|
- *build_no_docs
|
||||||
|
- *build_dist
|
||||||
|
|
||||||
ubuntu_install: &ubuntu_install
|
ubuntu_install: &ubuntu_install
|
||||||
run:
|
run:
|
||||||
|
|
@ -112,6 +119,7 @@ ubuntu_build_all: &ubuntu_build_all
|
||||||
- *build_no_debug_gui
|
- *build_no_debug_gui
|
||||||
- *build_no_tests
|
- *build_no_tests
|
||||||
- *build_no_docs
|
- *build_no_docs
|
||||||
|
- *build_dist
|
||||||
|
|
||||||
scan_build_run: &scan_build_run
|
scan_build_run: &scan_build_run
|
||||||
<<: *default_settings
|
<<: *default_settings
|
||||||
|
|
|
||||||
714
doc/button-debouncing-state-machine.svg
Normal file
714
doc/button-debouncing-state-machine.svg
Normal file
|
|
@ -0,0 +1,714 @@
|
||||||
|
<?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.2" editor="www.draw.io" type="google"><diagram id="27c35eac-9917-780f-69cd-550de3271581" name="Page-1">7R1dc5u49tdk7t2HZBCf4tGJnd3OtEmmTqezTx0ZZJu7BDyA62R//RUfwkYShDo2Qknz0NoChHy+z5HOORfGzdPznwnarL/EPg4vdM1/vjCmF7oODOiQ//KRl3JE1yy7HFklgV/dtR+YB//ialCrRreBj9PGjVkch1mwaQ56cRRhL2uMoSSJd83blnHYfOsGrTA3MPdQyI9+D/xsXY5C3d6P/4WD1Zq+GdhueeUJ0ZurX5KukR/vDoaM2YVxk8RxVn56er7BYQ49CpfyuduWq/XCEhxlfR7QFwvPs13HcpcIe8i41MsZfqJwW/3YT/Mf3x6q1WYvFARJvI18nM8CLozr3TrI8HyDvPzqjmCdjK2zp7C6vAzC8CYO46R41vAtDH2TjKdZEv+DD65AfWHYNrlSrQInGX5u/WmgBhghNRw/4Sx5IbdUDxiUWioqu7Sq77s9yoBdja0P0GVWY6iiklU99R6Q5EMFy55wNTm4LrZZFkcXuh2S914vEvJplX/aJDhNOXgTQtnkH9f4Ga3IYw34isC/wUlAlo2T/UMP+6GTANhuAtjk4SsCr3UO8NocwLBPWLb6GifZOiYAQOFsP3q9J2GtCc7/4Sx7qaQO2mYxGdrP8DmON9V95TvzF3VDkKwr3iYe7ma5DCUrnHWRD4+JBIcoC342339SwDoc3U7vv9/9+D759Pjp7k8FxYLuNqnWMGSKBQA4+H6dfZ5N5rMfD7O7qZogBloTxJZAMgwIYoMDcUbEYLzNzi5kGejPJvb1qWBsmqzwtQaTvsA1PIBdB7o2hAa65AEcxVmwfOF1W5vOI3IMoxTzCCnIlNpYehMhFFtPz6vczrxahvHOW6Mku/JRhlowxqDk9nbqngolFiNZoMmjpGaNQ5zYZ8AJb2/8Kk5a7BCVMGIwTEJwJA8jbqeJEsXRmGwSp4dNUgrWAYwSFpICiU6clNwuGVpZEgczQ0FUyH9wIikCJbotHKRNlYiW0sUh1YppRwbR2hzR/rI2VMEHlGeGAEclYhVIWDHJyKBVOGJItjFWt65qIePzg9Ll2P4deB9Wk+ttVx7X15HUMdJqq7/fyfauJFrVeRWlavAXMBQKHFeiGUVDTO9L9ztMgF0QSBssAgE4gI1HCLS5L10ywNDEoD+7DDCs3qSqzEZFvds2AnVldO9UKKiuSoqRQapjtvfb+KrTSnVkQRJyTP8hI7hMuBCKQi9DhQsN3nGgO0Pqbr5ZjFnmygxumf2tMmVUHWuTAU2wCTGUrjN1lQS0+7qqM2VZZeb73MNkgoegPrIjg1jHbJi1RZU67TIoi1hVih5S06cLkvpQcVjbW5jIhJajuR42PLqxrgQgTQFJsr9HVhDW5G2pL5O/r2c/5g/fvn66/zZX0JSCtt0UngAKNreHsqWoRFaDVLUeql5WENbiT4S9g1gh0CBDrjJ1vdVtmI7quGgbfXSq/rcSb/HoJEnQy8ENmziIsvRg5od84ADHADRx7Doag6Vyyj3O6rUdh0bV9aMYtzKEDh/1rf0LVuqkawKls8scRqe6kxvn+vY0ssh1xySKVHI7etGwrHCwrZIJYgnCwZZpunAJoe+6rmZA683mcouY1hzzyrSBZcDyX5YbHIbMyzVWszD4eZsAt8ccIBKj45Wte/OtiRotODOZs8WONhyS+NhTutkmQbxNeeWAI7QIc1zd8hriyJ0A7AVpUGiUHrsBbvF3Gj1hMx6WZffcDgAsck4i3vjDGVE8YvZpI6NOu1WW6uD3v96v+WPrI9oioImxSpBwny0CW1bU1WnNJJtyIB5/dIs9BS83uuWM2U5pE2ZdVOrIcjQdlfYGnB4WnylLZzl8TFv53WubBrfG4JlDlfzJPqTqyAppQ141PXydzecKpzjb1GailGoKKHUw/QRVCoQ6PawoKEs/wf7HXxXafYFM9GAfTpAhV1WKeMIechXKinhClQ7AQkHEczRmKewIAAzr6Z/yfJXNnq+Syva8vfoBKxLYrCS2RXbDYCUJVDJxe4liWdEXV6UEJNgjQgBlOQuuSrEWKLBlLUezNd+DS3ux1FxonGkbDzLJCsBhPYvzbQm5Yy4L0XZ2ehQnPDlI8v4GzfKYzj5P/h4+eHuGkib1jjLNv6OHbmX4yq5K7kefTTP3re5Hi3xhUnUcWtljAPHCFx18wbzhRwgyayKH2IfBv/kGdIW36sQaudu6vrCmZASFwYrY7FOPYKEwv3PCDjwUTqoLT4HvF8f9QrTA4TXy/lkVtHDAKsvir4s1qrqz1Uou6vzTBvaFdNnKQ5faleHAZtCJFvl6I6YNszkrzU+mM8TLZYpPjWOg8UHB97vnarLMJChENliZHE0lC8vtETaoaEmC+gaaSpHXmufGeAYDaO+w8oBlj4nvVbJ8+vG9rMgr0FQKvdasNc7CeBoffC3sDZbrc/Mg4cEehsEmxa+7QijdlL0AlsFzjpNzRl4Nm90e5KN81mB8P+YzVm2F8rv5XlaYDwCVIqY1Z3UeYJEGSt4BUJ3tax+ZVsRyJLI9UMnMp7XDOtleXhFHoJSZ36vIoLziooJKuAXja5WbP7AAOOnZatiMpZgCAeAIBACbcnMaOCtlo4rKuIrDoTJoVueVVZytc7Js27w+s3OalojRrnRoNP4EGg5MrZlzIoeWSR6QWu9ZH7OGO6rgcxv0ByBwpTSc3kfDyRMWfCTrQwoLwGxRy6y7CfQxR7+OqxOtSwt/6UqZFnqP8Je0allA58NfH1JasB2tpOYlAn3MQbNjEhMrOpNB4YZSQTN9TBXheFj+dkRKpmcL/MtMFQPGmD2RY3LFKjqTQuFKeSJGD2BKlBa/PZEyvsYWS5SZCQFG3QPgmGP3QFoPAKBUEwAg6gIwmpP3QNAG4ENKC1cfUYE4IGgE8A5y0yxjTN6eqZKH0svbe3MJ0ONhqVIqFOgDTHn2m1IdFPpUhwTy4mzm75bYF/uavONIQAVU6CtB4KBPs4C3l4A8Hpgq+RU1P541d/J4WPI5SB/SFmbTTCU2eQRKNRbp1YzclNXxre6P+tHp2zCaRzalZmhYKpnOvTI0LFkdswDt8fDRexrqTEc4t28V47PYe0q1bKiFZDeJ69JInDeeRwM5/XXIyXOrLf4EMuX+NaDcP4vK5aQZyjB5+4R8rtqh35Qfp/ff73ipQUfIqvaT0cENHZik6fZpkxWFzSf0Lfma0+JLnBAkErDj5JJKp/ylKMpH7x//mn0l/19/e3y8v8vR9RMXnVk0gqX833CHXvKvmyT2iMdaTLXAy7i4SrR8fo+XbVEOpHL6K/JpTt9K17LJzQGNvr9cGsqvB9EqzG9YBPmx7f9uya+69eNd9Ee1ysN76GTk7fXL6dgT8tZBVC4niXPXurrBxz8Dbw+O7XIZeAH5jVcHwN20wnZOqC7reNkuIIKvRqZWLKxGp7ZAJcCK31xOUYLgPyn9ySUqXlpRUbyjIMEEl0fbC0ARrstnRNnBqsg0u7zLzk3BUdyiPRQVuCumutyWKzsEZYR3h0jsIMYDeDFCgy+k0CwPUknlQyVVDaVEjRFEkwFr/+2xECaXutai7GKiz3KtmNuBge/jiJP4J7HrmmrvUhfovfrIUaN6PzyL4vvtT5YgZwqgCRIjBzO3R90xhjsS2kOjVlQmQ6XaKrkuNTd2dmMfyq5razRzICrKtiqCwih1IxYW9kdnR52Ax4FmsMctAO9VQwGbn0L0cuDUFaLMPk1ShtrZ0/0FdKBl+brrQmjiV9rRjrpr4jAcXzz6q20T2ZQqmgt7qq6JHBq7i/eNG41mnyyqtyb+HIVG6AyMRpU2ewRbPeL8uCHUrXCPqaFua2ewNboy2r4EbG9LR3DQ8Wy1Ftl+32MuEyrsTT6Wrd2Wxb2vI2BcBdszHrMjX5M4zg6lbx6d/xL7OL/j/w==</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"/>
|
||||||
|
<path d="M 895.31 1495 L 848.83 1574.5" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
|
<path d="M 846.18 1579.03 L 846.69 1571.23 L 848.83 1574.5 L 852.73 1574.76 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>
|
||||||
|
<path d="M 843.3 1630 L 963.44 1874.29" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
|
<path d="M 965.75 1879 L 959.52 1874.26 L 963.44 1874.29 L 965.8 1871.17 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
|
<path d="M 816 1580 L 846 1580 L 861 1605 L 846 1630 L 816 1630 L 801 1605 Z" fill="#ea6b66" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||||
|
<g transform="translate(810.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>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 74 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
|
counteracted by "debouncing" the buttons, usually by ignoring erroneous
|
||||||
events.
|
events.
|
||||||
|
|
||||||
libinput has a built-in debouncing for hardware defects. This feature is
|
libinput provides two methods of debouncing buttons, referred to as the
|
||||||
available for all button-base devices but not active by default. When
|
"bounce" and "spurious" methods:
|
||||||
libinput detects a faulty button on a device, debouncing is enabled and a
|
|
||||||
warning is printed to the log. Subsequent button events are handled
|
- In the "bounce" method, libinput monitors hardware bouncing on button
|
||||||
correctly in that bouncing button events are ignored, a user should thus see
|
state changes, i.e. when a user clicks or releases a button. For example,
|
||||||
the expected behavior.
|
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
|
Note that libinput's debouncing intended to correct hardware damage or
|
||||||
substandard hardware. Debouncing is also used as an accessibility feature
|
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
|
filtered to only one key press. This feature must be implemented higher in
|
||||||
the stack, libinput is limited to hardware debouncing.
|
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"
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
14
doc/faqs.dox
14
doc/faqs.dox
|
|
@ -125,6 +125,20 @@ Changes performed by xinput do not persist across device hotplugs. xinput is
|
||||||
considered a debugging and testing tool only and should not be used for
|
considered a debugging and testing tool only and should not be used for
|
||||||
permanent configurations.
|
permanent configurations.
|
||||||
|
|
||||||
|
@section faq_configuration Can you add a configuration option for $FEATURE?
|
||||||
|
|
||||||
|
No. At least that's going to be the initial answer. Read <a
|
||||||
|
href="http://who-t.blogspot.com/2016/04/why-libinput-doesnt-have-lot-of-config.html">Why
|
||||||
|
libinput doesn't have a lot of configuration options</a> first.
|
||||||
|
Configuration options for most features are a signal that we are incapable
|
||||||
|
of handling it correctly. To get to that point, we want to be sure we're
|
||||||
|
truly incapable of doing so. libinput has several features that
|
||||||
|
are handled automatically (and correctly) that users wanted to have
|
||||||
|
configuration options for initially.
|
||||||
|
|
||||||
|
So the answer to this question will almost always be 'no'. A configuration
|
||||||
|
option is, in most cases, a cop-out.
|
||||||
|
|
||||||
@section faq_synclient Why don't synclient and syndaemon work with libinput?
|
@section faq_synclient Why don't synclient and syndaemon work with libinput?
|
||||||
|
|
||||||
Synclient and syndaemon rely on X input device properties that are specific
|
Synclient and syndaemon rely on X input device properties that are specific
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ EXTRACT_STATIC = YES
|
||||||
MAX_INITIALIZER_LINES = 0
|
MAX_INITIALIZER_LINES = 0
|
||||||
QUIET = YES
|
QUIET = YES
|
||||||
INPUT = @INPUT@
|
INPUT = @INPUT@
|
||||||
IMAGE_PATH = @top_srcdir@/doc/svg \
|
IMAGE_PATH = "@top_srcdir@/doc/svg" \
|
||||||
@top_srcdir@/doc/dot
|
"@top_srcdir@/doc/dot"
|
||||||
GENERATE_HTML = YES
|
GENERATE_HTML = YES
|
||||||
SEARCHENGINE = NO
|
SEARCHENGINE = NO
|
||||||
USE_MATHJAX = YES
|
USE_MATHJAX = YES
|
||||||
|
|
@ -20,11 +20,11 @@ MACRO_EXPANSION = YES
|
||||||
EXPAND_ONLY_PREDEF = YES
|
EXPAND_ONLY_PREDEF = YES
|
||||||
PREDEFINED = LIBINPUT_ATTRIBUTE_PRINTF(f, a)= \
|
PREDEFINED = LIBINPUT_ATTRIBUTE_PRINTF(f, a)= \
|
||||||
LIBINPUT_ATTRIBUTE_DEPRECATED
|
LIBINPUT_ATTRIBUTE_DEPRECATED
|
||||||
DOTFILE_DIRS = @top_srcdir@/doc/dot
|
DOTFILE_DIRS = "@top_srcdir@/doc/dot"
|
||||||
|
|
||||||
HTML_HEADER = @top_srcdir@/doc/style/header.html
|
HTML_HEADER = "@top_srcdir@/doc/style/header.html"
|
||||||
HTML_FOOTER = @top_srcdir@/doc/style/footer.html
|
HTML_FOOTER = "@top_srcdir@/doc/style/footer.html"
|
||||||
HTML_EXTRA_STYLESHEET = @top_srcdir@/doc/style/bootstrap.css \
|
HTML_EXTRA_STYLESHEET = "@top_srcdir@/doc/style/bootstrap.css" \
|
||||||
@top_srcdir@/doc/style/customdoxygen.css \
|
"@top_srcdir@/doc/style/customdoxygen.css" \
|
||||||
@top_srcdir@/doc/style/libinputdoxygen.css
|
"@top_srcdir@/doc/style/libinputdoxygen.css"
|
||||||
USE_MDFILE_AS_MAINPAGE = @top_srcdir@/README.md
|
USE_MDFILE_AS_MAINPAGE = "@top_srcdir@/README.md"
|
||||||
|
|
|
||||||
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 |
|
|
@ -1,18 +1,21 @@
|
||||||
/**
|
/**
|
||||||
@page test-suite libinput test suite
|
@page test-suite libinput test suite
|
||||||
|
|
||||||
The libinput test suite is based on
|
libinput ships with a number of tests all run automatically on `ninja test`.
|
||||||
[Check](http://check.sourceforge.net/doc/check_html/) and runs automatically
|
The primary test suite is the `libinput-test-suite-runner`. When testing,
|
||||||
during `make check`. Check itself is wrapped into a libinput-specific test
|
the `libinput-test-suite-runner` should always be invoked to check for
|
||||||
suite called *litest*. Tests are found in `$srcdir/test/`, the main test
|
behavior changes.
|
||||||
suite is `libinput-test-suite-runner`.
|
|
||||||
|
|
||||||
The test suite has a make-like job control enabled by the `-j` or `--jobs`
|
The test suite runner uses
|
||||||
flag and will fork off as many parallel processes as given by this flag. The
|
[Check](http://check.sourceforge.net/doc/check_html/) underneath the hood
|
||||||
default if unspecified is 8. When debugging a specific test case failure it
|
but most of the functionality is abstracted into *litest* wrappers.
|
||||||
is recommended to employ test filtures (see @ref test-filtering) and disable
|
|
||||||
parallel tests. The test suite automatically disables parallel make when run
|
The test suite runner has a make-like job control enabled by the `-j` or
|
||||||
in gdb.
|
`--jobs` flag and will fork off as many parallel processes as given by this
|
||||||
|
flag. The default if unspecified is 8. When debugging a specific test case
|
||||||
|
failure it is recommended to employ test filtures (see @ref test-filtering)
|
||||||
|
and disable parallel tests. The test suite automatically disables parallel
|
||||||
|
make when run in gdb.
|
||||||
|
|
||||||
@section test-config X.Org config to avoid interference
|
@section test-config X.Org config to avoid interference
|
||||||
|
|
||||||
|
|
@ -28,35 +31,67 @@ with your desktop.
|
||||||
|
|
||||||
Most tests require the creation of uinput devices and access to the
|
Most tests require the creation of uinput devices and access to the
|
||||||
resulting `/dev/input/eventX` nodes. Some tests require temporary udev rules.
|
resulting `/dev/input/eventX` nodes. Some tests require temporary udev rules.
|
||||||
<b>This usually requires the tests to be run as root</b>.
|
<b>This usually requires the tests to be run as root</b>. If not run as
|
||||||
|
root, the test suite runner will exit with status 77, interpreted as
|
||||||
|
"skipped" by ninja.
|
||||||
|
|
||||||
@section test-filtering Selective running of tests
|
@section test-filtering Selective running of tests
|
||||||
|
|
||||||
litest's tests are grouped by test groups and devices. A test group is e.g.
|
litest's tests are grouped into test groups, test names and devices. A test
|
||||||
"touchpad:tap" and incorporates all tapping-related tests for touchpads.
|
group is e.g. "touchpad:tap" and incorporates all tapping-related tests for
|
||||||
Each test function is (usually) run with one or more specific devices.
|
touchpads. Each test function is (usually) run with one or more specific
|
||||||
The `--list` commandline argument shows the list of suites and tests.
|
devices. The `--list` commandline argument shows the list of suites and
|
||||||
|
tests. This is useful when trying to figure out if a specific test is
|
||||||
|
run for a device.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
$ ./test/libinput-test-suite-runner --list
|
$ ./test/libinput-test-suite-runner --list
|
||||||
device:wheel:
|
...
|
||||||
wheel only
|
pointer:left-handed:
|
||||||
blackwidow
|
pointer_left_handed_during_click_multiple_buttons:
|
||||||
device:invalid devices:
|
trackpoint
|
||||||
no device
|
ms-surface-cover
|
||||||
device:group:
|
mouse-wheelclickcount
|
||||||
no device
|
mouse-wheelclickangle
|
||||||
logitech trackball
|
low-dpi-mouse
|
||||||
MS surface cover
|
mouse-roccat
|
||||||
mouse_roccat
|
mouse-wheel-tilt
|
||||||
wheel only
|
mouse
|
||||||
blackwidow
|
logitech-trackball
|
||||||
|
cyborg-rat
|
||||||
|
magicmouse
|
||||||
|
pointer_left_handed_during_click:
|
||||||
|
trackpoint
|
||||||
|
ms-surface-cover
|
||||||
|
mouse-wheelclickcount
|
||||||
|
mouse-wheelclickangle
|
||||||
|
low-dpi-mouse
|
||||||
|
mouse-roccat
|
||||||
|
mouse-wheel-tilt
|
||||||
|
mouse
|
||||||
|
logitech-trackball
|
||||||
|
cyborg-rat
|
||||||
|
litest-magicmouse-device
|
||||||
|
pointer_left_handed:
|
||||||
|
trackpoint
|
||||||
|
ms-surface-cover
|
||||||
|
mouse-wheelclickcount
|
||||||
|
mouse-wheelclickangle
|
||||||
|
low-dpi-mouse
|
||||||
|
mouse-roccat
|
||||||
|
mouse-wheel-tilt
|
||||||
|
mouse
|
||||||
...
|
...
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
In the above example, the "device:wheel" suite is run for the "wheel only" and
|
In the above example, the "pointer:left-handed" suite contains multiple
|
||||||
the "blackwidow" device. Both devices are automatically instantiated through
|
tests, e.g. "pointer_left_handed_during_click" (this is also the function
|
||||||
uinput by litest. The "no device" entry signals that litest does not
|
name of the test, making it easy to grep for). This particular test is run
|
||||||
instantiate a uinput device for a specific test (though the test itself may
|
for various devices including the trackpoint device and the magic mouse
|
||||||
|
device.
|
||||||
|
|
||||||
|
The "no device" entry signals that litest does not instantiate a uinput
|
||||||
|
device for a specific test (though the test itself may
|
||||||
instantiate one).
|
instantiate one).
|
||||||
|
|
||||||
The `--filter-test` argument enables selective running of tests through
|
The `--filter-test` argument enables selective running of tests through
|
||||||
|
|
@ -93,7 +128,7 @@ environment variable, if set, also enables verbose mode.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
$ ./test/libinput-test-suite-runner --verbose
|
$ ./test/libinput-test-suite-runner --verbose
|
||||||
$ LITEST_VERBOSE=1 make check
|
$ LITEST_VERBOSE=1 ninja test
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
project('libinput', 'c', 'cpp',
|
project('libinput', 'c', 'cpp',
|
||||||
version : '1.9.1',
|
version : '1.9.3',
|
||||||
license : 'MIT/Expat',
|
license : 'MIT/Expat',
|
||||||
default_options : [ 'c_std=gnu99', 'warning_level=2' ],
|
default_options : [ 'c_std=gnu99', 'warning_level=2' ],
|
||||||
meson_version : '>= 0.40.0')
|
meson_version : '>= 0.40.0')
|
||||||
|
|
@ -156,7 +156,9 @@ src_libinput = [
|
||||||
'src/libinput-private.h',
|
'src/libinput-private.h',
|
||||||
'src/evdev.c',
|
'src/evdev.c',
|
||||||
'src/evdev.h',
|
'src/evdev.h',
|
||||||
|
'src/evdev-debounce.c',
|
||||||
'src/evdev-fallback.c',
|
'src/evdev-fallback.c',
|
||||||
|
'src/evdev-fallback.h',
|
||||||
'src/evdev-middle-button.c',
|
'src/evdev-middle-button.c',
|
||||||
'src/evdev-mt-touchpad.c',
|
'src/evdev-mt-touchpad.c',
|
||||||
'src/evdev-mt-touchpad.h',
|
'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/libinput-stack-gnome.gv',
|
||||||
meson.source_root() + '/doc/dot/evemu.gv',
|
meson.source_root() + '/doc/dot/evemu.gv',
|
||||||
# svgs
|
# svgs
|
||||||
|
meson.source_root() + '/doc/svg/button-debouncing-wave-diagram.svg',
|
||||||
meson.source_root() + '/doc/svg/button-scrolling.svg',
|
meson.source_root() + '/doc/svg/button-scrolling.svg',
|
||||||
meson.source_root() + '/doc/svg/clickfinger.svg',
|
meson.source_root() + '/doc/svg/clickfinger.svg',
|
||||||
meson.source_root() + '/doc/svg/clickfinger-distance.svg',
|
meson.source_root() + '/doc/svg/clickfinger-distance.svg',
|
||||||
|
|
|
||||||
562
src/evdev-debounce.c
Normal file
562
src/evdev-debounce.c
Normal file
|
|
@ -0,0 +1,562 @@
|
||||||
|
/*
|
||||||
|
* 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_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_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_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 <mtdev-plumbing.h>
|
||||||
|
|
||||||
#include "evdev.h"
|
#include "evdev-fallback.h"
|
||||||
|
|
||||||
#define DEBOUNCE_TIME ms2us(12)
|
#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
|
static void
|
||||||
fallback_keyboard_notify_key(struct fallback_dispatch *dispatch,
|
fallback_keyboard_notify_key(struct fallback_dispatch *dispatch,
|
||||||
struct evdev_device *device,
|
struct evdev_device *device,
|
||||||
|
|
@ -317,6 +203,58 @@ fallback_flush_relative_motion(struct fallback_dispatch *dispatch,
|
||||||
pointer_notify_motion(base, time, &accel, &raw);
|
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
|
static void
|
||||||
fallback_flush_absolute_motion(struct fallback_dispatch *dispatch,
|
fallback_flush_absolute_motion(struct fallback_dispatch *dispatch,
|
||||||
struct evdev_device *device,
|
struct evdev_device *device,
|
||||||
|
|
@ -514,267 +452,14 @@ fallback_flush_st_up(struct fallback_dispatch *dispatch,
|
||||||
return true;
|
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
|
static void
|
||||||
fallback_process_touch_button(struct fallback_dispatch *dispatch,
|
fallback_process_touch_button(struct fallback_dispatch *dispatch,
|
||||||
struct evdev_device *device,
|
struct evdev_device *device,
|
||||||
uint64_t time, int value)
|
uint64_t time, int value)
|
||||||
{
|
{
|
||||||
if (dispatch->pending_event != EVDEV_NONE &&
|
dispatch->pending_event |= (value) ?
|
||||||
dispatch->pending_event != EVDEV_ABSOLUTE_MOTION)
|
|
||||||
fallback_flush_pending_event(dispatch, device, time);
|
|
||||||
|
|
||||||
dispatch->pending_event = (value ?
|
|
||||||
EVDEV_ABSOLUTE_TOUCH_DOWN :
|
EVDEV_ABSOLUTE_TOUCH_DOWN :
|
||||||
EVDEV_ABSOLUTE_TOUCH_UP);
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|
@ -797,8 +482,6 @@ fallback_process_key(struct fallback_dispatch *dispatch,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fallback_flush_pending_event(dispatch, device, time);
|
|
||||||
|
|
||||||
type = get_key_type(e->code);
|
type = get_key_type(e->code);
|
||||||
|
|
||||||
/* Ignore key release events from the kernel for keys that libinput
|
/* 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:
|
case KEY_TYPE_NONE:
|
||||||
break;
|
break;
|
||||||
case KEY_TYPE_KEY:
|
case KEY_TYPE_KEY:
|
||||||
|
case KEY_TYPE_BUTTON:
|
||||||
if ((e->value && hw_is_key_down(dispatch, e->code)) ||
|
if ((e->value && hw_is_key_down(dispatch, e->code)) ||
|
||||||
(e->value == 0 && !hw_is_key_down(dispatch, e->code)))
|
(e->value == 0 && !hw_is_key_down(dispatch, e->code)))
|
||||||
return;
|
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)) ||
|
dispatch->pending_event |= EVDEV_KEY;
|
||||||
(e->value == 0 && !hw_is_key_down(dispatch, e->code)))
|
|
||||||
return;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
hw_set_key_down(dispatch, e->code, e->value);
|
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
|
static void
|
||||||
|
|
@ -853,8 +509,9 @@ fallback_process_touch(struct fallback_dispatch *dispatch,
|
||||||
struct input_event *e,
|
struct input_event *e,
|
||||||
uint64_t time)
|
uint64_t time)
|
||||||
{
|
{
|
||||||
switch (e->code) {
|
struct mt_slot *slot = &dispatch->mt.slots[dispatch->mt.slot];
|
||||||
case ABS_MT_SLOT:
|
|
||||||
|
if (e->code == ABS_MT_SLOT) {
|
||||||
if ((size_t)e->value >= dispatch->mt.slots_len) {
|
if ((size_t)e->value >= dispatch->mt.slots_len) {
|
||||||
evdev_log_bug_libinput(device,
|
evdev_log_bug_libinput(device,
|
||||||
"exceeded slot count (%d of max %zd)\n",
|
"exceeded slot count (%d of max %zd)\n",
|
||||||
|
|
@ -862,32 +519,36 @@ fallback_process_touch(struct fallback_dispatch *dispatch,
|
||||||
dispatch->mt.slots_len);
|
dispatch->mt.slots_len);
|
||||||
e->value = dispatch->mt.slots_len - 1;
|
e->value = dispatch->mt.slots_len - 1;
|
||||||
}
|
}
|
||||||
fallback_flush_pending_event(dispatch, device, time);
|
|
||||||
dispatch->mt.slot = e->value;
|
dispatch->mt.slot = e->value;
|
||||||
break;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (e->code) {
|
||||||
case ABS_MT_TRACKING_ID:
|
case ABS_MT_TRACKING_ID:
|
||||||
if (dispatch->pending_event != EVDEV_NONE &&
|
if (e->value >= 0) {
|
||||||
dispatch->pending_event != EVDEV_ABSOLUTE_MT_MOTION)
|
dispatch->pending_event |= EVDEV_ABSOLUTE_MT;
|
||||||
fallback_flush_pending_event(dispatch, device, time);
|
slot->state = SLOT_STATE_BEGIN;
|
||||||
if (e->value >= 0)
|
} else {
|
||||||
dispatch->pending_event = EVDEV_ABSOLUTE_MT_DOWN;
|
dispatch->pending_event |= EVDEV_ABSOLUTE_MT;
|
||||||
else
|
slot->state = SLOT_STATE_END;
|
||||||
dispatch->pending_event = EVDEV_ABSOLUTE_MT_UP;
|
}
|
||||||
|
slot->dirty = true;
|
||||||
break;
|
break;
|
||||||
case ABS_MT_POSITION_X:
|
case ABS_MT_POSITION_X:
|
||||||
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
||||||
dispatch->mt.slots[dispatch->mt.slot].point.x = e->value;
|
dispatch->mt.slots[dispatch->mt.slot].point.x = e->value;
|
||||||
if (dispatch->pending_event == EVDEV_NONE)
|
dispatch->pending_event |= EVDEV_ABSOLUTE_MT;
|
||||||
dispatch->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
|
slot->dirty = true;
|
||||||
break;
|
break;
|
||||||
case ABS_MT_POSITION_Y:
|
case ABS_MT_POSITION_Y:
|
||||||
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
||||||
dispatch->mt.slots[dispatch->mt.slot].point.y = e->value;
|
dispatch->mt.slots[dispatch->mt.slot].point.y = e->value;
|
||||||
if (dispatch->pending_event == EVDEV_NONE)
|
dispatch->pending_event |= EVDEV_ABSOLUTE_MT;
|
||||||
dispatch->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
|
slot->dirty = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
fallback_process_absolute_motion(struct fallback_dispatch *dispatch,
|
fallback_process_absolute_motion(struct fallback_dispatch *dispatch,
|
||||||
struct evdev_device *device,
|
struct evdev_device *device,
|
||||||
|
|
@ -897,14 +558,12 @@ fallback_process_absolute_motion(struct fallback_dispatch *dispatch,
|
||||||
case ABS_X:
|
case ABS_X:
|
||||||
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
||||||
dispatch->abs.point.x = 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;
|
break;
|
||||||
case ABS_Y:
|
case ABS_Y:
|
||||||
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
evdev_device_check_abs_axis_range(device, e->code, e->value);
|
||||||
dispatch->abs.point.y = 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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -987,6 +646,8 @@ fallback_process_switch(struct fallback_dispatch *dispatch,
|
||||||
enum libinput_switch_state state;
|
enum libinput_switch_state state;
|
||||||
bool is_closed;
|
bool is_closed;
|
||||||
|
|
||||||
|
/* TODO: this should to move to handle_state */
|
||||||
|
|
||||||
switch (e->code) {
|
switch (e->code) {
|
||||||
case SW_LID:
|
case SW_LID:
|
||||||
is_closed = !!e->value;
|
is_closed = !!e->value;
|
||||||
|
|
@ -1037,61 +698,25 @@ fallback_process_relative(struct fallback_dispatch *dispatch,
|
||||||
struct evdev_device *device,
|
struct evdev_device *device,
|
||||||
struct input_event *e, uint64_t time)
|
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))
|
if (fallback_reject_relative(device, e, time))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (e->code) {
|
switch (e->code) {
|
||||||
case REL_X:
|
case REL_X:
|
||||||
if (dispatch->pending_event != EVDEV_RELATIVE_MOTION)
|
|
||||||
fallback_flush_pending_event(dispatch, device, time);
|
|
||||||
dispatch->rel.x += e->value;
|
dispatch->rel.x += e->value;
|
||||||
dispatch->pending_event = EVDEV_RELATIVE_MOTION;
|
dispatch->pending_event |= EVDEV_RELATIVE_MOTION;
|
||||||
break;
|
break;
|
||||||
case REL_Y:
|
case REL_Y:
|
||||||
if (dispatch->pending_event != EVDEV_RELATIVE_MOTION)
|
|
||||||
fallback_flush_pending_event(dispatch, device, time);
|
|
||||||
dispatch->rel.y += e->value;
|
dispatch->rel.y += e->value;
|
||||||
dispatch->pending_event = EVDEV_RELATIVE_MOTION;
|
dispatch->pending_event |= EVDEV_RELATIVE_MOTION;
|
||||||
break;
|
break;
|
||||||
case REL_WHEEL:
|
case REL_WHEEL:
|
||||||
fallback_flush_pending_event(dispatch, device, time);
|
dispatch->wheel.y += e->value;
|
||||||
wheel_degrees.y = -1 * e->value *
|
dispatch->pending_event |= EVDEV_WHEEL;
|
||||||
device->scroll.wheel_click_angle.x;
|
|
||||||
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);
|
|
||||||
break;
|
break;
|
||||||
case REL_HWHEEL:
|
case REL_HWHEEL:
|
||||||
fallback_flush_pending_event(dispatch, device, time);
|
dispatch->wheel.x += e->value;
|
||||||
wheel_degrees.x = e->value *
|
dispatch->pending_event |= EVDEV_WHEEL;
|
||||||
device->scroll.wheel_click_angle.y;
|
|
||||||
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);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1123,6 +748,120 @@ fallback_any_button_down(struct fallback_dispatch *dispatch,
|
||||||
return false;
|
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
|
static void
|
||||||
fallback_interface_process(struct evdev_dispatch *evdev_dispatch,
|
fallback_interface_process(struct evdev_dispatch *evdev_dispatch,
|
||||||
struct evdev_device *device,
|
struct evdev_device *device,
|
||||||
|
|
@ -1130,7 +869,6 @@ fallback_interface_process(struct evdev_dispatch *evdev_dispatch,
|
||||||
uint64_t time)
|
uint64_t time)
|
||||||
{
|
{
|
||||||
struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch);
|
struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch);
|
||||||
enum evdev_event_type sent;
|
|
||||||
|
|
||||||
if (dispatch->ignore_events)
|
if (dispatch->ignore_events)
|
||||||
return;
|
return;
|
||||||
|
|
@ -1149,20 +887,7 @@ fallback_interface_process(struct evdev_dispatch *evdev_dispatch,
|
||||||
fallback_process_switch(dispatch, device, event, time);
|
fallback_process_switch(dispatch, device, event, time);
|
||||||
break;
|
break;
|
||||||
case EV_SYN:
|
case EV_SYN:
|
||||||
sent = fallback_flush_pending_event(dispatch, device, time);
|
fallback_handle_state(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;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1254,6 +979,7 @@ fallback_return_to_neutral_state(struct fallback_dispatch *dispatch,
|
||||||
release_touches(dispatch, device, time);
|
release_touches(dispatch, device, time);
|
||||||
release_pressed_keys(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->hw_key_mask));
|
||||||
|
memset(dispatch->hw_key_mask, 0, sizeof(dispatch->last_hw_key_mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1341,6 +1067,8 @@ fallback_interface_destroy(struct evdev_dispatch *evdev_dispatch)
|
||||||
|
|
||||||
libinput_timer_cancel(&dispatch->debounce.timer);
|
libinput_timer_cancel(&dispatch->debounce.timer);
|
||||||
libinput_timer_destroy(&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->mt.slots);
|
||||||
free(dispatch);
|
free(dispatch);
|
||||||
}
|
}
|
||||||
|
|
@ -1714,7 +1442,6 @@ fallback_dispatch_create(struct libinput_device *libinput_device)
|
||||||
{
|
{
|
||||||
struct evdev_device *device = evdev_device(libinput_device);
|
struct evdev_device *device = evdev_device(libinput_device);
|
||||||
struct fallback_dispatch *dispatch;
|
struct fallback_dispatch *dispatch;
|
||||||
char timer_name[64];
|
|
||||||
|
|
||||||
dispatch = zalloc(sizeof *dispatch);
|
dispatch = zalloc(sizeof *dispatch);
|
||||||
dispatch->device = evdev_device(libinput_device);
|
dispatch->device = evdev_device(libinput_device);
|
||||||
|
|
@ -1764,14 +1491,7 @@ fallback_dispatch_create(struct libinput_device *libinput_device)
|
||||||
want_config);
|
want_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(timer_name,
|
fallback_init_debounce(dispatch);
|
||||||
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);
|
|
||||||
return &dispatch->base;
|
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
|
||||||
|
|
@ -1055,15 +1055,21 @@ tp_notify_clickpadbutton(struct tp_dispatch *tp,
|
||||||
if (is_topbutton && tp->buttons.trackpoint) {
|
if (is_topbutton && tp->buttons.trackpoint) {
|
||||||
struct evdev_dispatch *dispatch = tp->buttons.trackpoint->dispatch;
|
struct evdev_dispatch *dispatch = tp->buttons.trackpoint->dispatch;
|
||||||
struct input_event event;
|
struct input_event event;
|
||||||
|
struct input_event syn_report = {{ 0, 0 }, EV_SYN, SYN_REPORT, 0 };
|
||||||
|
|
||||||
event.time = us2tv(time);
|
event.time = us2tv(time);
|
||||||
event.type = EV_KEY;
|
event.type = EV_KEY;
|
||||||
event.code = button;
|
event.code = button;
|
||||||
event.value = (state == LIBINPUT_BUTTON_STATE_PRESSED) ? 1 : 0;
|
event.value = (state == LIBINPUT_BUTTON_STATE_PRESSED) ? 1 : 0;
|
||||||
|
syn_report.time = event.time;
|
||||||
dispatch->interface->process(dispatch,
|
dispatch->interface->process(dispatch,
|
||||||
tp->buttons.trackpoint,
|
tp->buttons.trackpoint,
|
||||||
&event,
|
&event,
|
||||||
time);
|
time);
|
||||||
|
dispatch->interface->process(dispatch,
|
||||||
|
tp->buttons.trackpoint,
|
||||||
|
&syn_report,
|
||||||
|
time);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -502,6 +502,7 @@ tp_process_trackpoint_button(struct tp_dispatch *tp,
|
||||||
{
|
{
|
||||||
struct evdev_dispatch *dispatch;
|
struct evdev_dispatch *dispatch;
|
||||||
struct input_event event;
|
struct input_event event;
|
||||||
|
struct input_event syn_report = {{ 0, 0 }, EV_SYN, SYN_REPORT, 0 };
|
||||||
|
|
||||||
if (!tp->buttons.trackpoint)
|
if (!tp->buttons.trackpoint)
|
||||||
return;
|
return;
|
||||||
|
|
@ -509,6 +510,7 @@ tp_process_trackpoint_button(struct tp_dispatch *tp,
|
||||||
dispatch = tp->buttons.trackpoint->dispatch;
|
dispatch = tp->buttons.trackpoint->dispatch;
|
||||||
|
|
||||||
event = *e;
|
event = *e;
|
||||||
|
syn_report.time = e->time;
|
||||||
|
|
||||||
switch (event.code) {
|
switch (event.code) {
|
||||||
case BTN_0:
|
case BTN_0:
|
||||||
|
|
@ -527,6 +529,9 @@ tp_process_trackpoint_button(struct tp_dispatch *tp,
|
||||||
dispatch->interface->process(dispatch,
|
dispatch->interface->process(dispatch,
|
||||||
tp->buttons.trackpoint,
|
tp->buttons.trackpoint,
|
||||||
&event, time);
|
&event, time);
|
||||||
|
dispatch->interface->process(dispatch,
|
||||||
|
tp->buttons.trackpoint,
|
||||||
|
&syn_report, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1588,6 +1593,8 @@ tp_interface_process(struct evdev_dispatch *dispatch,
|
||||||
static void
|
static void
|
||||||
tp_remove_sendevents(struct tp_dispatch *tp)
|
tp_remove_sendevents(struct tp_dispatch *tp)
|
||||||
{
|
{
|
||||||
|
struct paired_keyboard *kbd;
|
||||||
|
|
||||||
libinput_timer_cancel(&tp->palm.trackpoint_timer);
|
libinput_timer_cancel(&tp->palm.trackpoint_timer);
|
||||||
libinput_timer_cancel(&tp->dwt.keyboard_timer);
|
libinput_timer_cancel(&tp->dwt.keyboard_timer);
|
||||||
|
|
||||||
|
|
@ -1596,9 +1603,10 @@ tp_remove_sendevents(struct tp_dispatch *tp)
|
||||||
libinput_device_remove_event_listener(
|
libinput_device_remove_event_listener(
|
||||||
&tp->palm.trackpoint_listener);
|
&tp->palm.trackpoint_listener);
|
||||||
|
|
||||||
if (tp->dwt.keyboard)
|
ARRAY_FOR_EACH(tp->dwt.paired_keyboard, kbd) {
|
||||||
libinput_device_remove_event_listener(
|
if (kbd->device)
|
||||||
&tp->dwt.keyboard_listener);
|
libinput_device_remove_event_listener(&kbd->listener);
|
||||||
|
}
|
||||||
|
|
||||||
if (tp->lid_switch.lid_switch)
|
if (tp->lid_switch.lid_switch)
|
||||||
libinput_device_remove_event_listener(
|
libinput_device_remove_event_listener(
|
||||||
|
|
@ -1964,9 +1972,8 @@ tp_dwt_pair_keyboard(struct evdev_device *touchpad,
|
||||||
struct evdev_device *keyboard)
|
struct evdev_device *keyboard)
|
||||||
{
|
{
|
||||||
struct tp_dispatch *tp = (struct tp_dispatch*)touchpad->dispatch;
|
struct tp_dispatch *tp = (struct tp_dispatch*)touchpad->dispatch;
|
||||||
|
struct paired_keyboard *kbd;
|
||||||
if (tp->dwt.keyboard)
|
bool found = false;
|
||||||
return;
|
|
||||||
|
|
||||||
if ((keyboard->tags & EVDEV_TAG_KEYBOARD) == 0)
|
if ((keyboard->tags & EVDEV_TAG_KEYBOARD) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
@ -1974,16 +1981,25 @@ tp_dwt_pair_keyboard(struct evdev_device *touchpad,
|
||||||
if (!tp_want_dwt(touchpad, keyboard))
|
if (!tp_want_dwt(touchpad, keyboard))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
libinput_device_add_event_listener(&keyboard->base,
|
ARRAY_FOR_EACH(tp->dwt.paired_keyboard, kbd) {
|
||||||
&tp->dwt.keyboard_listener,
|
if (kbd->device)
|
||||||
tp_keyboard_event, tp);
|
continue;
|
||||||
tp->dwt.keyboard = keyboard;
|
|
||||||
tp->dwt.keyboard_active = false;
|
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
libinput_device_add_event_listener(&keyboard->base,
|
||||||
|
&kbd->listener,
|
||||||
|
tp_keyboard_event, tp);
|
||||||
|
kbd->device = keyboard;
|
||||||
evdev_log_debug(touchpad,
|
evdev_log_debug(touchpad,
|
||||||
"palm: dwt activated with %s<->%s\n",
|
"palm: dwt activated with %s<->%s\n",
|
||||||
touchpad->devname,
|
touchpad->devname,
|
||||||
keyboard->devname);
|
keyboard->devname);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
evdev_log_bug_libinput(touchpad,
|
||||||
|
"too many internal keyboards for dwt\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -2121,6 +2137,7 @@ tp_interface_device_removed(struct evdev_device *device,
|
||||||
struct evdev_device *removed_device)
|
struct evdev_device *removed_device)
|
||||||
{
|
{
|
||||||
struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
|
struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
|
||||||
|
struct paired_keyboard *kbd;
|
||||||
|
|
||||||
if (removed_device == tp->buttons.trackpoint) {
|
if (removed_device == tp->buttons.trackpoint) {
|
||||||
/* Clear any pending releases for the trackpoint */
|
/* Clear any pending releases for the trackpoint */
|
||||||
|
|
@ -2134,12 +2151,13 @@ tp_interface_device_removed(struct evdev_device *device,
|
||||||
tp->buttons.trackpoint = NULL;
|
tp->buttons.trackpoint = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (removed_device == tp->dwt.keyboard) {
|
ARRAY_FOR_EACH(tp->dwt.paired_keyboard, kbd) {
|
||||||
libinput_device_remove_event_listener(
|
if (kbd->device == removed_device) {
|
||||||
&tp->dwt.keyboard_listener);
|
libinput_device_remove_event_listener(&kbd->listener);
|
||||||
tp->dwt.keyboard = NULL;
|
kbd->device = NULL;
|
||||||
tp->dwt.keyboard_active = false;
|
tp->dwt.keyboard_active = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (removed_device == tp->lid_switch.lid_switch) {
|
if (removed_device == tp->lid_switch.lid_switch) {
|
||||||
libinput_device_remove_event_listener(
|
libinput_device_remove_event_listener(
|
||||||
|
|
|
||||||
|
|
@ -383,13 +383,20 @@ struct tp_dispatch {
|
||||||
struct libinput_device_config_dwt config;
|
struct libinput_device_config_dwt config;
|
||||||
bool dwt_enabled;
|
bool dwt_enabled;
|
||||||
|
|
||||||
bool keyboard_active;
|
/* We have to allow for more than one device node to be the
|
||||||
struct libinput_event_listener keyboard_listener;
|
* internal dwt keyboard (Razer Blade). But they're the same
|
||||||
struct libinput_timer keyboard_timer;
|
* physical device, so we don't care about per-keyboard
|
||||||
struct evdev_device *keyboard;
|
* key/modifier masks.
|
||||||
|
*/
|
||||||
|
struct paired_keyboard {
|
||||||
|
struct evdev_device *device;
|
||||||
|
struct libinput_event_listener listener;
|
||||||
|
} paired_keyboard[3];
|
||||||
|
|
||||||
unsigned long key_mask[NLONGS(KEY_CNT)];
|
unsigned long key_mask[NLONGS(KEY_CNT)];
|
||||||
unsigned long mod_mask[NLONGS(KEY_CNT)];
|
unsigned long mod_mask[NLONGS(KEY_CNT)];
|
||||||
|
bool keyboard_active;
|
||||||
|
struct libinput_timer keyboard_timer;
|
||||||
uint64_t keyboard_last_press_time;
|
uint64_t keyboard_last_press_time;
|
||||||
} dwt;
|
} dwt;
|
||||||
|
|
||||||
|
|
|
||||||
10
src/evdev.c
10
src/evdev.c
|
|
@ -1099,17 +1099,17 @@ evdev_read_wheel_click_props(struct evdev_device *device)
|
||||||
/* CLICK_COUNT overrides CLICK_ANGLE */
|
/* CLICK_COUNT overrides CLICK_ANGLE */
|
||||||
if (!evdev_read_wheel_click_count_prop(device,
|
if (!evdev_read_wheel_click_count_prop(device,
|
||||||
"MOUSE_WHEEL_CLICK_COUNT",
|
"MOUSE_WHEEL_CLICK_COUNT",
|
||||||
&angles.x))
|
&angles.y))
|
||||||
evdev_read_wheel_click_prop(device,
|
evdev_read_wheel_click_prop(device,
|
||||||
"MOUSE_WHEEL_CLICK_ANGLE",
|
"MOUSE_WHEEL_CLICK_ANGLE",
|
||||||
&angles.x);
|
&angles.y);
|
||||||
if (!evdev_read_wheel_click_count_prop(device,
|
if (!evdev_read_wheel_click_count_prop(device,
|
||||||
"MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL",
|
"MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL",
|
||||||
&angles.y)) {
|
&angles.x)) {
|
||||||
if (!evdev_read_wheel_click_prop(device,
|
if (!evdev_read_wheel_click_prop(device,
|
||||||
"MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL",
|
"MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL",
|
||||||
&angles.y))
|
&angles.x))
|
||||||
angles.y = angles.x;
|
angles.x = angles.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
return angles;
|
return angles;
|
||||||
|
|
|
||||||
24
src/evdev.h
24
src/evdev.h
|
|
@ -41,13 +41,14 @@
|
||||||
|
|
||||||
enum evdev_event_type {
|
enum evdev_event_type {
|
||||||
EVDEV_NONE,
|
EVDEV_NONE,
|
||||||
EVDEV_ABSOLUTE_TOUCH_DOWN,
|
EVDEV_ABSOLUTE_TOUCH_DOWN = (1 << 0),
|
||||||
EVDEV_ABSOLUTE_MOTION,
|
EVDEV_ABSOLUTE_MOTION = (1 << 1),
|
||||||
EVDEV_ABSOLUTE_TOUCH_UP,
|
EVDEV_ABSOLUTE_TOUCH_UP = (1 << 2),
|
||||||
EVDEV_ABSOLUTE_MT_DOWN,
|
EVDEV_ABSOLUTE_MT= (1 << 3),
|
||||||
EVDEV_ABSOLUTE_MT_MOTION,
|
EVDEV_WHEEL = (1 << 4),
|
||||||
EVDEV_ABSOLUTE_MT_UP,
|
EVDEV_KEY = (1 << 5),
|
||||||
EVDEV_RELATIVE_MOTION,
|
EVDEV_RELATIVE_MOTION = (1 << 6),
|
||||||
|
EVDEV_BUTTON = (1 << 7),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum evdev_device_seat_capability {
|
enum evdev_device_seat_capability {
|
||||||
|
|
@ -150,7 +151,16 @@ enum evdev_debounce_state {
|
||||||
DEBOUNCE_ACTIVE,
|
DEBOUNCE_ACTIVE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum mt_slot_state {
|
||||||
|
SLOT_STATE_NONE,
|
||||||
|
SLOT_STATE_BEGIN,
|
||||||
|
SLOT_STATE_UPDATE,
|
||||||
|
SLOT_STATE_END,
|
||||||
|
};
|
||||||
|
|
||||||
struct mt_slot {
|
struct mt_slot {
|
||||||
|
bool dirty;
|
||||||
|
enum mt_slot_state state;
|
||||||
int32_t seat_slot;
|
int32_t seat_slot;
|
||||||
struct device_coords point;
|
struct device_coords point;
|
||||||
struct device_coords hysteresis_center;
|
struct device_coords hysteresis_center;
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ static const char udev_rule[] =
|
||||||
"\n"
|
"\n"
|
||||||
"LABEL=\"mouse_end\"";
|
"LABEL=\"mouse_end\"";
|
||||||
|
|
||||||
TEST_DEVICE("litest-magicmouse-device",
|
TEST_DEVICE("magicmouse",
|
||||||
.type = LITEST_MAGICMOUSE,
|
.type = LITEST_MAGICMOUSE,
|
||||||
.features = LITEST_RELATIVE | LITEST_BUTTON | LITEST_WHEEL,
|
.features = LITEST_RELATIVE | LITEST_BUTTON | LITEST_WHEEL,
|
||||||
.interface = &interface,
|
.interface = &interface,
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include <check.h>
|
#include <check.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
|
@ -1071,20 +1072,35 @@ litest_install_model_quirks(struct list *created_files_list)
|
||||||
list_insert(created_files_list, &file->link);
|
list_insert(created_files_list, &file->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
mkdir_p(const char *dir)
|
||||||
|
{
|
||||||
|
char *path, *parent;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (streq(dir, "/"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
path = strdup(dir);
|
||||||
|
parent = dirname(path);
|
||||||
|
|
||||||
|
mkdir_p(parent);
|
||||||
|
rc = mkdir(dir, 0755);
|
||||||
|
|
||||||
|
if (rc == -1 && errno != EEXIST) {
|
||||||
|
litest_abort_msg("Failed to create directory %s (%s)\n",
|
||||||
|
dir,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
litest_init_udev_rules(struct list *created_files)
|
litest_init_udev_rules(struct list *created_files)
|
||||||
{
|
{
|
||||||
int rc;
|
mkdir_p(UDEV_RULES_D);
|
||||||
|
mkdir_p(UDEV_HWDB_D);
|
||||||
rc = mkdir(UDEV_RULES_D, 0755);
|
|
||||||
if (rc == -1 && errno != EEXIST)
|
|
||||||
litest_abort_msg("Failed to create udev rules directory (%s)\n",
|
|
||||||
strerror(errno));
|
|
||||||
|
|
||||||
rc = mkdir(UDEV_HWDB_D, 0755);
|
|
||||||
if (rc == -1 && errno != EEXIST)
|
|
||||||
litest_abort_msg("Failed to create udev hwdb directory (%s)\n",
|
|
||||||
strerror(errno));
|
|
||||||
|
|
||||||
litest_install_model_quirks(created_files);
|
litest_install_model_quirks(created_files);
|
||||||
litest_init_all_device_udev_rules(created_files);
|
litest_init_all_device_udev_rules(created_files);
|
||||||
|
|
@ -2002,7 +2018,10 @@ litest_hover_move_two_touches(struct litest_device *d,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
struct input_event *ev;
|
||||||
|
|
@ -2013,7 +2032,9 @@ litest_button_click(struct litest_device *d, unsigned int button, bool is_press)
|
||||||
|
|
||||||
ARRAY_FOR_EACH(click, ev)
|
ARRAY_FOR_EACH(click, ev)
|
||||||
litest_event(d, ev->type, ev->code, ev->value);
|
litest_event(d, ev->type, ev->code, ev->value);
|
||||||
|
libinput_dispatch(li);
|
||||||
litest_timeout_debounce();
|
litest_timeout_debounce();
|
||||||
|
libinput_dispatch(li);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -2023,7 +2044,7 @@ litest_button_scroll(struct litest_device *dev,
|
||||||
{
|
{
|
||||||
struct libinput *li = dev->libinput;
|
struct libinput *li = dev->libinput;
|
||||||
|
|
||||||
litest_button_click(dev, button, 1);
|
litest_button_click_debounced(dev, li, button, 1);
|
||||||
|
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
litest_timeout_buttonscroll();
|
litest_timeout_buttonscroll();
|
||||||
|
|
@ -2033,7 +2054,7 @@ litest_button_scroll(struct litest_device *dev,
|
||||||
litest_event(dev, EV_REL, REL_Y, dy);
|
litest_event(dev, EV_REL, REL_Y, dy);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
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);
|
libinput_dispatch(li);
|
||||||
}
|
}
|
||||||
|
|
@ -2041,7 +2062,14 @@ litest_button_scroll(struct litest_device *dev,
|
||||||
void
|
void
|
||||||
litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press)
|
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
|
void
|
||||||
|
|
@ -3154,7 +3182,7 @@ litest_timeout_tapndrag(void)
|
||||||
void
|
void
|
||||||
litest_timeout_debounce(void)
|
litest_timeout_debounce(void)
|
||||||
{
|
{
|
||||||
msleep(15);
|
msleep(30);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -596,7 +596,8 @@ litest_hover_move_two_touches(struct litest_device *d,
|
||||||
int steps, int sleep_ms);
|
int steps, int sleep_ms);
|
||||||
|
|
||||||
void
|
void
|
||||||
litest_button_click(struct litest_device *d,
|
litest_button_click_debounced(struct litest_device *d,
|
||||||
|
struct libinput *li,
|
||||||
unsigned int button,
|
unsigned int button,
|
||||||
bool is_press);
|
bool is_press);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -463,7 +463,7 @@ START_TEST(device_disable_release_buttons)
|
||||||
|
|
||||||
device = dev->libinput_device;
|
device = dev->libinput_device;
|
||||||
|
|
||||||
litest_button_click(dev, BTN_LEFT, true);
|
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
status = libinput_device_config_send_events_set_mode(device,
|
status = libinput_device_config_send_events_set_mode(device,
|
||||||
|
|
@ -497,7 +497,7 @@ START_TEST(device_disable_release_keys)
|
||||||
|
|
||||||
device = dev->libinput_device;
|
device = dev->libinput_device;
|
||||||
|
|
||||||
litest_button_click(dev, KEY_A, true);
|
litest_button_click_debounced(dev, li, KEY_A, true);
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
status = libinput_device_config_send_events_set_mode(device,
|
status = libinput_device_config_send_events_set_mode(device,
|
||||||
|
|
@ -616,7 +616,7 @@ START_TEST(device_disable_release_softbutton)
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
litest_touch_down(dev, 0, 90, 90);
|
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 */
|
/* make sure softbutton works */
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
|
|
@ -633,7 +633,7 @@ START_TEST(device_disable_release_softbutton)
|
||||||
|
|
||||||
litest_assert_empty_queue(li);
|
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, 0);
|
||||||
|
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_empty_queue(li);
|
||||||
|
|
@ -669,8 +669,8 @@ START_TEST(device_disable_topsoftbutton)
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
litest_touch_down(dev, 0, 90, 10);
|
litest_touch_down(dev, 0, 90, 10);
|
||||||
litest_button_click(dev, BTN_LEFT, true);
|
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||||
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, 0);
|
||||||
|
|
||||||
litest_wait_for_event(li);
|
litest_wait_for_event(li);
|
||||||
|
|
|
||||||
|
|
@ -416,8 +416,8 @@ START_TEST(event_conversion_tablet)
|
||||||
|
|
||||||
litest_tablet_proximity_in(dev, 50, 50, axes);
|
litest_tablet_proximity_in(dev, 50, 50, axes);
|
||||||
litest_tablet_motion(dev, 60, 50, axes);
|
litest_tablet_motion(dev, 60, 50, axes);
|
||||||
litest_button_click(dev, BTN_STYLUS, true);
|
litest_button_click_debounced(dev, li, BTN_STYLUS, true);
|
||||||
litest_button_click(dev, BTN_STYLUS, false);
|
litest_button_click_debounced(dev, li, BTN_STYLUS, false);
|
||||||
|
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
|
|
@ -458,7 +458,7 @@ START_TEST(event_conversion_tablet_pad)
|
||||||
struct libinput_event *event;
|
struct libinput_event *event;
|
||||||
int events = 0;
|
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_start(dev, 10);
|
||||||
litest_pad_ring_end(dev);
|
litest_pad_ring_end(dev);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,8 +68,8 @@ START_TEST(pad_time)
|
||||||
if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
|
if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
litest_button_click(dev, code, 1);
|
litest_button_click_debounced(dev, li, code, 1);
|
||||||
litest_button_click(dev, code, 0);
|
litest_button_click_debounced(dev, li, code, 0);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
|
|
@ -98,8 +98,8 @@ START_TEST(pad_time)
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
msleep(10);
|
msleep(10);
|
||||||
|
|
||||||
litest_button_click(dev, code, 1);
|
litest_button_click_debounced(dev, li, code, 1);
|
||||||
litest_button_click(dev, code, 0);
|
litest_button_click_debounced(dev, li, code, 0);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
ev = libinput_get_event(li);
|
ev = libinput_get_event(li);
|
||||||
|
|
@ -156,8 +156,8 @@ START_TEST(pad_button)
|
||||||
if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
|
if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
litest_button_click(dev, code, 1);
|
litest_button_click_debounced(dev, li, code, 1);
|
||||||
litest_button_click(dev, code, 0);
|
litest_button_click_debounced(dev, li, code, 0);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
|
|
@ -207,8 +207,8 @@ START_TEST(pad_button_mode_groups)
|
||||||
if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
|
if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
litest_button_click(dev, code, 1);
|
litest_button_click_debounced(dev, li, code, 1);
|
||||||
litest_button_click(dev, code, 0);
|
litest_button_click_debounced(dev, li, code, 0);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
|
|
|
||||||
|
|
@ -348,7 +348,7 @@ test_button_event(struct litest_device *dev, unsigned int button, int state)
|
||||||
{
|
{
|
||||||
struct libinput *li = dev->libinput;
|
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_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
|
||||||
litest_assert_button_event(li, button,
|
litest_assert_button_event(li, button,
|
||||||
|
|
@ -500,7 +500,7 @@ START_TEST(pointer_recover_from_lost_button_count)
|
||||||
|
|
||||||
litest_drain_events(dev->libinput);
|
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,
|
litest_assert_button_event(li,
|
||||||
BTN_LEFT,
|
BTN_LEFT,
|
||||||
|
|
@ -508,15 +508,15 @@ START_TEST(pointer_recover_from_lost_button_count)
|
||||||
|
|
||||||
/* Grab for the release to make libinput lose count */
|
/* Grab for the release to make libinput lose count */
|
||||||
libevdev_grab(evdev, LIBEVDEV_GRAB);
|
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);
|
libevdev_grab(evdev, LIBEVDEV_UNGRAB);
|
||||||
|
|
||||||
litest_assert_empty_queue(li);
|
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_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,
|
litest_assert_button_event(li,
|
||||||
BTN_LEFT,
|
BTN_LEFT,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
@ -802,7 +802,10 @@ START_TEST(pointer_seat_button_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_devices; ++i)
|
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);
|
libinput_dispatch(libinput);
|
||||||
while ((ev = libinput_get_event(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);
|
ck_assert_int_eq(seat_button_count, num_devices);
|
||||||
|
|
||||||
for (i = 0; i < num_devices; ++i)
|
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);
|
libinput_dispatch(libinput);
|
||||||
while ((ev = libinput_get_event(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);
|
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||||
|
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_button_click(dev, BTN_LEFT, 1);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||||
litest_button_click(dev, BTN_LEFT, 0);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||||
|
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_RIGHT,
|
BTN_RIGHT,
|
||||||
|
|
@ -931,8 +937,8 @@ START_TEST(pointer_left_handed)
|
||||||
BTN_RIGHT,
|
BTN_RIGHT,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
||||||
litest_button_click(dev, BTN_RIGHT, 1);
|
litest_button_click_debounced(dev, li, BTN_RIGHT, 1);
|
||||||
litest_button_click(dev, BTN_RIGHT, 0);
|
litest_button_click_debounced(dev, li, BTN_RIGHT, 0);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_LEFT,
|
BTN_LEFT,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
|
@ -941,8 +947,8 @@ START_TEST(pointer_left_handed)
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
||||||
if (libinput_device_pointer_has_button(d, BTN_MIDDLE)) {
|
if (libinput_device_pointer_has_button(d, BTN_MIDDLE)) {
|
||||||
litest_button_click(dev, BTN_MIDDLE, 1);
|
litest_button_click_debounced(dev, li, BTN_MIDDLE, 1);
|
||||||
litest_button_click(dev, BTN_MIDDLE, 0);
|
litest_button_click_debounced(dev, li, BTN_MIDDLE, 0);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
|
@ -961,14 +967,14 @@ START_TEST(pointer_left_handed_during_click)
|
||||||
enum libinput_config_status status;
|
enum libinput_config_status status;
|
||||||
|
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_button_click(dev, BTN_LEFT, 1);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
/* Change while button is down, expect correct release event */
|
/* Change while button is down, expect correct release event */
|
||||||
status = libinput_device_config_left_handed_set(d, 1);
|
status = libinput_device_config_left_handed_set(d, 1);
|
||||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
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,
|
litest_assert_button_event(li,
|
||||||
BTN_LEFT,
|
BTN_LEFT,
|
||||||
|
|
@ -992,16 +998,16 @@ START_TEST(pointer_left_handed_during_click_multiple_buttons)
|
||||||
litest_disable_middleemu(dev);
|
litest_disable_middleemu(dev);
|
||||||
|
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_button_click(dev, BTN_LEFT, 1);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
status = libinput_device_config_left_handed_set(d, 1);
|
status = libinput_device_config_left_handed_set(d, 1);
|
||||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||||
|
|
||||||
/* No left-handed until all buttons were down */
|
/* No left-handed until all buttons were down */
|
||||||
litest_button_click(dev, BTN_RIGHT, 1);
|
litest_button_click_debounced(dev, li, BTN_RIGHT, 1);
|
||||||
litest_button_click(dev, BTN_RIGHT, 0);
|
litest_button_click_debounced(dev, li, BTN_RIGHT, 0);
|
||||||
litest_button_click(dev, BTN_LEFT, 0);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||||
|
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_LEFT,
|
BTN_LEFT,
|
||||||
|
|
@ -1102,7 +1108,7 @@ START_TEST(pointer_scroll_button_no_event_before_timeout)
|
||||||
BTN_LEFT);
|
BTN_LEFT);
|
||||||
litest_drain_events(li);
|
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);
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
|
|
@ -1113,7 +1119,7 @@ START_TEST(pointer_scroll_button_no_event_before_timeout)
|
||||||
|
|
||||||
litest_timeout_buttonscroll();
|
litest_timeout_buttonscroll();
|
||||||
libinput_dispatch(li);
|
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,
|
litest_assert_button_event(li, BTN_LEFT,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
|
@ -1146,8 +1152,8 @@ START_TEST(pointer_scroll_button_middle_emulation)
|
||||||
|
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
litest_button_click(dev, BTN_LEFT, 1);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||||
litest_button_click(dev, BTN_RIGHT, 1);
|
litest_button_click_debounced(dev, li, BTN_RIGHT, 1);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
litest_timeout_buttonscroll();
|
litest_timeout_buttonscroll();
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
@ -1159,8 +1165,8 @@ START_TEST(pointer_scroll_button_middle_emulation)
|
||||||
|
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
litest_button_click(dev, BTN_LEFT, 0);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||||
litest_button_click(dev, BTN_RIGHT, 0);
|
litest_button_click_debounced(dev, li, BTN_RIGHT, 0);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -1);
|
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -1);
|
||||||
|
|
@ -1525,16 +1531,16 @@ START_TEST(middlebutton)
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(btn); i++) {
|
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_button_click(device, btn[i][1], true);
|
litest_button_click_debounced(device, li, btn[i][1], true);
|
||||||
|
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
litest_button_click(device, btn[i][2], false);
|
litest_button_click_debounced(device, li, btn[i][2], false);
|
||||||
litest_button_click(device, btn[i][3], false);
|
litest_button_click_debounced(device, li, btn[i][3], false);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
@ -1568,33 +1574,33 @@ START_TEST(middlebutton_nostart_while_down)
|
||||||
if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED)
|
if (status == LIBINPUT_CONFIG_STATUS_UNSUPPORTED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
litest_button_click(device, BTN_MIDDLE, true);
|
litest_button_click_debounced(device, li, BTN_MIDDLE, true);
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(btn); i++) {
|
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,
|
litest_assert_button_event(li,
|
||||||
btn[i][0],
|
btn[i][0],
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
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,
|
litest_assert_button_event(li,
|
||||||
btn[i][1],
|
btn[i][1],
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
|
||||||
litest_assert_empty_queue(li);
|
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,
|
litest_assert_button_event(li,
|
||||||
btn[i][2],
|
btn[i][2],
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
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,
|
litest_assert_button_event(li,
|
||||||
btn[i][3],
|
btn[i][3],
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
litest_assert_empty_queue(li);
|
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);
|
litest_drain_events(li);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
@ -1616,7 +1622,7 @@ START_TEST(middlebutton_timeout)
|
||||||
|
|
||||||
for (button = BTN_LEFT; button <= BTN_RIGHT; button++) {
|
for (button = BTN_LEFT; button <= BTN_RIGHT; button++) {
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_button_click(device, button, true);
|
litest_button_click_debounced(device, li, button, true);
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_empty_queue(li);
|
||||||
litest_timeout_middlebutton();
|
litest_timeout_middlebutton();
|
||||||
|
|
||||||
|
|
@ -1624,7 +1630,7 @@ START_TEST(middlebutton_timeout)
|
||||||
button,
|
button,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
|
||||||
litest_button_click(device, button, false);
|
litest_button_click_debounced(device, li, button, false);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
button,
|
button,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
@ -1657,22 +1663,22 @@ START_TEST(middlebutton_doubleclick)
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(btn); i++) {
|
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_button_click(device, btn[i][1], true);
|
litest_button_click_debounced(device, li, btn[i][1], true);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
litest_button_click(device, btn[i][2], false);
|
litest_button_click_debounced(device, li, btn[i][2], false);
|
||||||
litest_button_click(device, btn[i][2], true);
|
litest_button_click_debounced(device, li, btn[i][2], true);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
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,
|
litest_assert_button_event(li,
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
|
|
@ -1705,8 +1711,8 @@ START_TEST(middlebutton_middleclick)
|
||||||
for (button = BTN_LEFT; button <= BTN_RIGHT; button++) {
|
for (button = BTN_LEFT; button <= BTN_RIGHT; button++) {
|
||||||
/* release button before middle */
|
/* release button before middle */
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_button_click(device, button, true);
|
litest_button_click_debounced(device, li, button, true);
|
||||||
litest_button_click(device, BTN_MIDDLE, true);
|
litest_button_click_debounced(device, li, BTN_MIDDLE, true);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
button,
|
button,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
|
@ -1714,19 +1720,19 @@ START_TEST(middlebutton_middleclick)
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_empty_queue(li);
|
||||||
litest_button_click(device, button, false);
|
litest_button_click_debounced(device, li, button, false);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
button,
|
button,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
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,
|
litest_assert_button_event(li,
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
/* release middle before button */
|
/* release middle before button */
|
||||||
litest_button_click(device, button, true);
|
litest_button_click_debounced(device, li, button, true);
|
||||||
litest_button_click(device, BTN_MIDDLE, true);
|
litest_button_click_debounced(device, li, BTN_MIDDLE, true);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
button,
|
button,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
|
@ -1734,11 +1740,11 @@ START_TEST(middlebutton_middleclick)
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
litest_assert_empty_queue(li);
|
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,
|
litest_assert_button_event(li,
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
litest_button_click(device, button, false);
|
litest_button_click_debounced(device, li, button, false);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
button,
|
button,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
@ -1770,14 +1776,14 @@ START_TEST(middlebutton_middleclick_during)
|
||||||
|
|
||||||
/* trigger emulation, then real middle */
|
/* trigger emulation, then real middle */
|
||||||
for (button = BTN_LEFT; button <= BTN_RIGHT; button++) {
|
for (button = BTN_LEFT; button <= BTN_RIGHT; button++) {
|
||||||
litest_button_click(device, BTN_LEFT, true);
|
litest_button_click_debounced(device, li, BTN_LEFT, true);
|
||||||
litest_button_click(device, BTN_RIGHT, true);
|
litest_button_click_debounced(device, li, BTN_RIGHT, true);
|
||||||
|
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
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,
|
litest_assert_button_event(li,
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
@ -1788,23 +1794,23 @@ START_TEST(middlebutton_middleclick_during)
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
/* middle still down, release left/right */
|
/* 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_assert_empty_queue(li);
|
||||||
litest_button_click(device, button, true);
|
litest_button_click_debounced(device, li, button, true);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
button,
|
button,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
/* release both */
|
/* release both */
|
||||||
litest_button_click(device, BTN_LEFT, false);
|
litest_button_click_debounced(device, li, BTN_LEFT, false);
|
||||||
litest_button_click(device, BTN_RIGHT, false);
|
litest_button_click_debounced(device, li, BTN_RIGHT, false);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
button,
|
button,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
litest_assert_empty_queue(li);
|
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,
|
litest_assert_button_event(li,
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
@ -2104,91 +2110,176 @@ START_TEST(pointer_time_usec)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(debounce)
|
START_TEST(debounce_bounce)
|
||||||
{
|
{
|
||||||
struct litest_device *dev = litest_current_device();
|
struct litest_device *dev = litest_current_device();
|
||||||
struct libinput *li = dev->libinput;
|
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);
|
litest_disable_middleemu(dev);
|
||||||
|
disable_button_scrolling(dev);
|
||||||
litest_drain_events(li);
|
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_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);
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
litest_event(dev, EV_KEY, button, 1);
|
||||||
/* expect debouncing on now, this event is ignored */
|
|
||||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
libinput_dispatch(li);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
litest_timeout_debounce();
|
||||||
|
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_LEFT,
|
button,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
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,
|
litest_assert_button_event(li,
|
||||||
BTN_LEFT,
|
button,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_empty_queue(li);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(debounce_timer)
|
START_TEST(debounce_bounce_check_immediate)
|
||||||
{
|
{
|
||||||
struct litest_device *dev = litest_current_device();
|
struct litest_device *dev = litest_current_device();
|
||||||
struct libinput *li = dev->libinput;
|
struct libinput *li = dev->libinput;
|
||||||
|
|
||||||
litest_disable_middleemu(dev);
|
litest_disable_middleemu(dev);
|
||||||
|
disable_button_scrolling(dev);
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
|
/* Press must be sent without delay */
|
||||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
litest_assert_button_event(li,
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
BTN_LEFT,
|
||||||
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
litest_timeout_debounce();
|
||||||
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
|
/* held down & past timeout, we expect releases to be immediate */
|
||||||
|
|
||||||
/* expect debouncing on now, this event is ignored */
|
|
||||||
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_KEY, BTN_LEFT, 0);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
litest_assert_button_event(li,
|
||||||
|
BTN_LEFT,
|
||||||
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
||||||
litest_timeout_debounce();
|
litest_timeout_debounce();
|
||||||
litest_drain_events(li);
|
litest_assert_empty_queue(li);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
/* 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_KEY, BTN_LEFT, 1);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
litest_timeout_debounce();
|
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, 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
|
/* Not all devices can disable middle button emulation, time out on
|
||||||
* middle button here to make sure the initial button press event
|
* middle button here to make sure the initial button press event
|
||||||
* was flushed.
|
* was flushed.
|
||||||
*/
|
*/
|
||||||
libinput_dispatch(li);
|
|
||||||
litest_timeout_middlebutton();
|
litest_timeout_middlebutton();
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_LEFT,
|
button,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
|
||||||
/* bouncy bouncy bouncy */
|
/* 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_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_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
litest_assert_empty_queue(li);
|
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);
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
litest_timeout_debounce();
|
litest_timeout_debounce();
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_LEFT,
|
button,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_empty_queue(li);
|
||||||
|
|
@ -2196,7 +2287,7 @@ START_TEST(debounce_timer)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(debounce_multibounce)
|
START_TEST(debounce_spurious_multibounce)
|
||||||
{
|
{
|
||||||
struct litest_device *dev = litest_current_device();
|
struct litest_device *dev = litest_current_device();
|
||||||
struct libinput *li = dev->libinput;
|
struct libinput *li = dev->libinput;
|
||||||
|
|
@ -2204,15 +2295,7 @@ START_TEST(debounce_multibounce)
|
||||||
litest_disable_middleemu(dev);
|
litest_disable_middleemu(dev);
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
/* enable debouncing */
|
debounce_trigger_spurious(dev, 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);
|
litest_drain_events(li);
|
||||||
|
|
||||||
/* Let's assume our button has ventricular fibrilation and sends a
|
/* Let's assume our button has ventricular fibrilation and sends a
|
||||||
|
|
@ -2223,6 +2306,8 @@ START_TEST(debounce_multibounce)
|
||||||
|
|
||||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
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
|
/* Not all devices can disable middle button emulation, time out on
|
||||||
* middle button here to make sure the initial button press event
|
* middle button here to make sure the initial button press event
|
||||||
|
|
@ -2261,20 +2346,34 @@ START_TEST(debounce_multibounce)
|
||||||
}
|
}
|
||||||
END_TEST
|
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 litest_device *dev = litest_current_device();
|
||||||
|
struct libinput_device *device = dev->libinput_device;
|
||||||
struct libinput *li = dev->libinput;
|
struct libinput *li = dev->libinput;
|
||||||
|
|
||||||
|
if (!libinput_device_config_middle_emulation_is_available(device))
|
||||||
|
return;
|
||||||
|
|
||||||
litest_disable_middleemu(dev);
|
litest_disable_middleemu(dev);
|
||||||
|
disable_button_scrolling(dev);
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
|
/* Don't trigger spurious debouncing on otherbutton events */
|
||||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
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_KEY, BTN_LEFT, 0);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
litest_event(dev, EV_KEY, BTN_RIGHT, 1);
|
litest_event(dev, EV_KEY, BTN_RIGHT, 1);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 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_event(dev, EV_KEY, BTN_RIGHT, 0);
|
litest_event(dev, EV_KEY, BTN_RIGHT, 0);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
|
||||||
|
|
@ -2290,43 +2389,68 @@ START_TEST(debounce_no_debounce_for_otherbutton)
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_RIGHT,
|
BTN_RIGHT,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
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,
|
litest_assert_button_event(li,
|
||||||
BTN_RIGHT,
|
BTN_RIGHT,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
||||||
litest_assert_empty_queue(li);
|
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
|
END_TEST
|
||||||
|
|
||||||
START_TEST(debounce_cancel_debounce_otherbutton)
|
START_TEST(debounce_spurious_cancel_debounce_otherbutton)
|
||||||
{
|
{
|
||||||
struct litest_device *dev = litest_current_device();
|
struct litest_device *dev = litest_current_device();
|
||||||
|
struct libinput_device *device = dev->libinput_device;
|
||||||
struct libinput *li = dev->libinput;
|
struct libinput *li = dev->libinput;
|
||||||
|
|
||||||
|
if (!libinput_device_config_middle_emulation_is_available(device))
|
||||||
|
return;
|
||||||
|
|
||||||
litest_disable_middleemu(dev);
|
litest_disable_middleemu(dev);
|
||||||
|
disable_button_scrolling(dev);
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
debounce_trigger_spurious(dev, li);
|
||||||
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);
|
|
||||||
|
|
||||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
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_KEY, BTN_LEFT, 0);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 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_KEY, BTN_RIGHT, 1);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 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_event(dev, EV_KEY, BTN_RIGHT, 0);
|
litest_event(dev, EV_KEY, BTN_RIGHT, 0);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
|
||||||
|
|
@ -2342,6 +2466,12 @@ START_TEST(debounce_cancel_debounce_otherbutton)
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_RIGHT,
|
BTN_RIGHT,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
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,
|
litest_assert_button_event(li,
|
||||||
BTN_RIGHT,
|
BTN_RIGHT,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
@ -2350,31 +2480,28 @@ START_TEST(debounce_cancel_debounce_otherbutton)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(debounce_switch_to_otherbutton)
|
START_TEST(debounce_spurious_switch_to_otherbutton)
|
||||||
{
|
{
|
||||||
struct litest_device *dev = litest_current_device();
|
struct litest_device *dev = litest_current_device();
|
||||||
|
struct libinput_device *device = dev->libinput_device;
|
||||||
struct libinput *li = dev->libinput;
|
struct libinput *li = dev->libinput;
|
||||||
|
|
||||||
litest_drain_events(li);
|
if (!libinput_device_config_middle_emulation_is_available(device))
|
||||||
|
return;
|
||||||
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);
|
litest_drain_events(li);
|
||||||
|
debounce_trigger_spurious(dev, li);
|
||||||
|
|
||||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
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_KEY, BTN_LEFT, 0);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
/* release is now held back,
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
|
||||||
/* release is now held back, press was ignored,
|
|
||||||
* other button should flush the release */
|
* other button should flush the release */
|
||||||
litest_event(dev, EV_KEY, BTN_RIGHT, 1);
|
litest_event(dev, EV_KEY, BTN_RIGHT, 1);
|
||||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
|
@ -2412,6 +2539,7 @@ litest_setup_tests_pointer(void)
|
||||||
{
|
{
|
||||||
struct range axis_range = {ABS_X, ABS_Y + 1};
|
struct range axis_range = {ABS_X, ABS_Y + 1};
|
||||||
struct range compass = {0, 7}; /* cardinal directions */
|
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("pointer:motion", pointer_motion_relative, LITEST_RELATIVE, LITEST_POINTINGSTICK);
|
||||||
litest_add_for_device("pointer:motion", pointer_motion_relative_zero, LITEST_MOUSE);
|
litest_add_for_device("pointer:motion", pointer_motion_relative_zero, LITEST_MOUSE);
|
||||||
|
|
@ -2474,10 +2602,11 @@ litest_setup_tests_pointer(void)
|
||||||
|
|
||||||
litest_add("pointer:time", pointer_time_usec, LITEST_RELATIVE, LITEST_ANY);
|
litest_add("pointer:time", pointer_time_usec, LITEST_RELATIVE, LITEST_ANY);
|
||||||
|
|
||||||
litest_add("pointer:debounce", debounce, LITEST_BUTTON, LITEST_TOUCHPAD);
|
litest_add_ranged("pointer:debounce", debounce_bounce, LITEST_BUTTON, LITEST_TOUCHPAD, &buttons);
|
||||||
litest_add("pointer:debounce", debounce_timer, LITEST_BUTTON, LITEST_TOUCHPAD);
|
litest_add("pointer:debounce", debounce_bounce_check_immediate, LITEST_BUTTON, LITEST_TOUCHPAD);
|
||||||
litest_add("pointer:debounce", debounce_multibounce, LITEST_BUTTON, LITEST_TOUCHPAD);
|
litest_add_ranged("pointer:debounce", debounce_spurious, LITEST_BUTTON, LITEST_TOUCHPAD, &buttons);
|
||||||
litest_add("pointer:debounce_otherbutton", debounce_no_debounce_for_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD);
|
litest_add("pointer:debounce", debounce_spurious_multibounce, LITEST_BUTTON, LITEST_TOUCHPAD);
|
||||||
litest_add("pointer:debounce_otherbutton", debounce_cancel_debounce_otherbutton, 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_switch_to_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_touch_move_to(dev, 0, 48, 48, 50, 50, 10, 1);
|
||||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
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_drain_events(li);
|
||||||
|
|
||||||
litest_touch_move_to(dev, 0, 50, 50, 50 + dist, 50 + dist, 10, 1);
|
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_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);
|
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
|
||||||
|
|
||||||
/* still pinned after release */
|
/* 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_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);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
|
|
@ -1498,7 +1498,7 @@ START_TEST(clickpad_softbutton_hover_into_buttons)
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
litest_assert_empty_queue(li);
|
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, 0);
|
||||||
|
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
|
|
|
||||||
|
|
@ -332,8 +332,8 @@ START_TEST(touchpad_1fg_multitap_n_drag_click)
|
||||||
|
|
||||||
litest_touch_down(dev, 0, 50, 50);
|
litest_touch_down(dev, 0, 50, 50);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
litest_button_click(dev, BTN_LEFT, true);
|
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||||
litest_button_click(dev, BTN_LEFT, false);
|
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
for (ntaps = 0; ntaps <= range; ntaps++) {
|
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_up(dev, 0);
|
||||||
litest_touch_down(dev, 0, 70, 50);
|
litest_touch_down(dev, 0, 70, 50);
|
||||||
litest_button_click(dev, BTN_LEFT, true);
|
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||||
litest_button_click(dev, BTN_LEFT, false);
|
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
litest_assert_button_event(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_up(dev, 0);
|
||||||
litest_touch_down(dev, 0, 50, 50);
|
litest_touch_down(dev, 0, 50, 50);
|
||||||
litest_button_click(dev, BTN_LEFT, true);
|
litest_button_click_debounced(dev, li, BTN_LEFT, true);
|
||||||
litest_button_click(dev, BTN_LEFT, false);
|
litest_button_click_debounced(dev, li, BTN_LEFT, false);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
litest_assert_button_event(li, BTN_LEFT,
|
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_touch_move_to(dev, 0, 20, 95, 70, 95, 10, 5);
|
||||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
|
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);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
event = libinput_get_event(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_touch_move_to(dev, 0, 70, 95, 90, 95, 10, 0);
|
||||||
litest_assert_empty_queue(li);
|
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);
|
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_touch_move_to(dev, 0, 20, 95, 70, 95, 10, 5);
|
||||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
|
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);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
event = libinput_get_event(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_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||||
litest_assert_empty_queue(li);
|
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);
|
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);
|
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||||
|
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_button_click(dev, BTN_LEFT, 1);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||||
litest_button_click(dev, BTN_LEFT, 0);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||||
|
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_RIGHT,
|
BTN_RIGHT,
|
||||||
|
|
@ -1727,8 +1727,8 @@ START_TEST(touchpad_left_handed)
|
||||||
BTN_RIGHT,
|
BTN_RIGHT,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
||||||
litest_button_click(dev, BTN_RIGHT, 1);
|
litest_button_click_debounced(dev, li, BTN_RIGHT, 1);
|
||||||
litest_button_click(dev, BTN_RIGHT, 0);
|
litest_button_click_debounced(dev, li, BTN_RIGHT, 0);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_LEFT,
|
BTN_LEFT,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
|
@ -1739,8 +1739,8 @@ START_TEST(touchpad_left_handed)
|
||||||
if (libevdev_has_event_code(dev->evdev,
|
if (libevdev_has_event_code(dev->evdev,
|
||||||
EV_KEY,
|
EV_KEY,
|
||||||
BTN_MIDDLE)) {
|
BTN_MIDDLE)) {
|
||||||
litest_button_click(dev, BTN_MIDDLE, 1);
|
litest_button_click_debounced(dev, li, BTN_MIDDLE, 1);
|
||||||
litest_button_click(dev, BTN_MIDDLE, 0);
|
litest_button_click_debounced(dev, li, BTN_MIDDLE, 0);
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
|
@ -1779,8 +1779,8 @@ START_TEST(touchpad_left_handed_clickpad)
|
||||||
|
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_touch_down(dev, 0, 10, 90);
|
litest_touch_down(dev, 0, 10, 90);
|
||||||
litest_button_click(dev, BTN_LEFT, 1);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||||
litest_button_click(dev, BTN_LEFT, 0);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||||
litest_touch_up(dev, 0);
|
litest_touch_up(dev, 0);
|
||||||
|
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
|
|
@ -1792,8 +1792,8 @@ START_TEST(touchpad_left_handed_clickpad)
|
||||||
|
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_touch_down(dev, 0, 90, 90);
|
litest_touch_down(dev, 0, 90, 90);
|
||||||
litest_button_click(dev, BTN_LEFT, 1);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||||
litest_button_click(dev, BTN_LEFT, 0);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||||
litest_touch_up(dev, 0);
|
litest_touch_up(dev, 0);
|
||||||
|
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
|
|
@ -1805,8 +1805,8 @@ START_TEST(touchpad_left_handed_clickpad)
|
||||||
|
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_touch_down(dev, 0, 50, 50);
|
litest_touch_down(dev, 0, 50, 50);
|
||||||
litest_button_click(dev, BTN_LEFT, 1);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||||
litest_button_click(dev, BTN_LEFT, 0);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||||
litest_touch_up(dev, 0);
|
litest_touch_up(dev, 0);
|
||||||
|
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
|
|
@ -1833,8 +1833,8 @@ START_TEST(touchpad_left_handed_clickfinger)
|
||||||
|
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_touch_down(dev, 0, 10, 90);
|
litest_touch_down(dev, 0, 10, 90);
|
||||||
litest_button_click(dev, BTN_LEFT, 1);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||||
litest_button_click(dev, BTN_LEFT, 0);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||||
litest_touch_up(dev, 0);
|
litest_touch_up(dev, 0);
|
||||||
|
|
||||||
/* Clickfinger is unaffected by left-handed setting */
|
/* Clickfinger is unaffected by left-handed setting */
|
||||||
|
|
@ -1848,8 +1848,8 @@ START_TEST(touchpad_left_handed_clickfinger)
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_touch_down(dev, 0, 10, 90);
|
litest_touch_down(dev, 0, 10, 90);
|
||||||
litest_touch_down(dev, 1, 30, 90);
|
litest_touch_down(dev, 1, 30, 90);
|
||||||
litest_button_click(dev, BTN_LEFT, 1);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||||
litest_button_click(dev, BTN_LEFT, 0);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||||
litest_touch_up(dev, 0);
|
litest_touch_up(dev, 0);
|
||||||
litest_touch_up(dev, 1);
|
litest_touch_up(dev, 1);
|
||||||
|
|
||||||
|
|
@ -1943,13 +1943,13 @@ START_TEST(touchpad_left_handed_delayed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_button_click(dev, BTN_LEFT, 1);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
status = libinput_device_config_left_handed_set(d, 1);
|
status = libinput_device_config_left_handed_set(d, 1);
|
||||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
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,
|
litest_assert_button_event(li,
|
||||||
BTN_LEFT,
|
BTN_LEFT,
|
||||||
|
|
@ -1959,18 +1959,18 @@ START_TEST(touchpad_left_handed_delayed)
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
||||||
/* left-handed takes effect now */
|
/* left-handed takes effect now */
|
||||||
litest_button_click(dev, BTN_RIGHT, 1);
|
litest_button_click_debounced(dev, li, BTN_RIGHT, 1);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
litest_timeout_middlebutton();
|
litest_timeout_middlebutton();
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
litest_button_click(dev, BTN_LEFT, 1);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 1);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
status = libinput_device_config_left_handed_set(d, 0);
|
status = libinput_device_config_left_handed_set(d, 0);
|
||||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||||
|
|
||||||
litest_button_click(dev, BTN_RIGHT, 0);
|
litest_button_click_debounced(dev, li, BTN_RIGHT, 0);
|
||||||
litest_button_click(dev, BTN_LEFT, 0);
|
litest_button_click_debounced(dev, li, BTN_LEFT, 0);
|
||||||
|
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
BTN_LEFT,
|
BTN_LEFT,
|
||||||
|
|
@ -1999,13 +1999,13 @@ START_TEST(touchpad_left_handed_clickpad_delayed)
|
||||||
|
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_touch_down(dev, 0, 10, 90);
|
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);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
status = libinput_device_config_left_handed_set(d, 1);
|
status = libinput_device_config_left_handed_set(d, 1);
|
||||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
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_touch_up(dev, 0);
|
||||||
|
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
|
|
@ -2018,13 +2018,13 @@ START_TEST(touchpad_left_handed_clickpad_delayed)
|
||||||
/* left-handed takes effect now */
|
/* left-handed takes effect now */
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_touch_down(dev, 0, 90, 90);
|
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);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
status = libinput_device_config_left_handed_set(d, 0);
|
status = libinput_device_config_left_handed_set(d, 0);
|
||||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
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_touch_up(dev, 0);
|
||||||
|
|
||||||
litest_assert_button_event(li,
|
litest_assert_button_event(li,
|
||||||
|
|
@ -2657,12 +2657,12 @@ START_TEST(touchpad_trackpoint_buttons)
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
ARRAY_FOR_EACH(buttons, b) {
|
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,
|
assert_btnevent_from_device(trackpoint,
|
||||||
b->real_value,
|
b->real_value,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
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,
|
assert_btnevent_from_device(trackpoint,
|
||||||
b->real_value,
|
b->real_value,
|
||||||
|
|
@ -2683,7 +2683,7 @@ START_TEST(touchpad_trackpoint_mb_scroll)
|
||||||
LITEST_TRACKPOINT);
|
LITEST_TRACKPOINT);
|
||||||
|
|
||||||
litest_drain_events(li);
|
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);
|
libinput_dispatch(li);
|
||||||
litest_timeout_buttonscroll();
|
litest_timeout_buttonscroll();
|
||||||
libinput_dispatch(li);
|
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_SYN, SYN_REPORT, 0);
|
||||||
litest_event(trackpoint, EV_REL, REL_Y, -2);
|
litest_event(trackpoint, EV_REL, REL_Y, -2);
|
||||||
litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
|
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);
|
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);
|
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||||
|
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_button_click(touchpad, BTN_2, true); /* middle */
|
litest_button_click_debounced(touchpad, li, BTN_2, true); /* middle */
|
||||||
litest_button_click(touchpad, BTN_2, false);
|
litest_button_click_debounced(touchpad, li, BTN_2, false);
|
||||||
|
|
||||||
assert_btnevent_from_device(trackpoint,
|
assert_btnevent_from_device(trackpoint,
|
||||||
BTN_MIDDLE,
|
BTN_MIDDLE,
|
||||||
|
|
@ -2743,11 +2743,11 @@ START_TEST(touchpad_trackpoint_buttons_softbuttons)
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
litest_touch_down(touchpad, 0, 95, 90);
|
litest_touch_down(touchpad, 0, 95, 90);
|
||||||
litest_button_click(touchpad, BTN_LEFT, true);
|
litest_button_click_debounced(touchpad, li, BTN_LEFT, true);
|
||||||
litest_button_click(touchpad, BTN_1, true);
|
litest_button_click_debounced(touchpad, li, BTN_1, true);
|
||||||
litest_button_click(touchpad, BTN_LEFT, false);
|
litest_button_click_debounced(touchpad, li, BTN_LEFT, false);
|
||||||
litest_touch_up(touchpad, 0);
|
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,
|
assert_btnevent_from_device(touchpad,
|
||||||
BTN_RIGHT,
|
BTN_RIGHT,
|
||||||
|
|
@ -2763,10 +2763,10 @@ START_TEST(touchpad_trackpoint_buttons_softbuttons)
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
||||||
litest_touch_down(touchpad, 0, 95, 90);
|
litest_touch_down(touchpad, 0, 95, 90);
|
||||||
litest_button_click(touchpad, BTN_LEFT, true);
|
litest_button_click_debounced(touchpad, li, BTN_LEFT, true);
|
||||||
litest_button_click(touchpad, BTN_1, true);
|
litest_button_click_debounced(touchpad, li, BTN_1, true);
|
||||||
litest_button_click(touchpad, BTN_1, false);
|
litest_button_click_debounced(touchpad, li, BTN_1, false);
|
||||||
litest_button_click(touchpad, BTN_LEFT, false);
|
litest_button_click_debounced(touchpad, li, BTN_LEFT, false);
|
||||||
litest_touch_up(touchpad, 0);
|
litest_touch_up(touchpad, 0);
|
||||||
|
|
||||||
assert_btnevent_from_device(touchpad,
|
assert_btnevent_from_device(touchpad,
|
||||||
|
|
@ -2818,7 +2818,7 @@ START_TEST(touchpad_trackpoint_buttons_2fg_scroll)
|
||||||
libinput_event_destroy(e);
|
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,
|
assert_btnevent_from_device(trackpoint,
|
||||||
BTN_RIGHT,
|
BTN_RIGHT,
|
||||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
|
@ -2838,7 +2838,7 @@ START_TEST(touchpad_trackpoint_buttons_2fg_scroll)
|
||||||
libinput_event_destroy(e);
|
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,
|
assert_btnevent_from_device(trackpoint,
|
||||||
BTN_RIGHT,
|
BTN_RIGHT,
|
||||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
@ -2874,16 +2874,16 @@ START_TEST(touchpad_trackpoint_no_trackpoint)
|
||||||
struct libinput *li = touchpad->libinput;
|
struct libinput *li = touchpad->libinput;
|
||||||
|
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
litest_button_click(touchpad, BTN_0, true); /* left */
|
litest_button_click_debounced(touchpad, li, BTN_0, true); /* left */
|
||||||
litest_button_click(touchpad, BTN_0, false);
|
litest_button_click_debounced(touchpad, li, BTN_0, false);
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
litest_button_click(touchpad, BTN_1, true); /* right */
|
litest_button_click_debounced(touchpad, li, BTN_1, true); /* right */
|
||||||
litest_button_click(touchpad, BTN_1, false);
|
litest_button_click_debounced(touchpad, li, BTN_1, false);
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
litest_button_click(touchpad, BTN_2, true); /* middle */
|
litest_button_click_debounced(touchpad, li, BTN_2, true); /* middle */
|
||||||
litest_button_click(touchpad, BTN_2, false);
|
litest_button_click_debounced(touchpad, li, BTN_2, false);
|
||||||
litest_assert_empty_queue(li);
|
litest_assert_empty_queue(li);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
@ -3679,8 +3679,8 @@ START_TEST(touchpad_dwt_click)
|
||||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
|
litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
|
||||||
|
|
||||||
litest_touch_down(touchpad, 0, 50, 50);
|
litest_touch_down(touchpad, 0, 50, 50);
|
||||||
litest_button_click(touchpad, BTN_LEFT, true);
|
litest_button_click_debounced(touchpad, li, BTN_LEFT, true);
|
||||||
litest_button_click(touchpad, BTN_LEFT, false);
|
litest_button_click_debounced(touchpad, li, BTN_LEFT, false);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
litest_touch_up(touchpad, 0);
|
litest_touch_up(touchpad, 0);
|
||||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
|
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
|
||||||
|
|
@ -4232,6 +4232,152 @@ START_TEST(touchpad_dwt_acer_hawaii)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(touchpad_dwt_multiple_keyboards)
|
||||||
|
{
|
||||||
|
struct litest_device *touchpad = litest_current_device();
|
||||||
|
struct litest_device *k1, *k2;
|
||||||
|
struct libinput *li = touchpad->libinput;
|
||||||
|
|
||||||
|
ck_assert(has_disable_while_typing(touchpad));
|
||||||
|
|
||||||
|
enable_dwt(touchpad);
|
||||||
|
|
||||||
|
k1 = litest_add_device(li, LITEST_KEYBOARD);
|
||||||
|
k2 = litest_add_device(li, LITEST_KEYBOARD);
|
||||||
|
|
||||||
|
litest_keyboard_key(k1, KEY_A, true);
|
||||||
|
litest_keyboard_key(k1, KEY_A, false);
|
||||||
|
litest_drain_events(li);
|
||||||
|
|
||||||
|
litest_touch_down(touchpad, 0, 50, 50);
|
||||||
|
litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
|
||||||
|
litest_touch_up(touchpad, 0);
|
||||||
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
|
litest_timeout_dwt_short();
|
||||||
|
|
||||||
|
litest_keyboard_key(k2, KEY_A, true);
|
||||||
|
litest_keyboard_key(k2, KEY_A, false);
|
||||||
|
litest_drain_events(li);
|
||||||
|
|
||||||
|
litest_touch_down(touchpad, 0, 50, 50);
|
||||||
|
litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
|
||||||
|
litest_touch_up(touchpad, 0);
|
||||||
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
|
litest_timeout_dwt_short();
|
||||||
|
|
||||||
|
litest_delete_device(k1);
|
||||||
|
litest_delete_device(k2);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(touchpad_dwt_multiple_keyboards_bothkeys)
|
||||||
|
{
|
||||||
|
struct litest_device *touchpad = litest_current_device();
|
||||||
|
struct litest_device *k1, *k2;
|
||||||
|
struct libinput *li = touchpad->libinput;
|
||||||
|
|
||||||
|
ck_assert(has_disable_while_typing(touchpad));
|
||||||
|
|
||||||
|
enable_dwt(touchpad);
|
||||||
|
|
||||||
|
k1 = litest_add_device(li, LITEST_KEYBOARD);
|
||||||
|
k2 = litest_add_device(li, LITEST_KEYBOARD);
|
||||||
|
|
||||||
|
litest_keyboard_key(k1, KEY_A, true);
|
||||||
|
litest_keyboard_key(k1, KEY_A, false);
|
||||||
|
litest_keyboard_key(k2, KEY_B, true);
|
||||||
|
litest_keyboard_key(k2, KEY_B, false);
|
||||||
|
litest_drain_events(li);
|
||||||
|
|
||||||
|
litest_touch_down(touchpad, 0, 50, 50);
|
||||||
|
litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
|
||||||
|
litest_touch_up(touchpad, 0);
|
||||||
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
|
litest_delete_device(k1);
|
||||||
|
litest_delete_device(k2);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(touchpad_dwt_multiple_keyboards_bothkeys_modifier)
|
||||||
|
{
|
||||||
|
struct litest_device *touchpad = litest_current_device();
|
||||||
|
struct litest_device *k1, *k2;
|
||||||
|
struct libinput *li = touchpad->libinput;
|
||||||
|
|
||||||
|
ck_assert(has_disable_while_typing(touchpad));
|
||||||
|
|
||||||
|
enable_dwt(touchpad);
|
||||||
|
|
||||||
|
k1 = litest_add_device(li, LITEST_KEYBOARD);
|
||||||
|
k2 = litest_add_device(li, LITEST_KEYBOARD);
|
||||||
|
|
||||||
|
litest_keyboard_key(k1, KEY_RIGHTCTRL, true);
|
||||||
|
litest_keyboard_key(k1, KEY_RIGHTCTRL, false);
|
||||||
|
litest_keyboard_key(k2, KEY_B, true);
|
||||||
|
litest_keyboard_key(k2, KEY_B, false);
|
||||||
|
litest_drain_events(li);
|
||||||
|
|
||||||
|
/* If the keyboard is a single physical device, the above should
|
||||||
|
* trigger the modifier behavior for dwt. But libinput views it as
|
||||||
|
* two separate devices and this is such a niche case that it
|
||||||
|
* doesn't matter. So we test for the easy behavior:
|
||||||
|
* ctrl+B across two devices is *not* a dwt modifier combo
|
||||||
|
*/
|
||||||
|
litest_touch_down(touchpad, 0, 50, 50);
|
||||||
|
litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
|
||||||
|
litest_touch_up(touchpad, 0);
|
||||||
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
|
litest_delete_device(k1);
|
||||||
|
litest_delete_device(k2);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(touchpad_dwt_multiple_keyboards_remove)
|
||||||
|
{
|
||||||
|
struct litest_device *touchpad = litest_current_device();
|
||||||
|
struct litest_device *keyboards[2];
|
||||||
|
struct libinput *li = touchpad->libinput;
|
||||||
|
int which = _i; /* ranged test */
|
||||||
|
struct litest_device *removed, *remained;
|
||||||
|
|
||||||
|
ck_assert_int_le(which, 1);
|
||||||
|
|
||||||
|
ck_assert(has_disable_while_typing(touchpad));
|
||||||
|
|
||||||
|
enable_dwt(touchpad);
|
||||||
|
|
||||||
|
keyboards[0] = litest_add_device(li, LITEST_KEYBOARD);
|
||||||
|
keyboards[1] = litest_add_device(li, LITEST_KEYBOARD);
|
||||||
|
|
||||||
|
litest_keyboard_key(keyboards[0], KEY_A, true);
|
||||||
|
litest_keyboard_key(keyboards[0], KEY_A, false);
|
||||||
|
litest_keyboard_key(keyboards[1], KEY_B, true);
|
||||||
|
litest_keyboard_key(keyboards[1], KEY_B, false);
|
||||||
|
litest_drain_events(li);
|
||||||
|
|
||||||
|
litest_timeout_dwt_short();
|
||||||
|
|
||||||
|
removed = keyboards[which % 2];
|
||||||
|
remained = keyboards[(which + 1) % 2];
|
||||||
|
|
||||||
|
litest_delete_device(removed);
|
||||||
|
litest_keyboard_key(remained, KEY_C, true);
|
||||||
|
litest_keyboard_key(remained, KEY_C, false);
|
||||||
|
litest_drain_events(li);
|
||||||
|
|
||||||
|
litest_touch_down(touchpad, 0, 50, 50);
|
||||||
|
litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
|
||||||
|
litest_touch_up(touchpad, 0);
|
||||||
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
|
litest_delete_device(remained);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
static int
|
static int
|
||||||
has_thumb_detect(struct litest_device *dev)
|
has_thumb_detect(struct litest_device *dev)
|
||||||
{
|
{
|
||||||
|
|
@ -4346,7 +4492,7 @@ START_TEST(touchpad_thumb_clickfinger)
|
||||||
litest_touch_down(dev, 0, 50, 99);
|
litest_touch_down(dev, 0, 50, 99);
|
||||||
litest_touch_down(dev, 1, 60, 99);
|
litest_touch_down(dev, 1, 60, 99);
|
||||||
litest_touch_move_extended(dev, 0, 55, 99, axes);
|
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);
|
libinput_dispatch(li);
|
||||||
event = libinput_get_event(li);
|
event = libinput_get_event(li);
|
||||||
|
|
@ -4357,7 +4503,7 @@ START_TEST(touchpad_thumb_clickfinger)
|
||||||
|
|
||||||
litest_assert_empty_queue(li);
|
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, 0);
|
||||||
litest_touch_up(dev, 1);
|
litest_touch_up(dev, 1);
|
||||||
|
|
||||||
|
|
@ -4366,7 +4512,7 @@ START_TEST(touchpad_thumb_clickfinger)
|
||||||
litest_touch_down(dev, 0, 50, 99);
|
litest_touch_down(dev, 0, 50, 99);
|
||||||
litest_touch_down(dev, 1, 60, 99);
|
litest_touch_down(dev, 1, 60, 99);
|
||||||
litest_touch_move_extended(dev, 1, 65, 99, axes);
|
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);
|
libinput_dispatch(li);
|
||||||
event = libinput_get_event(li);
|
event = libinput_get_event(li);
|
||||||
|
|
@ -4401,7 +4547,7 @@ START_TEST(touchpad_thumb_btnarea)
|
||||||
|
|
||||||
litest_touch_down(dev, 0, 90, 99);
|
litest_touch_down(dev, 0, 90, 99);
|
||||||
litest_touch_move_extended(dev, 0, 95, 99, axes);
|
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 */
|
/* button areas work as usual with a thumb */
|
||||||
|
|
||||||
|
|
@ -5493,6 +5639,7 @@ void
|
||||||
litest_setup_tests_touchpad(void)
|
litest_setup_tests_touchpad(void)
|
||||||
{
|
{
|
||||||
struct range axis_range = {ABS_X, ABS_Y + 1};
|
struct range axis_range = {ABS_X, ABS_Y + 1};
|
||||||
|
struct range twice = {0, 2 };
|
||||||
|
|
||||||
litest_add("touchpad:motion", touchpad_1fg_motion, LITEST_TOUCHPAD, LITEST_ANY);
|
litest_add("touchpad:motion", touchpad_1fg_motion, LITEST_TOUCHPAD, LITEST_ANY);
|
||||||
litest_add("touchpad:motion", touchpad_2fg_no_motion, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
litest_add("touchpad:motion", touchpad_2fg_no_motion, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||||
|
|
@ -5620,6 +5767,10 @@ litest_setup_tests_touchpad(void)
|
||||||
litest_add("touchpad:dwt", touchpad_dwt_remove_kbd_while_active, LITEST_TOUCHPAD, LITEST_ANY);
|
litest_add("touchpad:dwt", touchpad_dwt_remove_kbd_while_active, LITEST_TOUCHPAD, LITEST_ANY);
|
||||||
litest_add_for_device("touchpad:dwt", touchpad_dwt_apple, LITEST_BCM5974);
|
litest_add_for_device("touchpad:dwt", touchpad_dwt_apple, LITEST_BCM5974);
|
||||||
litest_add_for_device("touchpad:dwt", touchpad_dwt_acer_hawaii, LITEST_ACER_HAWAII_TOUCHPAD);
|
litest_add_for_device("touchpad:dwt", touchpad_dwt_acer_hawaii, LITEST_ACER_HAWAII_TOUCHPAD);
|
||||||
|
litest_add_for_device("touchpad:dwt", touchpad_dwt_multiple_keyboards, LITEST_SYNAPTICS_I2C);
|
||||||
|
litest_add_for_device("touchpad:dwt", touchpad_dwt_multiple_keyboards_bothkeys, LITEST_SYNAPTICS_I2C);
|
||||||
|
litest_add_for_device("touchpad:dwt", touchpad_dwt_multiple_keyboards_bothkeys_modifier, LITEST_SYNAPTICS_I2C);
|
||||||
|
litest_add_ranged_for_device("touchpad:dwt", touchpad_dwt_multiple_keyboards_remove, LITEST_SYNAPTICS_I2C, &twice);
|
||||||
|
|
||||||
litest_add("touchpad:thumb", touchpad_thumb_begin_no_motion, LITEST_CLICKPAD, LITEST_ANY);
|
litest_add("touchpad:thumb", touchpad_thumb_begin_no_motion, LITEST_CLICKPAD, LITEST_ANY);
|
||||||
litest_add("touchpad:thumb", touchpad_thumb_update_no_motion, LITEST_CLICKPAD, LITEST_ANY);
|
litest_add("touchpad:thumb", touchpad_thumb_update_no_motion, LITEST_CLICKPAD, LITEST_ANY);
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,9 @@ START_TEST(trackpoint_middlebutton)
|
||||||
litest_drain_events(li);
|
litest_drain_events(li);
|
||||||
|
|
||||||
/* A quick middle button click should get reported normally */
|
/* 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);
|
msleep(2);
|
||||||
litest_button_click(dev, BTN_MIDDLE, 0);
|
litest_button_click_debounced(dev, li, BTN_MIDDLE, 0);
|
||||||
|
|
||||||
litest_wait_for_event(li);
|
litest_wait_for_event(li);
|
||||||
|
|
||||||
|
|
@ -173,7 +173,7 @@ START_TEST(trackpoint_topsoftbuttons_left_handed_trackpoint)
|
||||||
|
|
||||||
litest_touch_down(touchpad, 0, 5, 5);
|
litest_touch_down(touchpad, 0, 5, 5);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
litest_button_click(touchpad, BTN_LEFT, true);
|
litest_button_click_debounced(touchpad, li, BTN_LEFT, true);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
event = libinput_get_event(li);
|
event = libinput_get_event(li);
|
||||||
|
|
@ -184,7 +184,7 @@ START_TEST(trackpoint_topsoftbuttons_left_handed_trackpoint)
|
||||||
ck_assert(device == trackpoint->libinput_device);
|
ck_assert(device == trackpoint->libinput_device);
|
||||||
libinput_event_destroy(event);
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
litest_button_click(touchpad, BTN_LEFT, false);
|
litest_button_click_debounced(touchpad, li, BTN_LEFT, false);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
event = libinput_get_event(li);
|
event = libinput_get_event(li);
|
||||||
litest_is_button_event(event,
|
litest_is_button_event(event,
|
||||||
|
|
@ -216,7 +216,7 @@ START_TEST(trackpoint_topsoftbuttons_left_handed_touchpad)
|
||||||
|
|
||||||
litest_touch_down(touchpad, 0, 5, 5);
|
litest_touch_down(touchpad, 0, 5, 5);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
litest_button_click(touchpad, BTN_LEFT, true);
|
litest_button_click_debounced(touchpad, li, BTN_LEFT, true);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
event = libinput_get_event(li);
|
event = libinput_get_event(li);
|
||||||
|
|
@ -225,7 +225,7 @@ START_TEST(trackpoint_topsoftbuttons_left_handed_touchpad)
|
||||||
ck_assert(device == trackpoint->libinput_device);
|
ck_assert(device == trackpoint->libinput_device);
|
||||||
libinput_event_destroy(event);
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
litest_button_click(touchpad, BTN_LEFT, false);
|
litest_button_click_debounced(touchpad, li, BTN_LEFT, false);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
event = libinput_get_event(li);
|
event = libinput_get_event(li);
|
||||||
litest_is_button_event(event,
|
litest_is_button_event(event,
|
||||||
|
|
@ -260,7 +260,7 @@ START_TEST(trackpoint_topsoftbuttons_left_handed_both)
|
||||||
|
|
||||||
litest_touch_down(touchpad, 0, 5, 5);
|
litest_touch_down(touchpad, 0, 5, 5);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
litest_button_click(touchpad, BTN_LEFT, true);
|
litest_button_click_debounced(touchpad, li, BTN_LEFT, true);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
|
|
||||||
event = libinput_get_event(li);
|
event = libinput_get_event(li);
|
||||||
|
|
@ -271,7 +271,7 @@ START_TEST(trackpoint_topsoftbuttons_left_handed_both)
|
||||||
ck_assert(device == trackpoint->libinput_device);
|
ck_assert(device == trackpoint->libinput_device);
|
||||||
libinput_event_destroy(event);
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
litest_button_click(touchpad, BTN_LEFT, false);
|
litest_button_click_debounced(touchpad, li, BTN_LEFT, false);
|
||||||
libinput_dispatch(li);
|
libinput_dispatch(li);
|
||||||
event = libinput_get_event(li);
|
event = libinput_get_event(li);
|
||||||
litest_is_button_event(event,
|
litest_is_button_event(event,
|
||||||
|
|
|
||||||
|
|
@ -747,6 +747,9 @@ print_switch_event(struct libinput_event *ev)
|
||||||
case LIBINPUT_SWITCH_LID:
|
case LIBINPUT_SWITCH_LID:
|
||||||
which = "lid";
|
which = "lid";
|
||||||
break;
|
break;
|
||||||
|
case LIBINPUT_SWITCH_TABLET_MODE:
|
||||||
|
which = "tablet-mode";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,9 @@ Enable or disable natural scrolling
|
||||||
.B \-\-enable\-left\-handed|\-\-disable\-left\-handed
|
.B \-\-enable\-left\-handed|\-\-disable\-left\-handed
|
||||||
Enable or disable left handed button configuration
|
Enable or disable left handed button configuration
|
||||||
.TP 8
|
.TP 8
|
||||||
|
.B \-\-enable\-middlebutton|\-\-disable\-middlebutton
|
||||||
|
Enable or disable middle button emulation
|
||||||
|
.TP 8
|
||||||
.B \-\-enable\-dwt|\-\-disable\-dwt
|
.B \-\-enable\-dwt|\-\-disable\-dwt
|
||||||
Enable or disable disable-while-typing
|
Enable or disable disable-while-typing
|
||||||
.TP 8
|
.TP 8
|
||||||
|
|
|
||||||
|
|
@ -314,6 +314,12 @@ print_device_notify(struct libinput_event *ev)
|
||||||
if (libinput_device_has_capability(dev,
|
if (libinput_device_has_capability(dev,
|
||||||
LIBINPUT_DEVICE_CAP_TABLET_PAD))
|
LIBINPUT_DEVICE_CAP_TABLET_PAD))
|
||||||
printf("tablet-pad");
|
printf("tablet-pad");
|
||||||
|
if (libinput_device_has_capability(dev,
|
||||||
|
LIBINPUT_DEVICE_CAP_GESTURE))
|
||||||
|
printf("gesture");
|
||||||
|
if (libinput_device_has_capability(dev,
|
||||||
|
LIBINPUT_DEVICE_CAP_SWITCH))
|
||||||
|
printf("switch");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
printf("Tap-to-click: %s\n", tap_default(dev));
|
printf("Tap-to-click: %s\n", tap_default(dev));
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,15 @@
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
|
try:
|
||||||
import evdev
|
import evdev
|
||||||
import evdev.ecodes
|
import evdev.ecodes
|
||||||
import pyudev
|
import pyudev
|
||||||
|
except ModuleNotFoundError as e:
|
||||||
|
print('Error: {}'.format(str(e)), file=sys.stderr)
|
||||||
|
print('One or more python modules are missing. Please install those '
|
||||||
|
'modules and re-run this tool.')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
class Range(object):
|
class Range(object):
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ libinput\-measure\-touch-size \- measure touch size and orientation of devices
|
||||||
The
|
The
|
||||||
.B "libinput measure touch\-size"
|
.B "libinput measure touch\-size"
|
||||||
tool measures the size and orientation of a touch as provided by the kernel.
|
tool measures the size and orientation of a touch as provided by the kernel.
|
||||||
an interactive tool. When executed, the tool will prompt the user to
|
This is an interactive tool. When executed, the tool will prompt the user to
|
||||||
interact with the touch device. On termination, the tool prints a summary of the
|
interact with the touch device. On termination, the tool prints a summary of the
|
||||||
values seen. This data should be attached to any
|
values seen. This data should be attached to any
|
||||||
touch\-size\-related bug report.
|
touch\-size\-related bug report.
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,15 @@
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
|
try:
|
||||||
import evdev
|
import evdev
|
||||||
import evdev.ecodes
|
import evdev.ecodes
|
||||||
import pyudev
|
import pyudev
|
||||||
|
except ModuleNotFoundError as e:
|
||||||
|
print('Error: {}'.format(str(e)), file=sys.stderr)
|
||||||
|
print('One or more python modules are missing. Please install those '
|
||||||
|
'modules and re-run this tool.')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
class Range(object):
|
class Range(object):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
.TH libinput-measure-touchpad-tap "1" "" "libinput @LIBINPUT_VERSION@" "libinput Manual"
|
.TH libinput-measure-touchpad-tap "1" "" "libinput @LIBINPUT_VERSION@" "libinput Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
libinput\-measure\-touchpad\-tap \- measure tap-to-click properities of devices
|
libinput\-measure\-touchpad\-tap \- measure tap-to-click properties of devices
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B libinput measure touchpad\-tap [\-\-help] [\-\-format=\fI<format>\fB] \fI[/dev/input/event0]\fR
|
.B libinput measure touchpad\-tap [\-\-help] [\-\-format=\fI<format>\fB] \fI[/dev/input/event0]\fR
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,15 @@
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
|
try:
|
||||||
import evdev
|
import evdev
|
||||||
import evdev.ecodes
|
import evdev.ecodes
|
||||||
import pyudev
|
import pyudev
|
||||||
|
except ModuleNotFoundError as e:
|
||||||
|
print('Error: {}'.format(str(e)), file=sys.stderr)
|
||||||
|
print('One or more python modules are missing. Please install those '
|
||||||
|
'modules and re-run this tool.')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
MINIMUM_EVENT_COUNT = 1000
|
MINIMUM_EVENT_COUNT = 1000
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ Measure tap-to-click time
|
||||||
.B libinput\-measure\-touchpad\-pressure(1)
|
.B libinput\-measure\-touchpad\-pressure(1)
|
||||||
Measure touch pressure
|
Measure touch pressure
|
||||||
.TP 8
|
.TP 8
|
||||||
.B libinput-measure-trackpoint-range(1)
|
.B libinput\-measure\-trackpoint\-range(1)
|
||||||
Measure the delta range of a trackpoint
|
Measure the delta range of a trackpoint
|
||||||
.SH LIBINPUT
|
.SH LIBINPUT
|
||||||
Part of the
|
Part of the
|
||||||
|
|
|
||||||
|
|
@ -510,11 +510,20 @@ tools_exec_command(const char *prefix, int real_argc, char **real_argv)
|
||||||
setup_path();
|
setup_path();
|
||||||
|
|
||||||
rc = execvp(executable, argv);
|
rc = execvp(executable, argv);
|
||||||
if (rc)
|
if (rc) {
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"libinput: %s is not a libinput command or not installed. "
|
||||||
|
"See 'libinput --help'\n",
|
||||||
|
command);
|
||||||
|
|
||||||
|
} else {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Failed to execute '%s' (%s)\n",
|
"Failed to execute '%s' (%s)\n",
|
||||||
command,
|
command,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue