mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-04 03:50:14 +01:00
Merge branch 'clickpad-improvements-v2' of git://people.freedesktop.org/~jwrdegoede/libinput
This commit is contained in:
commit
5082eaf250
15 changed files with 1322 additions and 235 deletions
|
|
@ -1,3 +1,5 @@
|
|||
EXTRA_DIST = touchpad-tap-state-machine.svg touchpad-softbutton-state-machine.svg
|
||||
|
||||
if HAVE_DOXYGEN
|
||||
|
||||
noinst_DATA = html/index.html
|
||||
|
|
@ -12,7 +14,7 @@ clean-local:
|
|||
$(AM_V_at)rm -rf html
|
||||
|
||||
doc_src= $(shell find html -type f -printf "html/%P\n" 2>/dev/null)
|
||||
EXTRA_DIST = $(builddir)/html/index.html $(doc_src)
|
||||
EXTRA_DIST += $(builddir)/html/index.html $(doc_src)
|
||||
|
||||
endif
|
||||
|
||||
|
|
|
|||
390
doc/touchpad-softbutton-state-machine.svg
Normal file
390
doc/touchpad-softbutton-state-machine.svg
Normal file
|
|
@ -0,0 +1,390 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1560px" height="1624px" version="1.1">
|
||||
<defs/>
|
||||
<g transform="translate(0.5,0.5)">
|
||||
<path d="M 232 441 L 257 441" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 263 441 L 256 445 L 257 441 L 256 438 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<ellipse cx="154" cy="151" rx="49.5" ry="30" fill="#ccccff" stroke="#000000" stroke-width="2" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="154" y="141">
|
||||
NONE</text>
|
||||
<text x="154" y="155">
|
||||
on-entry:</text>
|
||||
<text x="154" y="169">
|
||||
curr = none</text>
|
||||
</g>
|
||||
<rect x="82" y="391" width="150" height="101" rx="6" ry="6" fill="#ccffcc" stroke="#000000" stroke-width="2" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="157" y="424">
|
||||
BOTTOM_NEW</text>
|
||||
<text x="157" y="438">
|
||||
on-entry:</text>
|
||||
<text x="157" y="452">
|
||||
curr = button</text>
|
||||
<text x="157" y="466">
|
||||
start inner timeout</text>
|
||||
</g>
|
||||
<rect x="392" y="392" width="130" height="100" rx="6" ry="6" fill="#ccffcc" stroke="#000000" stroke-width="2" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="457" y="432">
|
||||
AREA</text>
|
||||
<text x="457" y="446">
|
||||
on-entry:</text>
|
||||
<text x="457" y="460">
|
||||
curr =area</text>
|
||||
</g>
|
||||
<path d="M 284 416 C 287 413 291 411 295 411 L 329 411 C 333 411 337 413 340 416 L 360 439 C 361 441 361 442 360 443 L 340 466 C 337 469 333 471 329 471 L 295 471 C 291 471 287 469 284 466 L 264 443 C 264 442 264 441 264 439 L 284 416 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="312" y="438">
|
||||
finger in</text>
|
||||
<text x="312" y="452">
|
||||
area</text>
|
||||
</g>
|
||||
<rect x="92" y="712" width="130" height="100" rx="6" ry="6" fill="#ccffcc" stroke="#000000" stroke-width="2" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="157" y="766">
|
||||
BOTTOM</text>
|
||||
</g>
|
||||
<path d="M 129 7 C 132 4 136 2 140 2 L 174 2 C 178 2 182 4 185 7 L 205 30 C 205 31 205 33 205 34 L 185 57 C 182 60 178 62 174 62 L 140 62 C 136 62 132 60 129 57 L 109 34 C 108 33 108 31 109 30 L 129 7 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="157" y="29">
|
||||
finger</text>
|
||||
<text x="157" y="43">
|
||||
up</text>
|
||||
</g>
|
||||
<path d="M 64 571 C 67 568 71 566 75 566 L 109 566 C 113 566 117 568 120 571 L 140 594 C 140 596 140 597 140 598 L 120 621 C 117 624 113 626 109 626 L 75 626 C 71 626 67 624 64 621 L 44 598 C 43 597 43 596 44 594 L 64 571 Z" fill="#000000" stroke="#ffffff" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#FFFFFF" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="92" y="586">
|
||||
phys</text>
|
||||
<text x="92" y="600">
|
||||
button</text>
|
||||
<text x="92" y="614">
|
||||
press</text>
|
||||
</g>
|
||||
<path d="M 361 441 L 386 442" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 391 442 L 384 445 L 386 442 L 384 438 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 177 571 C 180 568 184 566 188 566 L 222 566 C 226 566 230 568 233 571 L 253 594 C 254 596 254 597 253 598 L 233 621 C 230 624 226 626 222 626 L 188 626 C 184 626 180 624 177 621 L 157 598 C 157 597 157 596 157 594 L 177 571 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="205" y="593">
|
||||
inner</text>
|
||||
<text x="205" y="607">
|
||||
timeout</text>
|
||||
</g>
|
||||
<path d="M 157 492 L 189 560" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 191 565 L 185 560 L 189 560 L 191 557 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 196 626 L 173 706" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 172 711 L 170 703 L 173 706 L 177 705 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 265 693 C 267 690 271 688 275 688 L 309 688 C 314 688 318 690 320 693 L 340 716 C 341 717 341 719 340 720 L 320 743 C 318 746 314 748 309 748 L 275 748 C 271 748 267 746 265 743 L 245 720 C 244 719 244 717 245 716 L 265 693 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="292" y="715">
|
||||
finger in</text>
|
||||
<text x="292" y="729">
|
||||
AREA</text>
|
||||
</g>
|
||||
<path d="M 222 762 L 241 724" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 243 719 L 243 727 L 241 724 L 237 724 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<rect x="361" y="718" width="194" height="94" rx="6" ry="6" fill="#ccffcc" stroke="#000000" stroke-width="2" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="457" y="755">
|
||||
BOTTOM_TO_AREA</text>
|
||||
<text x="457" y="769">
|
||||
on-entry:</text>
|
||||
<text x="457" y="783">
|
||||
start outer timeout</text>
|
||||
</g>
|
||||
<path d="M 341 718 L 358 759" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 360 764 L 354 759 L 358 759 L 361 756 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 430 541 C 432 538 436 536 440 536 L 474 536 C 479 536 483 538 485 541 L 505 564 C 506 566 506 567 505 568 L 485 591 C 483 594 479 596 474 596 L 440 596 C 436 596 432 594 430 591 L 410 568 C 409 567 409 566 410 564 L 430 541 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="457" y="563">
|
||||
outer</text>
|
||||
<text x="457" y="577">
|
||||
timeout</text>
|
||||
</g>
|
||||
<path d="M 457 718 L 457 603" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 457 597 L 461 604 L 457 603 L 454 604 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 457 536 L 457 498" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 457 493 L 461 500 L 457 498 L 454 500 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 135 235 C 137 232 140 230 144 230 L 170 230 C 173 230 176 232 178 235 L 194 259 C 194 260 194 262 194 263 L 178 287 C 176 290 173 292 170 292 L 144 292 C 140 292 137 290 135 287 L 120 263 C 119 262 119 260 120 259 L 135 235 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="157" y="258">
|
||||
finger in</text>
|
||||
<text x="157" y="272">
|
||||
bottom</text>
|
||||
</g>
|
||||
<path d="M 155 181 L 156 224" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 156 229 L 152 222 L 156 224 L 159 222 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 157 292 L 157 384" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 157 389 L 153 382 L 157 384 L 160 382 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 438 236 C 440 233 443 231 446 231 L 469 231 C 472 231 475 233 477 236 L 491 259 C 492 260 492 262 491 263 L 477 287 C 475 290 472 292 469 292 L 446 292 C 443 292 440 290 438 287 L 424 263 C 423 262 423 260 424 259 L 438 236 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="457" y="258">
|
||||
finger in</text>
|
||||
<text x="457" y="272">
|
||||
area</text>
|
||||
</g>
|
||||
<path d="M 457 292 L 457 385" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 457 391 L 454 384 L 457 385 L 461 384 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 204 151 L 418 246" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 422 248 L 414 249 L 418 246 L 417 242 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 290 563 C 293 559 297 556 302 556 L 338 556 C 343 556 347 559 350 563 L 372 594 C 372 595 372 597 372 599 L 350 630 C 347 634 343 636 338 636 L 302 636 C 297 636 293 634 290 630 L 268 599 C 268 597 268 595 268 594 L 290 563 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="320" y="586">
|
||||
finger in</text>
|
||||
<text x="320" y="600">
|
||||
bottom</text>
|
||||
<text x="320" y="614">
|
||||
button != curr</text>
|
||||
</g>
|
||||
<path d="M 295 558 L 242 487" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 238 483 L 245 486 L 242 487 L 240 490 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 419 718 L 357 641" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 353 637 L 360 640 L 357 641 L 355 645 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 92 626 L 153 707" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 156 711 L 149 708 L 153 707 L 155 703 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 157 492 L 96 561" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 92 565 L 94 558 L 96 561 L 100 562 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 266 772 C 269 767 273 765 278 765 L 314 765 C 318 765 323 767 326 772 L 347 802 C 347 804 347 806 347 808 L 326 838 C 323 842 318 845 314 845 L 278 845 C 273 845 269 842 266 838 L 245 808 C 244 806 244 804 245 802 L 266 772 Z" fill="#ffd966" stroke="#000000" stroke-width="2" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="296" y="788">
|
||||
finger in</text>
|
||||
<text x="296" y="802">
|
||||
bottom</text>
|
||||
<text x="296" y="816">
|
||||
button == curr</text>
|
||||
</g>
|
||||
<path d="M 361 765 L 349 799" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 348 804 L 347 796 L 349 799 L 353 798 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 244 805 L 225 768" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 222 763 L 229 767 L 225 768 L 222 771 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 206 712 L 276 641" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 280 637 L 277 644 L 276 641 L 272 640 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 178 492 L 263 554" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 267 557 L 259 556 L 263 554 L 263 550 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 554 765 L 728 765 Q 738 765 738 755 L 738 42 Q 738 32 728 32 L 212 32" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 206 32 L 213 28 L 212 32 L 213 35 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 92 762 L 18 762 Q 8 762 8 752 L 8 42 Q 8 32 18 32 L 102 32" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 107 32 L 100 35 L 102 32 L 100 28 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 522 442 L 728 442 Q 738 442 738 432 L 738 42 Q 738 32 728 32 L 212 32" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 206 32 L 213 28 L 212 32 L 213 35 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 82 441 L 18 441 Q 8 441 8 431 L 8 42 Q 8 32 18 32 L 102 32" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 107 32 L 100 35 L 102 32 L 100 28 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 156 62 L 156 81 Q 156 91 156 101 L 156 114" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 156 119 L 152 112 L 156 114 L 159 112 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<rect x="1123" y="472" width="120" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1183" y="489">
|
||||
Check state of</text>
|
||||
<text x="1183" y="503">
|
||||
all touches</text>
|
||||
</g>
|
||||
<path d="M 1183 512 L 1183 520 Q 1183 529 1183 536 L 1183 544" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1178 536 L 1183 545 L 1187 536" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<ellipse cx="1183" cy="72" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
||||
<path d="M 1183 87 L 1183 114 Q 1183 124 1183 134 L 1183 160" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1178 152 L 1183 161 L 1187 152" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<rect x="1133" y="17" width="100" height="40" fill="none" stroke="none" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1183" y="41">
|
||||
tp_post_softbutton_buttons()</text>
|
||||
</g>
|
||||
<path d="M 1183 212 L 1278 267 L 1183 322 L 1088 267 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1183" y="264">
|
||||
!buttons.click_pend</text>
|
||||
<text x="1183" y="278">
|
||||
&& current == old</text>
|
||||
</g>
|
||||
<path d="M 1278 267 L 1338 267 Q 1348 267 1358 267 L 1425 267" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1418 271 L 1427 267 L 1418 262" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||
<rect fill="#ffffff" stroke="none" x="1368" y="247" width="24" height="18" stroke-width="0"/>
|
||||
<text x="1368" y="261">
|
||||
yes</text>
|
||||
</g>
|
||||
<path d="M 1183 322 L 1183 332 Q 1183 342 1183 351 L 1183 360" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1178 352 L 1183 361 L 1187 352" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||
<rect fill="#ffffff" stroke="none" x="1184" y="329" width="18" height="18" stroke-width="0"/>
|
||||
<text x="1185" y="339">
|
||||
no</text>
|
||||
</g>
|
||||
<ellipse cx="1443" cy="267" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
||||
<ellipse cx="1443" cy="267" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
|
||||
<rect x="1078" y="112" width="200" height="60" rx="24" ry="24" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1178" y="132">
|
||||
current = buttons.state & 0x01</text>
|
||||
<text x="1178" y="146">
|
||||
old = buttons.old_state & 0x01</text>
|
||||
<text x="1178" y="160">
|
||||
button = 0</text>
|
||||
</g>
|
||||
<path d="M 1183 172 L 1183 182 Q 1183 192 1183 201 L 1183 210" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1178 202 L 1183 211 L 1187 202" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1183 546 L 1298 617 L 1183 688 L 1068 617 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1183" y="621">
|
||||
All touches are in state none</text>
|
||||
</g>
|
||||
<path d="M 1183 688 L 1183 696 Q 1183 703 1183 709 L 1183 716" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1178 708 L 1183 717 L 1187 708" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||
<rect fill="#ffffff" stroke="none" x="1184" y="685" width="18" height="18" stroke-width="0"/>
|
||||
<text x="1185" y="698">
|
||||
no</text>
|
||||
</g>
|
||||
<path d="M 1298 617 L 1308 617 Q 1318 617 1327 617 L 1335 617" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1328 622 L 1337 617 L 1328 613" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||
<rect fill="#ffffff" stroke="none" x="1299" y="625" width="24" height="18" stroke-width="0"/>
|
||||
<text x="1300" y="634">
|
||||
yes</text>
|
||||
</g>
|
||||
<rect x="1338" y="597" width="150" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1413" y="621">
|
||||
buttons.click_pend = 1</text>
|
||||
</g>
|
||||
<path d="M 1488 617 L 1498 617 Q 1508 617 1517 617 L 1525 617" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1518 622 L 1527 617 L 1518 613" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1183 718 L 1298 789 L 1183 860 L 1068 789 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1183" y="793">
|
||||
(Some touches are in right) &&</text>
|
||||
<text x="1183" y="807">
|
||||
(Some touches are in left)</text>
|
||||
</g>
|
||||
<path d="M 1298 789 L 1308 789 Q 1318 789 1327 789 L 1335 789" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1328 794 L 1337 789 L 1328 785" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||
<rect fill="#ffffff" stroke="none" x="1301" y="797" width="24" height="18" stroke-width="0"/>
|
||||
<text x="1302" y="806">
|
||||
yes</text>
|
||||
</g>
|
||||
<rect x="1338" y="769" width="160" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1418" y="793">
|
||||
button = BTN_MIDDLE</text>
|
||||
</g>
|
||||
<path d="M 1498 789 L 1528 789 Q 1538 789 1538 799 L 1538 1207 Q 1538 1217 1528 1217 L 1282 1217" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1290 1212 L 1281 1217 L 1290 1221" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1183 362 L 1245 396 L 1183 431 L 1120 396 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1183" y="400">
|
||||
current</text>
|
||||
</g>
|
||||
<path d="M 1120 396 L 971 396 Q 961 396 961 406 L 961 1172 Q 961 1182 961 1182 L 961 1182" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 965 1180 L 961 1182 L 965 1184" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||
<rect fill="#ffffff" stroke="none" x="1057" y="377" width="18" height="18" stroke-width="0"/>
|
||||
<text x="1058" y="390">
|
||||
no</text>
|
||||
</g>
|
||||
<path d="M 1183 431 L 1183 441 Q 1183 451 1183 460 L 1183 470" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1178 462 L 1183 471 L 1187 462" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||
<rect fill="#ffffff" stroke="none" x="1184" y="438" width="24" height="18" stroke-width="0"/>
|
||||
<text x="1185" y="448">
|
||||
yes</text>
|
||||
</g>
|
||||
<path d="M 1183 902 L 1279 967 L 1183 1032 L 1086 967 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1183" y="971">
|
||||
Some touches are in right</text>
|
||||
</g>
|
||||
<path d="M 1279 967 L 1298 967 Q 1308 967 1318 967 L 1335 967" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1328 971 L 1337 967 L 1328 962" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||
<rect fill="#ffffff" stroke="none" x="1309" y="984" width="24" height="18" stroke-width="0"/>
|
||||
<text x="1310" y="994">
|
||||
yes</text>
|
||||
</g>
|
||||
<path d="M 1183 860 L 1183 871 Q 1183 881 1183 890 L 1183 900" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1178 892 L 1183 901 L 1187 892" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||
<rect fill="#ffffff" stroke="none" x="1184" y="863" width="18" height="18" stroke-width="0"/>
|
||||
<text x="1185" y="877">
|
||||
no</text>
|
||||
</g>
|
||||
<rect x="1338" y="947" width="160" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1418" y="971">
|
||||
button = BTN_RIGHT</text>
|
||||
</g>
|
||||
<rect x="1103" y="1082" width="160" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1183" y="1106">
|
||||
button = BTN_LEFT</text>
|
||||
</g>
|
||||
<path d="M 1183 1032 L 1183 1047 Q 1183 1057 1183 1067 L 1183 1080" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1178 1072 L 1183 1081 L 1187 1072" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||
<rect fill="#ffffff" stroke="none" x="1184" y="1039" width="18" height="18" stroke-width="0"/>
|
||||
<text x="1185" y="1053">
|
||||
no</text>
|
||||
</g>
|
||||
<rect x="1085" y="1182" width="195" height="70" rx="28" ry="28" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1183" y="1214">
|
||||
buttons.active = button</text>
|
||||
<text x="1183" y="1228">
|
||||
state = BUTTON_PRESSED</text>
|
||||
</g>
|
||||
<path d="M 1183 1252 L 1183 1282 Q 1183 1292 1173 1292 L 1083 1292 Q 1073 1292 1073 1302 L 1073 1330" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1068 1322 L 1073 1331 L 1077 1322" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1183 1122 L 1183 1142 Q 1183 1152 1183 1162 L 1183 1180" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1178 1172 L 1183 1181 L 1187 1172" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1498 967 L 1528 967 Q 1538 967 1538 977 L 1538 1207 Q 1538 1217 1528 1217 L 1282 1217" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1290 1212 L 1281 1217 L 1290 1221" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<rect x="863" y="1182" width="195" height="70" rx="28" ry="28" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="960" y="1207">
|
||||
button = buttons.active</text>
|
||||
<text x="960" y="1221">
|
||||
buttons.active = 0</text>
|
||||
<text x="960" y="1235">
|
||||
state = BUTTON_RELEASED</text>
|
||||
</g>
|
||||
<rect x="998" y="1332" width="150" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1073" y="1356">
|
||||
buttons.click_pend = 0</text>
|
||||
</g>
|
||||
<path d="M 1073 1372 L 1073 1379 Q 1073 1387 1073 1393 L 1073 1400" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1068 1392 L 1073 1401 L 1077 1392" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 960 1252 L 960 1282 Q 960 1292 970 1292 L 1063 1292 Q 1073 1292 1073 1302 L 1073 1330" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1068 1322 L 1073 1331 L 1077 1322" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1073 1402 L 1113 1422 L 1073 1442 L 1033 1422 Z" fill="#ffffc0" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1073" y="1426">
|
||||
button</text>
|
||||
</g>
|
||||
<path d="M 1113 1422 L 1178 1422 Q 1188 1422 1188 1432 L 1188 1597 Q 1188 1607 1178 1607 L 1090 1607" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1098 1602 L 1089 1607 L 1098 1611" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||
<rect fill="#ffffff" stroke="none" x="1114" y="1402" width="18" height="18" stroke-width="0"/>
|
||||
<text x="1115" y="1416">
|
||||
no</text>
|
||||
</g>
|
||||
<path d="M 1073 1442 L 1073 1452 Q 1073 1462 1073 1471 L 1073 1480" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1068 1472 L 1073 1481 L 1077 1472" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" font-size="11px">
|
||||
<rect fill="#ffffff" stroke="none" x="1074" y="1449" width="24" height="18" stroke-width="0"/>
|
||||
<text x="1075" y="1459">
|
||||
yes</text>
|
||||
</g>
|
||||
<rect x="988" y="1482" width="170" height="40" rx="16" ry="16" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
|
||||
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
|
||||
<text x="1073" y="1499">
|
||||
pointer_notify_button(</text>
|
||||
<text x="1073" y="1513">
|
||||
button, state)</text>
|
||||
</g>
|
||||
<path d="M 1073 1522 L 1073 1542 Q 1073 1552 1073 1562 L 1073 1590" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<path d="M 1068 1582 L 1073 1591 L 1077 1582" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
|
||||
<ellipse cx="1073" cy="1607" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
||||
<ellipse cx="1073" cy="1607" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
|
||||
<ellipse cx="1543" cy="617" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
|
||||
<ellipse cx="1543" cy="617" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 26 KiB |
|
|
@ -14,6 +14,7 @@ libinput_la_SOURCES = \
|
|||
evdev-mt-touchpad.c \
|
||||
evdev-mt-touchpad.h \
|
||||
evdev-mt-touchpad-tap.c \
|
||||
evdev-mt-touchpad-buttons.c \
|
||||
evdev-touchpad.c \
|
||||
filter.c \
|
||||
filter.h \
|
||||
|
|
|
|||
625
src/evdev-mt-touchpad-buttons.c
Normal file
625
src/evdev-mt-touchpad-buttons.c
Normal file
|
|
@ -0,0 +1,625 @@
|
|||
/*
|
||||
* Copyright © 2014 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/input.h>
|
||||
#include <sys/timerfd.h>
|
||||
|
||||
#include "evdev-mt-touchpad.h"
|
||||
|
||||
#define DEFAULT_BUTTON_MOTION_THRESHOLD 0.02 /* 2% of size */
|
||||
#define DEFAULT_BUTTON_ENTER_TIMEOUT 100 /* ms */
|
||||
#define DEFAULT_BUTTON_LEAVE_TIMEOUT 300 /* ms */
|
||||
|
||||
/*****************************************
|
||||
* BEFORE YOU EDIT THIS FILE, look at the state diagram in
|
||||
* doc/touchpad-softbutton-state-machine.svg, or online at
|
||||
* https://drive.google.com/file/d/0B1NwWmji69nocUs1cVJTbkdwMFk/edit?usp=sharing
|
||||
* (it's a http://draw.io diagram)
|
||||
*
|
||||
* Any changes in this file must be represented in the diagram.
|
||||
*
|
||||
* The state machine only affects the soft button area code.
|
||||
*/
|
||||
|
||||
#define CASE_RETURN_STRING(a) case a: return #a;
|
||||
|
||||
static inline const char*
|
||||
button_state_to_str(enum button_state state) {
|
||||
switch(state) {
|
||||
CASE_RETURN_STRING(BUTTON_STATE_NONE);
|
||||
CASE_RETURN_STRING(BUTTON_STATE_AREA);
|
||||
CASE_RETURN_STRING(BUTTON_STATE_BOTTOM);
|
||||
CASE_RETURN_STRING(BUTTON_STATE_BOTTOM_NEW);
|
||||
CASE_RETURN_STRING(BUTTON_STATE_BOTTOM_TO_AREA);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline const char*
|
||||
button_event_to_str(enum button_event event) {
|
||||
switch(event) {
|
||||
CASE_RETURN_STRING(BUTTON_EVENT_IN_BOTTOM_R);
|
||||
CASE_RETURN_STRING(BUTTON_EVENT_IN_BOTTOM_L);
|
||||
CASE_RETURN_STRING(BUTTON_EVENT_IN_AREA);
|
||||
CASE_RETURN_STRING(BUTTON_EVENT_UP);
|
||||
CASE_RETURN_STRING(BUTTON_EVENT_PRESS);
|
||||
CASE_RETURN_STRING(BUTTON_EVENT_RELEASE);
|
||||
CASE_RETURN_STRING(BUTTON_EVENT_TIMEOUT);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_inside_button_area(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
return t->y >= tp->buttons.area.top_edge;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_inside_right_area(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
return is_inside_button_area(tp, t) &&
|
||||
t->x > tp->buttons.area.rightbutton_left_edge;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_inside_left_area(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
return is_inside_button_area(tp, t) &&
|
||||
!is_inside_right_area(tp, t);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_button_set_timer(struct tp_dispatch *tp, uint64_t timeout)
|
||||
{
|
||||
struct itimerspec its;
|
||||
its.it_interval.tv_sec = 0;
|
||||
its.it_interval.tv_nsec = 0;
|
||||
its.it_value.tv_sec = timeout / 1000;
|
||||
its.it_value.tv_nsec = (timeout % 1000) * 1000 * 1000;
|
||||
timerfd_settime(tp->buttons.timer_fd, TFD_TIMER_ABSTIME, &its, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_button_set_enter_timer(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
t->button.timeout = t->millis + DEFAULT_BUTTON_ENTER_TIMEOUT;
|
||||
tp_button_set_timer(tp, t->button.timeout);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_button_set_leave_timer(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
t->button.timeout = t->millis + DEFAULT_BUTTON_LEAVE_TIMEOUT;
|
||||
tp_button_set_timer(tp, t->button.timeout);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_button_clear_timer(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
t->button.timeout = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* tp_button_set_state, change state and implement on-entry behavior
|
||||
* as described in the state machine diagram.
|
||||
*/
|
||||
static void
|
||||
tp_button_set_state(struct tp_dispatch *tp, struct tp_touch *t,
|
||||
enum button_state new_state, enum button_event event)
|
||||
{
|
||||
tp_button_clear_timer(tp, t);
|
||||
|
||||
t->button.state = new_state;
|
||||
switch (t->button.state) {
|
||||
case BUTTON_STATE_NONE:
|
||||
t->button.curr = 0;
|
||||
break;
|
||||
case BUTTON_STATE_AREA:
|
||||
t->button.curr = BUTTON_EVENT_IN_AREA;
|
||||
tp_set_pointer(tp, t);
|
||||
break;
|
||||
case BUTTON_STATE_BOTTOM:
|
||||
break;
|
||||
case BUTTON_STATE_BOTTOM_NEW:
|
||||
t->button.curr = event;
|
||||
tp_button_set_enter_timer(tp, t);
|
||||
break;
|
||||
case BUTTON_STATE_BOTTOM_TO_AREA:
|
||||
tp_button_set_leave_timer(tp, t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_button_none_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum button_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case BUTTON_EVENT_IN_BOTTOM_R:
|
||||
case BUTTON_EVENT_IN_BOTTOM_L:
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM_NEW, event);
|
||||
break;
|
||||
case BUTTON_EVENT_IN_AREA:
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
|
||||
break;
|
||||
case BUTTON_EVENT_UP:
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
|
||||
break;
|
||||
case BUTTON_EVENT_PRESS:
|
||||
case BUTTON_EVENT_RELEASE:
|
||||
case BUTTON_EVENT_TIMEOUT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_button_area_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum button_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case BUTTON_EVENT_IN_BOTTOM_R:
|
||||
case BUTTON_EVENT_IN_BOTTOM_L:
|
||||
case BUTTON_EVENT_IN_AREA:
|
||||
break;
|
||||
case BUTTON_EVENT_UP:
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
|
||||
break;
|
||||
case BUTTON_EVENT_PRESS:
|
||||
case BUTTON_EVENT_RELEASE:
|
||||
case BUTTON_EVENT_TIMEOUT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_button_bottom_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum button_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case BUTTON_EVENT_IN_BOTTOM_R:
|
||||
case BUTTON_EVENT_IN_BOTTOM_L:
|
||||
if (event != t->button.curr)
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM_NEW,
|
||||
event);
|
||||
break;
|
||||
case BUTTON_EVENT_IN_AREA:
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM_TO_AREA, event);
|
||||
break;
|
||||
case BUTTON_EVENT_UP:
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
|
||||
break;
|
||||
case BUTTON_EVENT_PRESS:
|
||||
case BUTTON_EVENT_RELEASE:
|
||||
case BUTTON_EVENT_TIMEOUT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_button_bottom_new_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum button_event event)
|
||||
{
|
||||
switch(event) {
|
||||
case BUTTON_EVENT_IN_BOTTOM_R:
|
||||
case BUTTON_EVENT_IN_BOTTOM_L:
|
||||
if (event != t->button.curr)
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM_NEW,
|
||||
event);
|
||||
break;
|
||||
case BUTTON_EVENT_IN_AREA:
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
|
||||
break;
|
||||
case BUTTON_EVENT_UP:
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
|
||||
break;
|
||||
case BUTTON_EVENT_PRESS:
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM, event);
|
||||
break;
|
||||
case BUTTON_EVENT_RELEASE:
|
||||
break;
|
||||
case BUTTON_EVENT_TIMEOUT:
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM, event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_button_bottom_to_area_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum button_event event)
|
||||
{
|
||||
switch(event) {
|
||||
case BUTTON_EVENT_IN_BOTTOM_R:
|
||||
case BUTTON_EVENT_IN_BOTTOM_L:
|
||||
if (event == t->button.curr)
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM,
|
||||
event);
|
||||
else
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_BOTTOM_NEW,
|
||||
event);
|
||||
break;
|
||||
case BUTTON_EVENT_IN_AREA:
|
||||
break;
|
||||
case BUTTON_EVENT_UP:
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_NONE, event);
|
||||
break;
|
||||
case BUTTON_EVENT_PRESS:
|
||||
case BUTTON_EVENT_RELEASE:
|
||||
break;
|
||||
case BUTTON_EVENT_TIMEOUT:
|
||||
tp_button_set_state(tp, t, BUTTON_STATE_AREA, event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_button_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum button_event event,
|
||||
uint64_t time)
|
||||
{
|
||||
enum button_state current = t->button.state;
|
||||
|
||||
switch(t->button.state) {
|
||||
case BUTTON_STATE_NONE:
|
||||
tp_button_none_handle_event(tp, t, event);
|
||||
break;
|
||||
case BUTTON_STATE_AREA:
|
||||
tp_button_area_handle_event(tp, t, event);
|
||||
break;
|
||||
case BUTTON_STATE_BOTTOM:
|
||||
tp_button_bottom_handle_event(tp, t, event);
|
||||
break;
|
||||
case BUTTON_STATE_BOTTOM_NEW:
|
||||
tp_button_bottom_new_handle_event(tp, t, event);
|
||||
break;
|
||||
case BUTTON_STATE_BOTTOM_TO_AREA:
|
||||
tp_button_bottom_to_area_handle_event(tp, t, event);
|
||||
break;
|
||||
}
|
||||
|
||||
if (current != t->button.state)
|
||||
log_debug("button state: from %s, event %s to %s\n",
|
||||
button_state_to_str(current),
|
||||
button_event_to_str(event),
|
||||
button_state_to_str(t->button.state));
|
||||
}
|
||||
|
||||
int
|
||||
tp_button_handle_state(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
|
||||
tp_for_each_touch(tp, t) {
|
||||
if (t->state == TOUCH_NONE)
|
||||
continue;
|
||||
|
||||
if (t->state == TOUCH_END) {
|
||||
tp_button_handle_event(tp, t, BUTTON_EVENT_UP, time);
|
||||
} else if (t->dirty) {
|
||||
if (is_inside_right_area(tp, t))
|
||||
tp_button_handle_event(tp, t, BUTTON_EVENT_IN_BOTTOM_R, time);
|
||||
else if (is_inside_left_area(tp, t))
|
||||
tp_button_handle_event(tp, t, BUTTON_EVENT_IN_BOTTOM_L, time);
|
||||
else
|
||||
tp_button_handle_event(tp, t, BUTTON_EVENT_IN_AREA, time);
|
||||
}
|
||||
if (tp->queued & TOUCHPAD_EVENT_BUTTON_RELEASE)
|
||||
tp_button_handle_event(tp, t, BUTTON_EVENT_RELEASE, time);
|
||||
if (tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS)
|
||||
tp_button_handle_event(tp, t, BUTTON_EVENT_PRESS, time);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_button_handle_timeout(struct tp_dispatch *tp, uint64_t now)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
|
||||
tp_for_each_touch(tp, t) {
|
||||
if (t->button.timeout != 0 && t->button.timeout <= now) {
|
||||
tp_button_clear_timer(tp, t);
|
||||
tp_button_handle_event(tp, t, BUTTON_EVENT_TIMEOUT, now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
tp_process_button(struct tp_dispatch *tp,
|
||||
const struct input_event *e,
|
||||
uint64_t time)
|
||||
{
|
||||
uint32_t mask = 1 << (e->code - BTN_LEFT);
|
||||
|
||||
/* Ignore other buttons on clickpads */
|
||||
if (tp->buttons.is_clickpad && e->code != BTN_LEFT) {
|
||||
log_bug("received %s button event on a clickpad (kernel bug?)\n",
|
||||
libevdev_event_code_get_name(EV_KEY, e->code));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (e->value) {
|
||||
tp->buttons.state |= mask;
|
||||
tp->queued |= TOUCHPAD_EVENT_BUTTON_PRESS;
|
||||
} else {
|
||||
tp->buttons.state &= ~mask;
|
||||
tp->queued |= TOUCHPAD_EVENT_BUTTON_RELEASE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_button_timeout_handler(void *data)
|
||||
{
|
||||
struct tp_dispatch *tp = data;
|
||||
uint64_t expires;
|
||||
int len;
|
||||
struct timespec ts;
|
||||
uint64_t now;
|
||||
|
||||
len = read(tp->buttons.timer_fd, &expires, sizeof expires);
|
||||
if (len != sizeof expires)
|
||||
/* This will only happen if the application made the fd
|
||||
* non-blocking, but this function should only be called
|
||||
* upon the timeout, so lets continue anyway. */
|
||||
log_error("timerfd read error: %s\n", strerror(errno));
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
now = ts.tv_sec * 1000ULL + ts.tv_nsec / 1000000;
|
||||
|
||||
tp_button_handle_timeout(tp, now);
|
||||
}
|
||||
|
||||
int
|
||||
tp_init_buttons(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
int width, height;
|
||||
double diagonal;
|
||||
|
||||
tp->buttons.is_clickpad = libevdev_has_property(device->evdev,
|
||||
INPUT_PROP_BUTTONPAD);
|
||||
|
||||
if (libevdev_has_event_code(device->evdev, EV_KEY, BTN_MIDDLE) ||
|
||||
libevdev_has_event_code(device->evdev, EV_KEY, BTN_RIGHT)) {
|
||||
if (tp->buttons.is_clickpad)
|
||||
log_bug("clickpad advertising right button (kernel bug?)\n");
|
||||
} else {
|
||||
if (!tp->buttons.is_clickpad)
|
||||
log_bug("non clickpad without right button (kernel bug)?\n");
|
||||
}
|
||||
|
||||
width = abs(device->abs.max_x - device->abs.min_x);
|
||||
height = abs(device->abs.max_y - device->abs.min_y);
|
||||
diagonal = sqrt(width*width + height*height);
|
||||
|
||||
tp->buttons.motion_dist = diagonal * DEFAULT_BUTTON_MOTION_THRESHOLD;
|
||||
|
||||
if (libevdev_get_id_vendor(device->evdev) == 0x5ac) /* Apple */
|
||||
tp->buttons.use_clickfinger = true;
|
||||
|
||||
if (tp->buttons.is_clickpad && !tp->buttons.use_clickfinger) {
|
||||
tp->buttons.area.top_edge = height * .8 + device->abs.min_y;
|
||||
tp->buttons.area.rightbutton_left_edge = width/2 + device->abs.min_x;
|
||||
tp->buttons.timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
|
||||
|
||||
if (tp->buttons.timer_fd == -1)
|
||||
return -1;
|
||||
|
||||
tp->buttons.source =
|
||||
libinput_add_fd(tp->device->base.seat->libinput,
|
||||
tp->buttons.timer_fd,
|
||||
tp_button_timeout_handler,
|
||||
tp);
|
||||
if (tp->buttons.source == NULL)
|
||||
return -1;
|
||||
} else {
|
||||
tp->buttons.area.top_edge = INT_MAX;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
tp_destroy_buttons(struct tp_dispatch *tp)
|
||||
{
|
||||
if (tp->buttons.source) {
|
||||
libinput_remove_source(tp->device->base.seat->libinput,
|
||||
tp->buttons.source);
|
||||
tp->buttons.source = NULL;
|
||||
}
|
||||
if (tp->buttons.timer_fd > -1) {
|
||||
close(tp->buttons.timer_fd);
|
||||
tp->buttons.timer_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
tp_post_clickfinger_buttons(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
uint32_t current, old, button;
|
||||
enum libinput_pointer_button_state state;
|
||||
|
||||
current = tp->buttons.state;
|
||||
old = tp->buttons.old_state;
|
||||
|
||||
if (current == old)
|
||||
return 0;
|
||||
|
||||
if (current) {
|
||||
switch (tp->nfingers_down) {
|
||||
case 1: button = BTN_LEFT; break;
|
||||
case 2: button = BTN_RIGHT; break;
|
||||
case 3: button = BTN_MIDDLE; break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
tp->buttons.active = button;
|
||||
state = LIBINPUT_POINTER_BUTTON_STATE_PRESSED;
|
||||
} else {
|
||||
button = tp->buttons.active;
|
||||
tp->buttons.active = 0;
|
||||
state = LIBINPUT_POINTER_BUTTON_STATE_RELEASED;
|
||||
}
|
||||
|
||||
if (button)
|
||||
pointer_notify_button(&tp->device->base,
|
||||
time,
|
||||
button,
|
||||
state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_post_physical_buttons(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
uint32_t current, old, button;
|
||||
|
||||
current = tp->buttons.state;
|
||||
old = tp->buttons.old_state;
|
||||
button = BTN_LEFT;
|
||||
|
||||
while (current || old) {
|
||||
enum libinput_pointer_button_state state;
|
||||
|
||||
if ((current & 0x1) ^ (old & 0x1)) {
|
||||
if (!!(current & 0x1))
|
||||
state = LIBINPUT_POINTER_BUTTON_STATE_PRESSED;
|
||||
else
|
||||
state = LIBINPUT_POINTER_BUTTON_STATE_RELEASED;
|
||||
|
||||
pointer_notify_button(&tp->device->base,
|
||||
time,
|
||||
button,
|
||||
state);
|
||||
}
|
||||
|
||||
button++;
|
||||
current >>= 1;
|
||||
old >>= 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_post_softbutton_buttons(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
uint32_t current, old, button;
|
||||
enum libinput_pointer_button_state state;
|
||||
enum { AREA = 0x01, LEFT = 0x02, RIGHT = 0x04 };
|
||||
|
||||
current = tp->buttons.state;
|
||||
old = tp->buttons.old_state;
|
||||
button = 0;
|
||||
|
||||
if (!tp->buttons.click_pending && current == old)
|
||||
return 0;
|
||||
|
||||
if (current) {
|
||||
struct tp_touch *t;
|
||||
|
||||
tp_for_each_touch(tp, t) {
|
||||
switch (t->button.curr) {
|
||||
case BUTTON_EVENT_IN_AREA:
|
||||
button |= AREA;
|
||||
break;
|
||||
case BUTTON_EVENT_IN_BOTTOM_L:
|
||||
button |= LEFT;
|
||||
break;
|
||||
case BUTTON_EVENT_IN_BOTTOM_R:
|
||||
button |= RIGHT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (button) {
|
||||
case 0:
|
||||
/* No touches, wait for a touch before processing */
|
||||
tp->buttons.click_pending = true;
|
||||
return 0;
|
||||
case RIGHT:
|
||||
case RIGHT | AREA:
|
||||
/* Some touches in right, no touches in left */
|
||||
button = BTN_RIGHT;
|
||||
break;
|
||||
case LEFT | RIGHT:
|
||||
case LEFT | RIGHT | AREA:
|
||||
/* Some touches in left and some in right */
|
||||
button = BTN_MIDDLE;
|
||||
break;
|
||||
default:
|
||||
button = BTN_LEFT;
|
||||
}
|
||||
|
||||
tp->buttons.active = button;
|
||||
state = LIBINPUT_POINTER_BUTTON_STATE_PRESSED;
|
||||
} else {
|
||||
button = tp->buttons.active;
|
||||
tp->buttons.active = 0;
|
||||
state = LIBINPUT_POINTER_BUTTON_STATE_RELEASED;
|
||||
}
|
||||
|
||||
tp->buttons.click_pending = false;
|
||||
|
||||
if (button)
|
||||
pointer_notify_button(&tp->device->base,
|
||||
time,
|
||||
button,
|
||||
state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
tp_post_button_events(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
if (tp->buttons.is_clickpad) {
|
||||
if (tp->buttons.use_clickfinger)
|
||||
return tp_post_clickfinger_buttons(tp, time);
|
||||
else
|
||||
return tp_post_softbutton_buttons(tp, time);
|
||||
}
|
||||
|
||||
return tp_post_physical_buttons(tp, time);
|
||||
}
|
||||
|
||||
int
|
||||
tp_button_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
return t->button.state == BUTTON_STATE_AREA;
|
||||
}
|
||||
|
|
@ -97,7 +97,7 @@ tap_event_to_str(enum tap_event event) {
|
|||
|
||||
static void
|
||||
tp_tap_notify(struct tp_dispatch *tp,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
int nfingers,
|
||||
enum libinput_pointer_button_state state)
|
||||
{
|
||||
|
|
@ -118,9 +118,9 @@ tp_tap_notify(struct tp_dispatch *tp,
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tap_set_timer(struct tp_dispatch *tp, uint32_t time)
|
||||
tp_tap_set_timer(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
uint32_t timeout = time + DEFAULT_TAP_TIMEOUT_PERIOD;
|
||||
uint64_t timeout = time + DEFAULT_TAP_TIMEOUT_PERIOD;
|
||||
struct itimerspec its;
|
||||
|
||||
its.it_interval.tv_sec = 0;
|
||||
|
|
@ -139,7 +139,7 @@ tp_tap_clear_timer(struct tp_dispatch *tp)
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tap_idle_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t time)
|
||||
tp_tap_idle_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
|
||||
{
|
||||
|
||||
switch (event) {
|
||||
|
|
@ -160,7 +160,7 @@ tp_tap_idle_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tap_touch_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t time)
|
||||
tp_tap_touch_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
|
||||
{
|
||||
|
||||
switch (event) {
|
||||
|
|
@ -185,7 +185,7 @@ tp_tap_touch_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tap_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t time)
|
||||
tp_tap_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
|
||||
{
|
||||
|
||||
switch (event) {
|
||||
|
|
@ -206,7 +206,7 @@ tp_tap_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tap_tapped_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t time)
|
||||
tp_tap_tapped_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
|
||||
{
|
||||
|
||||
switch (event) {
|
||||
|
|
@ -230,7 +230,7 @@ tp_tap_tapped_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tap_touch2_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t time)
|
||||
tp_tap_touch2_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
|
||||
{
|
||||
|
||||
switch (event) {
|
||||
|
|
@ -256,7 +256,7 @@ tp_tap_touch2_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tap_touch2_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t time)
|
||||
tp_tap_touch2_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
|
||||
{
|
||||
|
||||
switch (event) {
|
||||
|
|
@ -278,7 +278,7 @@ tp_tap_touch2_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, ui
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tap_touch3_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t time)
|
||||
tp_tap_touch3_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
|
||||
{
|
||||
|
||||
switch (event) {
|
||||
|
|
@ -303,7 +303,7 @@ tp_tap_touch3_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tap_touch3_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t time)
|
||||
tp_tap_touch3_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
|
||||
{
|
||||
|
||||
switch (event) {
|
||||
|
|
@ -324,7 +324,7 @@ tp_tap_touch3_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, ui
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t time)
|
||||
tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
|
||||
{
|
||||
switch (event) {
|
||||
case TAP_EVENT_TOUCH:
|
||||
|
|
@ -349,7 +349,7 @@ tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp, enum tap_event
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tap_dragging_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t time)
|
||||
tp_tap_dragging_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
|
||||
{
|
||||
|
||||
switch (event) {
|
||||
|
|
@ -372,7 +372,7 @@ tp_tap_dragging_handle_event(struct tp_dispatch *tp, enum tap_event event, uint3
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t time)
|
||||
tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
|
||||
{
|
||||
|
||||
switch (event) {
|
||||
|
|
@ -395,7 +395,7 @@ tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp, enum tap_event event,
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tap_dragging2_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t time)
|
||||
tp_tap_dragging2_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
|
||||
{
|
||||
|
||||
switch (event) {
|
||||
|
|
@ -418,7 +418,7 @@ tp_tap_dragging2_handle_event(struct tp_dispatch *tp, enum tap_event event, uint
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tap_dead_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t time)
|
||||
tp_tap_dead_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
|
||||
{
|
||||
|
||||
switch (event) {
|
||||
|
|
@ -435,7 +435,7 @@ tp_tap_dead_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t
|
|||
}
|
||||
|
||||
static void
|
||||
tp_tap_handle_event(struct tp_dispatch *tp, enum tap_event event, uint32_t time)
|
||||
tp_tap_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time)
|
||||
{
|
||||
enum tp_tap_state current;
|
||||
if (!tp->tap.enabled)
|
||||
|
|
@ -503,7 +503,7 @@ tp_tap_exceeds_motion_threshold(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
}
|
||||
|
||||
int
|
||||
tp_tap_handle_state(struct tp_dispatch *tp, uint32_t time)
|
||||
tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
int filter_motion = 0;
|
||||
|
|
@ -554,7 +554,7 @@ tp_tap_timeout_handler(void *data)
|
|||
uint64_t expires;
|
||||
int len;
|
||||
struct timespec ts;
|
||||
uint32_t now;
|
||||
uint64_t now;
|
||||
|
||||
len = read(touchpad->tap.timer_fd, &expires, sizeof expires);
|
||||
if (len != sizeof expires)
|
||||
|
|
@ -564,13 +564,13 @@ tp_tap_timeout_handler(void *data)
|
|||
log_error("timerfd read error: %s\n", strerror(errno));
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
now = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
|
||||
now = ts.tv_sec * 1000ULL + ts.tv_nsec / 1000000;
|
||||
|
||||
tp_tap_handle_timeout(touchpad, now);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
tp_tap_handle_timeout(struct tp_dispatch *tp, uint32_t time)
|
||||
tp_tap_handle_timeout(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
if (!tp->tap.enabled)
|
||||
return 0;
|
||||
|
|
@ -615,6 +615,8 @@ tp_destroy_tap(struct tp_dispatch *tp)
|
|||
libinput_remove_source(tp->device->base.seat->libinput, tp->tap.source);
|
||||
tp->tap.source = NULL;
|
||||
}
|
||||
if (tp->tap.timer_fd > -1)
|
||||
if (tp->tap.timer_fd > -1) {
|
||||
close(tp->tap.timer_fd);
|
||||
tp->tap.timer_fd = -1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ static double
|
|||
tp_accel_profile(struct motion_filter *filter,
|
||||
void *data,
|
||||
double velocity,
|
||||
uint32_t time)
|
||||
uint64_t time)
|
||||
{
|
||||
struct tp_dispatch *tp =
|
||||
(struct tp_dispatch *) data;
|
||||
|
|
@ -80,7 +80,7 @@ tp_motion_history_offset(struct tp_touch *t, int offset)
|
|||
|
||||
static void
|
||||
tp_filter_motion(struct tp_dispatch *tp,
|
||||
double *dx, double *dy, uint32_t time)
|
||||
double *dx, double *dy, uint64_t time)
|
||||
{
|
||||
struct motion_params motion;
|
||||
|
||||
|
|
@ -152,24 +152,14 @@ tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
|
|||
static inline void
|
||||
tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
struct tp_touch *tmp = NULL;
|
||||
|
||||
if (t->state != TOUCH_UPDATE) {
|
||||
tp_motion_history_reset(t);
|
||||
t->dirty = true;
|
||||
t->state = TOUCH_BEGIN;
|
||||
t->pinned.is_pinned = false;
|
||||
tp->nfingers_down++;
|
||||
assert(tp->nfingers_down >= 1);
|
||||
tp->queued |= TOUCHPAD_EVENT_MOTION;
|
||||
|
||||
tp_for_each_touch(tp, tmp) {
|
||||
if (tmp->is_pointer)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tmp->is_pointer) {
|
||||
t->is_pointer = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -182,6 +172,7 @@ tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
t->dirty = true;
|
||||
t->is_pointer = false;
|
||||
t->state = TOUCH_END;
|
||||
t->pinned.is_pinned = false;
|
||||
assert(tp->nfingers_down >= 1);
|
||||
tp->nfingers_down--;
|
||||
tp->queued |= TOUCHPAD_EVENT_MOTION;
|
||||
|
|
@ -215,7 +206,7 @@ tp_get_delta(struct tp_touch *t, double *dx, double *dy)
|
|||
static void
|
||||
tp_process_absolute(struct tp_dispatch *tp,
|
||||
const struct input_event *e,
|
||||
uint32_t time)
|
||||
uint64_t time)
|
||||
{
|
||||
struct tp_touch *t = tp_current_touch(tp);
|
||||
|
||||
|
|
@ -247,7 +238,7 @@ tp_process_absolute(struct tp_dispatch *tp,
|
|||
static void
|
||||
tp_process_absolute_st(struct tp_dispatch *tp,
|
||||
const struct input_event *e,
|
||||
uint32_t time)
|
||||
uint64_t time)
|
||||
{
|
||||
struct tp_touch *t = tp_current_touch(tp);
|
||||
|
||||
|
|
@ -270,7 +261,7 @@ tp_process_absolute_st(struct tp_dispatch *tp,
|
|||
static void
|
||||
tp_process_fake_touch(struct tp_dispatch *tp,
|
||||
const struct input_event *e,
|
||||
uint32_t time)
|
||||
uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
unsigned int fake_touches;
|
||||
|
|
@ -318,22 +309,13 @@ tp_process_fake_touch(struct tp_dispatch *tp,
|
|||
static void
|
||||
tp_process_key(struct tp_dispatch *tp,
|
||||
const struct input_event *e,
|
||||
uint32_t time)
|
||||
uint64_t time)
|
||||
{
|
||||
uint32_t mask;
|
||||
|
||||
switch (e->code) {
|
||||
case BTN_LEFT:
|
||||
case BTN_MIDDLE:
|
||||
case BTN_RIGHT:
|
||||
mask = 1 << (e->code - BTN_LEFT);
|
||||
if (e->value) {
|
||||
tp->buttons.state |= mask;
|
||||
tp->queued |= TOUCHPAD_EVENT_BUTTON_PRESS;
|
||||
} else {
|
||||
tp->buttons.state &= ~mask;
|
||||
tp->queued |= TOUCHPAD_EVENT_BUTTON_RELEASE;
|
||||
}
|
||||
tp_process_button(tp, e, time);
|
||||
break;
|
||||
case BTN_TOUCH:
|
||||
case BTN_TOOL_DOUBLETAP:
|
||||
|
|
@ -346,54 +328,60 @@ tp_process_key(struct tp_dispatch *tp,
|
|||
}
|
||||
|
||||
static void
|
||||
tp_unpin_finger(struct tp_dispatch *tp)
|
||||
tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
unsigned int xdist, ydist;
|
||||
|
||||
if (!t->pinned.is_pinned)
|
||||
return;
|
||||
|
||||
xdist = abs(t->x - t->pinned.center_x);
|
||||
ydist = abs(t->y - t->pinned.center_y);
|
||||
|
||||
if (xdist * xdist + ydist * ydist >=
|
||||
tp->buttons.motion_dist * tp->buttons.motion_dist) {
|
||||
t->pinned.is_pinned = false;
|
||||
tp_set_pointer(tp, t);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_pin_fingers(struct tp_dispatch *tp)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
tp_for_each_touch(tp, t) {
|
||||
if (t->is_pinned) {
|
||||
t->is_pinned = false;
|
||||
|
||||
if (t->state != TOUCH_END &&
|
||||
tp->nfingers_down == 1)
|
||||
t->is_pointer = true;
|
||||
break;
|
||||
}
|
||||
tp_for_each_touch(tp, t) {
|
||||
t->is_pointer = false;
|
||||
t->pinned.is_pinned = true;
|
||||
t->pinned.center_x = t->x;
|
||||
t->pinned.center_y = t->y;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_pin_finger(struct tp_dispatch *tp)
|
||||
static int
|
||||
tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
struct tp_touch *t,
|
||||
*pinned = NULL;
|
||||
return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
|
||||
!t->pinned.is_pinned && tp_button_touch_active(tp, t);
|
||||
}
|
||||
|
||||
tp_for_each_touch(tp, t) {
|
||||
if (t->is_pinned) {
|
||||
pinned = t;
|
||||
break;
|
||||
}
|
||||
void
|
||||
tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t)
|
||||
{
|
||||
struct tp_touch *tmp = NULL;
|
||||
|
||||
/* Only set the touch as pointer if we don't have one yet */
|
||||
tp_for_each_touch(tp, tmp) {
|
||||
if (tmp->is_pointer)
|
||||
return;
|
||||
}
|
||||
|
||||
assert(!pinned);
|
||||
|
||||
pinned = tp_current_touch(tp);
|
||||
|
||||
if (tp->nfingers_down != 1) {
|
||||
tp_for_each_touch(tp, t) {
|
||||
if (t == pinned)
|
||||
continue;
|
||||
|
||||
if (t->y > pinned->y)
|
||||
pinned = t;
|
||||
}
|
||||
}
|
||||
|
||||
pinned->is_pinned = true;
|
||||
pinned->is_pointer = false;
|
||||
if (tp_touch_active(tp, t))
|
||||
t->is_pointer = true;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_process_state(struct tp_dispatch *tp, uint32_t time)
|
||||
tp_process_state(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
struct tp_touch *first = tp_get_touch(tp, 0);
|
||||
|
|
@ -409,20 +397,25 @@ tp_process_state(struct tp_dispatch *tp, uint32_t time)
|
|||
|
||||
tp_motion_hysteresis(tp, t);
|
||||
tp_motion_history_push(t);
|
||||
|
||||
tp_unpin_finger(tp, t);
|
||||
}
|
||||
|
||||
/* We have a physical button down event on a clickpad. For drag and
|
||||
drop, this means we try to identify which finger pressed the
|
||||
physical button and "pin" it, i.e. remove pointer-moving
|
||||
capabilities from it.
|
||||
tp_button_handle_state(tp, time);
|
||||
|
||||
/*
|
||||
* We have a physical button down event on a clickpad. To avoid
|
||||
* spurious pointer moves by the clicking finger we pin all fingers.
|
||||
* We unpin fingers when they move more then a certain threshold to
|
||||
* to allow drag and drop.
|
||||
*/
|
||||
if ((tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) &&
|
||||
!tp->buttons.has_buttons)
|
||||
tp_pin_finger(tp);
|
||||
tp->buttons.is_clickpad)
|
||||
tp_pin_fingers(tp);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_post_process_state(struct tp_dispatch *tp, uint32_t time)
|
||||
tp_post_process_state(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
|
||||
|
|
@ -441,14 +434,11 @@ tp_post_process_state(struct tp_dispatch *tp, uint32_t time)
|
|||
|
||||
tp->buttons.old_state = tp->buttons.state;
|
||||
|
||||
if (tp->queued & TOUCHPAD_EVENT_BUTTON_RELEASE)
|
||||
tp_unpin_finger(tp);
|
||||
|
||||
tp->queued = TOUCHPAD_EVENT_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_post_twofinger_scroll(struct tp_dispatch *tp, uint32_t time)
|
||||
tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
int nchanged = 0;
|
||||
|
|
@ -456,7 +446,7 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint32_t time)
|
|||
double tmpx, tmpy;
|
||||
|
||||
tp_for_each_touch(tp, t) {
|
||||
if (t->dirty) {
|
||||
if (tp_touch_active(tp, t) && t->dirty) {
|
||||
nchanged++;
|
||||
tp_get_delta(t, &tmpx, &tmpy);
|
||||
|
||||
|
|
@ -507,14 +497,18 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint32_t time)
|
|||
}
|
||||
|
||||
static int
|
||||
tp_post_scroll_events(struct tp_dispatch *tp, uint32_t time)
|
||||
tp_post_scroll_events(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
/* don't scroll if a clickpad is held down */
|
||||
if (!tp->buttons.has_buttons &&
|
||||
(tp->buttons.state || tp->buttons.old_state))
|
||||
return 0;
|
||||
struct tp_touch *t;
|
||||
int nfingers_down = 0;
|
||||
|
||||
if (tp->nfingers_down != 2) {
|
||||
/* Only count active touches for 2 finger scrolling */
|
||||
tp_for_each_touch(tp, t) {
|
||||
if (tp_touch_active(tp, t))
|
||||
nfingers_down++;
|
||||
}
|
||||
|
||||
if (nfingers_down != 2) {
|
||||
/* terminate scrolling with a zero scroll event to notify
|
||||
* caller that it really ended now */
|
||||
if (tp->scroll.state != SCROLL_STATE_NONE) {
|
||||
|
|
@ -538,89 +532,8 @@ tp_post_scroll_events(struct tp_dispatch *tp, uint32_t time)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_post_clickfinger_buttons(struct tp_dispatch *tp, uint32_t time)
|
||||
{
|
||||
uint32_t current, old, button;
|
||||
enum libinput_pointer_button_state state;
|
||||
|
||||
current = tp->buttons.state;
|
||||
old = tp->buttons.old_state;
|
||||
|
||||
if (current == old)
|
||||
return 0;
|
||||
|
||||
switch (tp->nfingers_down) {
|
||||
case 1: button = BTN_LEFT; break;
|
||||
case 2: button = BTN_RIGHT; break;
|
||||
case 3: button = BTN_MIDDLE; break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (current)
|
||||
state = LIBINPUT_POINTER_BUTTON_STATE_PRESSED;
|
||||
else
|
||||
state = LIBINPUT_POINTER_BUTTON_STATE_RELEASED;
|
||||
|
||||
pointer_notify_button(&tp->device->base,
|
||||
time,
|
||||
button,
|
||||
state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_post_physical_buttons(struct tp_dispatch *tp, uint32_t time)
|
||||
{
|
||||
uint32_t current, old, button;
|
||||
|
||||
current = tp->buttons.state;
|
||||
old = tp->buttons.old_state;
|
||||
button = BTN_LEFT;
|
||||
|
||||
while (current || old) {
|
||||
enum libinput_pointer_button_state state;
|
||||
|
||||
if ((current & 0x1) ^ (old & 0x1)) {
|
||||
if (!!(current & 0x1))
|
||||
state = LIBINPUT_POINTER_BUTTON_STATE_PRESSED;
|
||||
else
|
||||
state = LIBINPUT_POINTER_BUTTON_STATE_RELEASED;
|
||||
|
||||
pointer_notify_button(&tp->device->base,
|
||||
time,
|
||||
button,
|
||||
state);
|
||||
}
|
||||
|
||||
button++;
|
||||
current >>= 1;
|
||||
old >>= 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_post_button_events(struct tp_dispatch *tp, uint32_t time)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ((tp->queued &
|
||||
(TOUCHPAD_EVENT_BUTTON_PRESS|TOUCHPAD_EVENT_BUTTON_RELEASE)) == 0)
|
||||
return 0;
|
||||
|
||||
if (tp->buttons.has_buttons)
|
||||
rc = tp_post_physical_buttons(tp, time);
|
||||
else
|
||||
rc = tp_post_clickfinger_buttons(tp, time);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_post_events(struct tp_dispatch *tp, uint32_t time)
|
||||
tp_post_events(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t = tp_current_touch(tp);
|
||||
double dx, dy;
|
||||
|
|
@ -661,7 +574,7 @@ static void
|
|||
tp_process(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
struct input_event *e,
|
||||
uint32_t time)
|
||||
uint64_t time)
|
||||
{
|
||||
struct tp_dispatch *tp =
|
||||
(struct tp_dispatch *)dispatch;
|
||||
|
|
@ -691,6 +604,7 @@ tp_destroy(struct evdev_dispatch *dispatch)
|
|||
(struct tp_dispatch*)dispatch;
|
||||
|
||||
tp_destroy_tap(tp);
|
||||
tp_destroy_buttons(tp);
|
||||
|
||||
if (tp->filter)
|
||||
tp->filter->interface->destroy(tp->filter);
|
||||
|
|
@ -703,10 +617,18 @@ static struct evdev_dispatch_interface tp_interface = {
|
|||
tp_destroy
|
||||
};
|
||||
|
||||
static void
|
||||
tp_init_touch(struct tp_dispatch *tp,
|
||||
struct tp_touch *t)
|
||||
{
|
||||
t->button.state = BUTTON_STATE_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_init_slots(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
size_t i;
|
||||
const struct input_absinfo *absinfo;
|
||||
|
||||
absinfo = libevdev_get_abs_info(device->evdev, ABS_MT_SLOT);
|
||||
|
|
@ -715,15 +637,38 @@ tp_init_slots(struct tp_dispatch *tp,
|
|||
tp->slot = absinfo->value;
|
||||
tp->has_mt = true;
|
||||
} else {
|
||||
tp->ntouches = 5; /* FIXME: based on DOUBLETAP, etc. */
|
||||
struct map {
|
||||
unsigned int code;
|
||||
int ntouches;
|
||||
} max_touches[] = {
|
||||
{ BTN_TOOL_QUINTTAP, 5 },
|
||||
{ BTN_TOOL_QUADTAP, 4 },
|
||||
{ BTN_TOOL_TRIPLETAP, 3 },
|
||||
{ BTN_TOOL_DOUBLETAP, 2 },
|
||||
};
|
||||
struct map *m;
|
||||
|
||||
tp->slot = 0;
|
||||
tp->has_mt = false;
|
||||
tp->ntouches = 1;
|
||||
|
||||
ARRAY_FOR_EACH(max_touches, m) {
|
||||
if (libevdev_has_event_code(device->evdev,
|
||||
EV_KEY,
|
||||
m->code)) {
|
||||
tp->ntouches = m->ntouches;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
tp->touches = calloc(tp->ntouches,
|
||||
sizeof(struct tp_touch));
|
||||
if (!tp->touches)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < tp->ntouches; i++)
|
||||
tp_init_touch(tp, &tp->touches[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -765,6 +710,7 @@ tp_init(struct tp_dispatch *tp,
|
|||
tp->base.interface = &tp_interface;
|
||||
tp->device = device;
|
||||
tp->tap.timer_fd = -1;
|
||||
tp->buttons.timer_fd = -1;
|
||||
|
||||
if (tp_init_slots(tp, device) != 0)
|
||||
return -1;
|
||||
|
|
@ -778,10 +724,6 @@ tp_init(struct tp_dispatch *tp,
|
|||
tp->hysteresis.margin_y =
|
||||
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
|
||||
|
||||
if (libevdev_has_event_code(device->evdev, EV_KEY, BTN_MIDDLE) ||
|
||||
libevdev_has_event_code(device->evdev, EV_KEY, BTN_RIGHT))
|
||||
tp->buttons.has_buttons = true;
|
||||
|
||||
if (tp_init_scroll(tp) != 0)
|
||||
return -1;
|
||||
|
||||
|
|
@ -791,6 +733,9 @@ tp_init(struct tp_dispatch *tp,
|
|||
if (tp_init_tap(tp) != 0)
|
||||
return -1;
|
||||
|
||||
if (tp_init_buttons(tp, device) != 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,24 @@ enum touch_state {
|
|||
TOUCH_END
|
||||
};
|
||||
|
||||
enum button_event {
|
||||
BUTTON_EVENT_IN_BOTTOM_R = 30,
|
||||
BUTTON_EVENT_IN_BOTTOM_L,
|
||||
BUTTON_EVENT_IN_AREA,
|
||||
BUTTON_EVENT_UP,
|
||||
BUTTON_EVENT_PRESS,
|
||||
BUTTON_EVENT_RELEASE,
|
||||
BUTTON_EVENT_TIMEOUT,
|
||||
};
|
||||
|
||||
enum button_state {
|
||||
BUTTON_STATE_NONE,
|
||||
BUTTON_STATE_AREA,
|
||||
BUTTON_STATE_BOTTOM,
|
||||
BUTTON_STATE_BOTTOM_NEW,
|
||||
BUTTON_STATE_BOTTOM_TO_AREA,
|
||||
};
|
||||
|
||||
enum scroll_state {
|
||||
SCROLL_STATE_NONE,
|
||||
SCROLL_STATE_SCROLLING
|
||||
|
|
@ -77,10 +95,9 @@ struct tp_touch {
|
|||
bool dirty;
|
||||
bool fake; /* a fake touch */
|
||||
bool is_pointer; /* the pointer-controlling touch */
|
||||
bool is_pinned; /* holds the phys. button */
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
uint32_t millis;
|
||||
uint64_t millis;
|
||||
|
||||
struct {
|
||||
struct tp_motion samples[TOUCHPAD_HISTORY_LENGTH];
|
||||
|
|
@ -92,6 +109,24 @@ struct tp_touch {
|
|||
int32_t center_x;
|
||||
int32_t center_y;
|
||||
} hysteresis;
|
||||
|
||||
/* A pinned touchpoint is the one that pressed the physical button
|
||||
* on a clickpad. After the release, it won't move until the center
|
||||
* moves more than a threshold away from the original coordinates
|
||||
*/
|
||||
struct {
|
||||
bool is_pinned;
|
||||
int32_t center_x;
|
||||
int32_t center_y;
|
||||
} pinned;
|
||||
|
||||
/* Software-button state and timeout if applicable */
|
||||
struct {
|
||||
enum button_state state;
|
||||
/* We use button_event here so we can use == on events */
|
||||
enum button_event curr;
|
||||
uint64_t timeout;
|
||||
} button;
|
||||
};
|
||||
|
||||
struct tp_dispatch {
|
||||
|
|
@ -119,9 +154,28 @@ struct tp_dispatch {
|
|||
} accel;
|
||||
|
||||
struct {
|
||||
bool has_buttons; /* true for physical LMR buttons */
|
||||
bool is_clickpad; /* true for clickpads */
|
||||
bool use_clickfinger; /* number of fingers decides button number */
|
||||
bool click_pending;
|
||||
uint32_t state;
|
||||
uint32_t old_state;
|
||||
uint32_t motion_dist; /* for pinned touches */
|
||||
unsigned int active; /* currently active button, for release event */
|
||||
|
||||
/* Only used for clickpads. The software button area is always
|
||||
* a horizontal strip across the touchpad. Depending on the
|
||||
* rightbutton_left_edge value, the buttons are split according to the
|
||||
* edge settings.
|
||||
*/
|
||||
struct {
|
||||
int32_t top_edge;
|
||||
int32_t rightbutton_left_edge;
|
||||
} area;
|
||||
|
||||
unsigned int timeout; /* current timeout in ms */
|
||||
|
||||
int timer_fd;
|
||||
struct libinput_source *source;
|
||||
} buttons; /* physical buttons */
|
||||
|
||||
struct {
|
||||
|
|
@ -146,11 +200,14 @@ struct tp_dispatch {
|
|||
void
|
||||
tp_get_delta(struct tp_touch *t, double *dx, double *dy);
|
||||
|
||||
void
|
||||
tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t);
|
||||
|
||||
int
|
||||
tp_tap_handle_state(struct tp_dispatch *tp, uint32_t time);
|
||||
tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time);
|
||||
|
||||
unsigned int
|
||||
tp_tap_handle_timeout(struct tp_dispatch *tp, uint32_t time);
|
||||
tp_tap_handle_timeout(struct tp_dispatch *tp, uint64_t time);
|
||||
|
||||
int
|
||||
tp_init_tap(struct tp_dispatch *tp);
|
||||
|
|
@ -158,4 +215,24 @@ tp_init_tap(struct tp_dispatch *tp);
|
|||
void
|
||||
tp_destroy_tap(struct tp_dispatch *tp);
|
||||
|
||||
int
|
||||
tp_init_buttons(struct tp_dispatch *tp, struct evdev_device *device);
|
||||
|
||||
void
|
||||
tp_destroy_buttons(struct tp_dispatch *tp);
|
||||
|
||||
int
|
||||
tp_process_button(struct tp_dispatch *tp,
|
||||
const struct input_event *e,
|
||||
uint64_t time);
|
||||
|
||||
int
|
||||
tp_post_button_events(struct tp_dispatch *tp, uint64_t time);
|
||||
|
||||
int
|
||||
tp_button_handle_state(struct tp_dispatch *tp, uint64_t time);
|
||||
|
||||
int
|
||||
tp_button_touch_active(struct tp_dispatch *tp, struct tp_touch *t);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ static double
|
|||
touchpad_profile(struct motion_filter *filter,
|
||||
void *data,
|
||||
double velocity,
|
||||
uint32_t time)
|
||||
uint64_t time)
|
||||
{
|
||||
struct touchpad_dispatch *touchpad =
|
||||
(struct touchpad_dispatch *) data;
|
||||
|
|
@ -273,7 +273,7 @@ touchpad_get_delta(struct touchpad_dispatch *touchpad, double *dx, double *dy)
|
|||
|
||||
static void
|
||||
filter_motion(struct touchpad_dispatch *touchpad,
|
||||
double *dx, double *dy, uint32_t time)
|
||||
double *dx, double *dy, uint64_t time)
|
||||
{
|
||||
struct motion_params motion;
|
||||
|
||||
|
|
@ -287,7 +287,7 @@ filter_motion(struct touchpad_dispatch *touchpad,
|
|||
}
|
||||
|
||||
static void
|
||||
notify_button_pressed(struct touchpad_dispatch *touchpad, uint32_t time)
|
||||
notify_button_pressed(struct touchpad_dispatch *touchpad, uint64_t time)
|
||||
{
|
||||
pointer_notify_button(
|
||||
&touchpad->device->base,
|
||||
|
|
@ -297,7 +297,7 @@ notify_button_pressed(struct touchpad_dispatch *touchpad, uint32_t time)
|
|||
}
|
||||
|
||||
static void
|
||||
notify_button_released(struct touchpad_dispatch *touchpad, uint32_t time)
|
||||
notify_button_released(struct touchpad_dispatch *touchpad, uint64_t time)
|
||||
{
|
||||
pointer_notify_button(
|
||||
&touchpad->device->base,
|
||||
|
|
@ -307,16 +307,16 @@ notify_button_released(struct touchpad_dispatch *touchpad, uint32_t time)
|
|||
}
|
||||
|
||||
static void
|
||||
notify_tap(struct touchpad_dispatch *touchpad, uint32_t time)
|
||||
notify_tap(struct touchpad_dispatch *touchpad, uint64_t time)
|
||||
{
|
||||
notify_button_pressed(touchpad, time);
|
||||
notify_button_released(touchpad, time);
|
||||
}
|
||||
|
||||
static void
|
||||
process_fsm_events(struct touchpad_dispatch *touchpad, uint32_t time)
|
||||
process_fsm_events(struct touchpad_dispatch *touchpad, uint64_t time)
|
||||
{
|
||||
uint32_t timeout = UINT32_MAX;
|
||||
uint64_t timeout = UINT64_MAX;
|
||||
enum fsm_event event;
|
||||
unsigned int i;
|
||||
|
||||
|
|
@ -398,7 +398,7 @@ process_fsm_events(struct touchpad_dispatch *touchpad, uint32_t time)
|
|||
}
|
||||
}
|
||||
|
||||
if (timeout != UINT32_MAX) {
|
||||
if (timeout != UINT64_MAX) {
|
||||
struct itimerspec its;
|
||||
|
||||
its.it_interval.tv_sec = 0;
|
||||
|
|
@ -447,7 +447,7 @@ fsm_timeout_handler(void *data)
|
|||
uint64_t expires;
|
||||
int len;
|
||||
struct timespec ts;
|
||||
uint32_t now;
|
||||
uint64_t now;
|
||||
|
||||
len = read(touchpad->fsm.timer.fd, &expires, sizeof expires);
|
||||
if (len != sizeof expires)
|
||||
|
|
@ -458,7 +458,7 @@ fsm_timeout_handler(void *data)
|
|||
|
||||
if (touchpad->fsm.events_count == 0) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
now = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
|
||||
now = ts.tv_sec * 1000ULL + ts.tv_nsec / 1000000;
|
||||
|
||||
push_fsm_event(touchpad, FSM_EVENT_TIMEOUT);
|
||||
process_fsm_events(touchpad, now);
|
||||
|
|
@ -466,7 +466,7 @@ fsm_timeout_handler(void *data)
|
|||
}
|
||||
|
||||
static void
|
||||
touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time)
|
||||
touchpad_update_state(struct touchpad_dispatch *touchpad, uint64_t time)
|
||||
{
|
||||
int motion_index;
|
||||
int center_x, center_y;
|
||||
|
|
@ -618,7 +618,7 @@ static inline void
|
|||
process_key(struct touchpad_dispatch *touchpad,
|
||||
struct evdev_device *device,
|
||||
struct input_event *e,
|
||||
uint32_t time)
|
||||
uint64_t time)
|
||||
{
|
||||
uint32_t code;
|
||||
|
||||
|
|
@ -685,7 +685,7 @@ static void
|
|||
touchpad_process(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
struct input_event *e,
|
||||
uint32_t time)
|
||||
uint64_t time)
|
||||
{
|
||||
struct touchpad_dispatch *touchpad =
|
||||
(struct touchpad_dispatch *) dispatch;
|
||||
|
|
|
|||
12
src/evdev.c
12
src/evdev.c
|
|
@ -110,7 +110,7 @@ evdev_device_transform_y(struct evdev_device *device,
|
|||
}
|
||||
|
||||
static void
|
||||
evdev_flush_pending_event(struct evdev_device *device, uint32_t time)
|
||||
evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
||||
{
|
||||
int32_t cx, cy;
|
||||
li_fixed_t x, y;
|
||||
|
|
@ -309,7 +309,7 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time)
|
|||
static void
|
||||
evdev_process_touch(struct evdev_device *device,
|
||||
struct input_event *e,
|
||||
uint32_t time)
|
||||
uint64_t time)
|
||||
{
|
||||
switch (e->code) {
|
||||
case ABS_MT_SLOT:
|
||||
|
|
@ -358,7 +358,7 @@ evdev_process_absolute_motion(struct evdev_device *device,
|
|||
|
||||
static inline void
|
||||
evdev_process_relative(struct evdev_device *device,
|
||||
struct input_event *e, uint32_t time)
|
||||
struct input_event *e, uint64_t time)
|
||||
{
|
||||
struct libinput_device *base = &device->base;
|
||||
|
||||
|
|
@ -406,7 +406,7 @@ evdev_process_relative(struct evdev_device *device,
|
|||
static inline void
|
||||
evdev_process_absolute(struct evdev_device *device,
|
||||
struct input_event *e,
|
||||
uint32_t time)
|
||||
uint64_t time)
|
||||
{
|
||||
if (device->is_mt) {
|
||||
evdev_process_touch(device, e, time);
|
||||
|
|
@ -441,7 +441,7 @@ static void
|
|||
fallback_process(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
struct input_event *event,
|
||||
uint32_t time)
|
||||
uint64_t time)
|
||||
{
|
||||
int need_frame = 0;
|
||||
|
||||
|
|
@ -491,7 +491,7 @@ static inline void
|
|||
evdev_process_event(struct evdev_device *device, struct input_event *e)
|
||||
{
|
||||
struct evdev_dispatch *dispatch = device->dispatch;
|
||||
uint32_t time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
|
||||
uint64_t time = e->time.tv_sec * 1000ULL + e->time.tv_usec / 1000;
|
||||
|
||||
dispatch->interface->process(dispatch, device, e, time);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ struct evdev_dispatch_interface {
|
|||
void (*process)(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
struct input_event *event,
|
||||
uint32_t time);
|
||||
uint64_t time);
|
||||
|
||||
/* Destroy an event dispatch handler and free all its resources. */
|
||||
void (*destroy)(struct evdev_dispatch *dispatch);
|
||||
|
|
|
|||
16
src/filter.c
16
src/filter.c
|
|
@ -32,7 +32,7 @@
|
|||
void
|
||||
filter_dispatch(struct motion_filter *filter,
|
||||
struct motion_params *motion,
|
||||
void *data, uint32_t time)
|
||||
void *data, uint64_t time)
|
||||
{
|
||||
filter->interface->filter(filter, motion, data, time);
|
||||
}
|
||||
|
|
@ -48,7 +48,7 @@ filter_dispatch(struct motion_filter *filter,
|
|||
struct pointer_tracker {
|
||||
double dx;
|
||||
double dy;
|
||||
uint32_t time;
|
||||
uint64_t time;
|
||||
int dir;
|
||||
};
|
||||
|
||||
|
|
@ -128,7 +128,7 @@ get_direction(int dx, int dy)
|
|||
static void
|
||||
feed_trackers(struct pointer_accelerator *accel,
|
||||
double dx, double dy,
|
||||
uint32_t time)
|
||||
uint64_t time)
|
||||
{
|
||||
int i, current;
|
||||
struct pointer_tracker *trackers = accel->trackers;
|
||||
|
|
@ -157,7 +157,7 @@ tracker_by_offset(struct pointer_accelerator *accel, unsigned int offset)
|
|||
}
|
||||
|
||||
static double
|
||||
calculate_tracker_velocity(struct pointer_tracker *tracker, uint32_t time)
|
||||
calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time)
|
||||
{
|
||||
int dx;
|
||||
int dy;
|
||||
|
|
@ -170,7 +170,7 @@ calculate_tracker_velocity(struct pointer_tracker *tracker, uint32_t time)
|
|||
}
|
||||
|
||||
static double
|
||||
calculate_velocity(struct pointer_accelerator *accel, uint32_t time)
|
||||
calculate_velocity(struct pointer_accelerator *accel, uint64_t time)
|
||||
{
|
||||
struct pointer_tracker *tracker;
|
||||
double velocity;
|
||||
|
|
@ -224,14 +224,14 @@ calculate_velocity(struct pointer_accelerator *accel, uint32_t time)
|
|||
|
||||
static double
|
||||
acceleration_profile(struct pointer_accelerator *accel,
|
||||
void *data, double velocity, uint32_t time)
|
||||
void *data, double velocity, uint64_t time)
|
||||
{
|
||||
return accel->profile(&accel->base, data, velocity, time);
|
||||
}
|
||||
|
||||
static double
|
||||
calculate_acceleration(struct pointer_accelerator *accel,
|
||||
void *data, double velocity, uint32_t time)
|
||||
void *data, double velocity, uint64_t time)
|
||||
{
|
||||
double factor;
|
||||
|
||||
|
|
@ -273,7 +273,7 @@ apply_softening(struct pointer_accelerator *accel,
|
|||
static void
|
||||
accelerator_filter(struct motion_filter *filter,
|
||||
struct motion_params *motion,
|
||||
void *data, uint32_t time)
|
||||
void *data, uint64_t time)
|
||||
{
|
||||
struct pointer_accelerator *accel =
|
||||
(struct pointer_accelerator *) filter;
|
||||
|
|
|
|||
|
|
@ -34,13 +34,13 @@ struct motion_filter;
|
|||
void
|
||||
filter_dispatch(struct motion_filter *filter,
|
||||
struct motion_params *motion,
|
||||
void *data, uint32_t time);
|
||||
void *data, uint64_t time);
|
||||
|
||||
|
||||
struct motion_filter_interface {
|
||||
void (*filter)(struct motion_filter *filter,
|
||||
struct motion_params *motion,
|
||||
void *data, uint32_t time);
|
||||
void *data, uint64_t time);
|
||||
void (*destroy)(struct motion_filter *filter);
|
||||
};
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ create_linear_acceleration_filter(double speed);
|
|||
typedef double (*accel_profile_func_t)(struct motion_filter *filter,
|
||||
void *data,
|
||||
double velocity,
|
||||
uint32_t time);
|
||||
uint64_t time);
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelator_filter(accel_profile_func_t filter);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,46 @@ extern "C" {
|
|||
* behind an API.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page tpbuttons Touchpad button behavior
|
||||
*
|
||||
* For touchpad devices without physical buttons, libinput enables an
|
||||
* emulated right button area through either of two methods.
|
||||
*
|
||||
* Software button areas
|
||||
* =====================
|
||||
* On most touchpads, the bottom area of the touchpad is split into a a left
|
||||
* and a right-button area. Pressing the touchpad down with a finger in
|
||||
* those areas will generate clicks as shown in the diagram below:
|
||||
*
|
||||
* @code
|
||||
+------------------------+
|
||||
| |
|
||||
| |
|
||||
| LEFT |
|
||||
| |
|
||||
| |
|
||||
+------------------------+
|
||||
| LEFT | RIGHT |
|
||||
+------------------------+
|
||||
* @endcode
|
||||
*
|
||||
* Generally, the touchpad will emulate a right-button click if the finger
|
||||
* was set down in the right button area and did not leave the
|
||||
* right button area before clicking, even if another finger was already
|
||||
* down on the touchpad in another area.
|
||||
* A middle click is generated by clicking the touchpad when one finger is
|
||||
* in the bottom left button area, and one finger is in the botton right
|
||||
* button area.
|
||||
* The exact behavior of the touchpad is implementation-dependent.
|
||||
*
|
||||
* Clickfinger
|
||||
* ===========
|
||||
* On Apple touchpads, no button areas are provided. Instead, use a
|
||||
* two-finger click for a right button click, and a three-finger click for a
|
||||
* middle button click.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup fixed_point
|
||||
*
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ static int events[] = {
|
|||
EV_KEY, BTN_TOOL_DOUBLETAP,
|
||||
EV_KEY, BTN_TOOL_TRIPLETAP,
|
||||
EV_KEY, BTN_TOOL_QUADTAP,
|
||||
INPUT_PROP_MAX, INPUT_PROP_BUTTONPAD,
|
||||
-1, -1
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -70,10 +70,10 @@ START_TEST(touchpad_2fg_no_motion)
|
|||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_down(dev, 1, 70, 70);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 80, 50, 5);
|
||||
litest_touch_move_to(dev, 1, 70, 70, 80, 50, 5);
|
||||
litest_touch_down(dev, 0, 20, 20);
|
||||
litest_touch_down(dev, 1, 70, 20);
|
||||
litest_touch_move_to(dev, 0, 20, 20, 80, 80, 5);
|
||||
litest_touch_move_to(dev, 1, 70, 20, 80, 50, 5);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
|
||||
|
|
@ -217,7 +217,7 @@ END_TEST
|
|||
|
||||
START_TEST(touchpad_1fg_clickfinger)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct litest_device *dev = litest_create_device(LITEST_BCM5974);
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
|
|
@ -237,12 +237,14 @@ START_TEST(touchpad_1fg_clickfinger)
|
|||
LIBINPUT_POINTER_BUTTON_STATE_PRESSED);
|
||||
assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_POINTER_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_delete_device(dev);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_2fg_clickfinger)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct litest_device *dev = litest_create_device(LITEST_BCM5974);
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
|
|
@ -264,6 +266,8 @@ START_TEST(touchpad_2fg_clickfinger)
|
|||
LIBINPUT_POINTER_BUTTON_STATE_PRESSED);
|
||||
assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_POINTER_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_delete_device(dev);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
|
@ -362,8 +366,8 @@ int main(int argc, char **argv) {
|
|||
litest_add("touchpad:tap", touchpad_1fg_tap_n_drag, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:tap", touchpad_2fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
|
||||
litest_add("touchpad:clickfinger", touchpad_1fg_clickfinger, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:clickfinger", touchpad_2fg_clickfinger, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add_no_device("touchpad:clickfinger", touchpad_1fg_clickfinger);
|
||||
litest_add_no_device("touchpad:clickfinger", touchpad_2fg_clickfinger);
|
||||
|
||||
litest_add("touchpad:click", touchpad_btn_left, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
litest_add("touchpad:click", clickpad_btn_left, LITEST_CLICKPAD, LITEST_ANY);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue