touchpad: Add edge-scrolling support

Add edge-scrolling support for non multi-touch touchpads as well as for
users who prefer edge-scrolling (as long as they don't have a clickpad).

Note the percentage to use of the width / height as scroll-edge differs from
one manufacturer to the next, the various per model percentages were taken
from xf86-input-synaptics.

BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=85635
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Hans de Goede 2014-11-24 12:16:06 +01:00 committed by Peter Hutterer
parent 8b6572bfae
commit 6a4ceed2b9
5 changed files with 767 additions and 11 deletions

View file

@ -0,0 +1,262 @@
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1490px" height="1399px" version="1.1">
<defs/>
<g transform="translate(0.5,0.5)">
<ellipse cx="261" cy="143" rx="63" ry="45.5" fill="#ccccff" stroke="#000000" stroke-width="2" pointer-events="none"/>
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
<text x="261" y="126">NONE</text>
<text x="261" y="140">on-entry:</text>
<text x="261" y="154">edge = none</text>
<text x="261" y="168">threshold = def</text>
</g>
<rect x="30" y="386" 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="105" y="419">EDGE_NEW</text>
<text x="105" y="433">on-entry:</text>
<text x="105" y="447">edge = get_edge()</text>
<text x="105" y="461">set_timer()</text>
</g>
<rect x="348" y="386" 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="413" y="419">AREA</text>
<text x="413" y="433">on-entry:</text>
<text x="413" y="447">edge = none</text>
<text x="413" y="461">set_pointer()</text>
</g>
<path d="M 237 7 C 239 4 243 2 246 2 L 275 2 C 278 2 282 4 284 7 L 301 30 C 301 31 301 33 301 34 L 284 57 C 282 60 278 62 275 62 L 246 62 C 243 62 239 60 237 57 L 220 34 C 220 33 220 31 220 30 L 237 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="261" y="36">release</text>
</g>
<path d="M 237 222 C 239 219 243 217 246 217 L 276 217 C 279 217 283 219 285 222 L 303 245 C 303 246 303 248 303 249 L 285 272 C 283 275 279 277 276 277 L 246 277 C 243 277 239 275 237 272 L 219 249 C 219 248 219 246 219 245 L 237 222 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="261" y="251">touch</text>
</g>
<path d="M 261 188 L 261 211" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 261 216 L 258 209 L 261 211 L 265 209 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 218 535 C 223 531 229 528 235 528 L 285 528 C 291 528 297 531 302 535 L 331 570 C 332 571 332 574 331 575 L 302 610 C 297 614 291 617 285 617 L 235 617 C 229 617 223 614 218 610 L 189 575 C 188 574 188 571 189 570 L 218 535 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="260" y="563">touch,</text>
<text x="260" y="577">edge &amp;= get_edge()</text>
</g>
<path d="M 220 526 L 158 487" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 224 529 L 217 528 L 220 526 L 220 522 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 105 617 L 105 650" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 105 656 L 101 649 L 105 650 L 108 649 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 478 436 L 498 436 Q 508 436 508 426 L 508 42 Q 508 32 498 32 L 307 32" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 302 32 L 309 29 L 307 32 L 309 36 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 261 62 L 261 71 Q 261 80 261 85 L 261 91" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 261 96 L 257 89 L 261 91 L 264 89 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<ellipse cx="1133" cy="67" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
<path d="M 1133 82 L 1133 110 Q 1133 120 1133 130 L 1133 155" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1129 147 L 1133 156 L 1138 147" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<rect x="1083" y="12" 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="1133" y="36">tp_edge_scroll_post_events()</text>
</g>
<path d="M 1133 212 L 1193 242 L 1133 272 L 1073 242 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="1133" y="246">dirty?</text>
</g>
<path d="M 1193 242 L 1278 242 Q 1288 242 1298 242 L 1456 242" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1448 247 L 1457 242 L 1448 238" 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="1225" y="223" width="18" height="18" stroke-width="0"/>
<text x="1226" y="236">no</text>
</g>
<path d="M 1133 272 L 1133 285 Q 1133 295 1133 305 L 1133 316" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1129 308 L 1133 317 L 1138 308" 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="1150" y="292" width="24" height="18" stroke-width="0"/>
<text x="1150" y="302">yes</text>
</g>
<ellipse cx="1473" cy="242" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
<ellipse cx="1473" cy="242" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
<rect x="1033" y="97" width="200" 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="1133" y="115">current = buttons.state &amp; 0x01</text>
<text x="1133" y="129">old = buttons.old_state &amp; 0x01</text>
<text x="1133" y="143">button = 0</text>
<text x="1133" y="157">is_top = 0</text>
</g>
<path d="M 1133 167 L 1133 180 Q 1133 190 1133 200 L 1133 210" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1129 202 L 1133 211 L 1138 202" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<rect x="1237" y="436" width="188" height="50" rx="20" ry="20" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
<text x="1331" y="458">notify_axis(last_axis, 0.0)</text>
<text x="1331" y="472">last_axis = -1</text>
</g>
<path d="M 1134 516 L 1194 552 L 1134 587 L 1073 552 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="1134" y="556">edge == right</text>
</g>
<path d="M 1194 552 L 1268 552 Q 1278 552 1278 553 L 1278 554 Q 1278 554 1268 554 L 1250 554" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1258 550 L 1249 554 L 1258 559" 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="1202" y="559" width="24" height="18" stroke-width="0"/>
<text x="1203" y="569">yes</text>
</g>
<rect x="1248" y="534" 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="1328" y="551">axis = scroll_vertical</text>
<text x="1328" y="565">delta = dy</text>
</g>
<path d="M 1408 554 L 1468 554 Q 1478 554 1478 564 L 1478 952 Q 1478 962 1468 962 L 1233 962" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1241 958 L 1232 962 L 1241 967" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1133 318 L 1196 352 L 1133 387 L 1071 352 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="1133" y="356">edge == none</text>
</g>
<path d="M 1134 386 L 1134 441 Q 1134 451 1134 461 L 1134 514" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1129 506 L 1134 515 L 1138 506" 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="1135" y="449" width="18" height="18" stroke-width="0"/>
<text x="1136" y="458">no</text>
</g>
<path d="M 1133 657 L 1194 692 L 1133 727 L 1072 692 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="1133" y="696">edge == bottom</text>
</g>
<path d="M 1194 692 L 1208 692 Q 1218 692 1228 692 L 1249 692" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1241 697 L 1250 692 L 1241 688" 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="1213" y="700" width="24" height="18" stroke-width="0"/>
<text x="1214" y="709">yes</text>
</g>
<path d="M 1134 587 L 1133 587 Q 1133 587 1133 597 L 1133 647 Q 1133 657 1133 656 L 1133 655" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1129 647 L 1133 656 L 1138 647" 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="1135" y="607" width="18" height="18" stroke-width="0"/>
<text x="1135" y="621">no</text>
</g>
<rect x="1251" y="672" 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="1331" y="689">axis = scroll_horizontal</text>
<text x="1331" y="703">delta = dx</text>
</g>
<path d="M 1133 727 L 1133 727 Q 1134 727 1134 737 L 1134 807 Q 1134 817 1134 816 L 1134 815" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1129 807 L 1134 816 L 1138 807" 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="1135" y="756" width="18" height="18" stroke-width="0"/>
<text x="1136" y="770">no</text>
</g>
<rect x="1036" y="917" width="195" height="90" rx="36" ry="36" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
<text x="1134" y="966">get_delta()</text>
</g>
<path d="M 1134 1007 L 1134 1037 Q 1134 1047 1134 1057 L 1134 1070" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1129 1062 L 1134 1071 L 1138 1062" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1411 692 L 1468 692 Q 1478 692 1478 702 L 1478 952 Q 1478 962 1468 962 L 1233 962" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1241 958 L 1232 962 L 1241 967" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<rect x="1031" y="1197" width="205" height="90" rx="36" ry="36" fill="#ffffc0" stroke="#ff0000" pointer-events="none"/>
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
<text x="1134" y="1232">notify_axis(axis, delta)</text>
<text x="1134" y="1246">last_axis = axis</text>
<text x="1134" y="1260">emit(scroll_event_posted)</text>
</g>
<path d="M 1134 1072 L 1200 1107 L 1134 1142 L 1067 1107 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="1134" y="1111">delta &lt; threshold</text>
</g>
<path d="M 1200 1107 L 1318 1107 Q 1328 1107 1338 1107 L 1456 1107" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1448 1112 L 1457 1107 L 1448 1103" 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="1259" y="1118" width="24" height="18" stroke-width="0"/>
<text x="1260" y="1131">yes</text>
</g>
<path d="M 1134 1142 L 1134 1160 Q 1134 1170 1134 1180 L 1134 1195" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1129 1187 L 1134 1196 L 1138 1187" 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="1135" y="1150" width="18" height="18" stroke-width="0"/>
<text x="1136" y="1159">no</text>
</g>
<ellipse cx="1473" cy="1107" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
<ellipse cx="1473" cy="1107" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
<ellipse cx="1473" cy="352" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
<ellipse cx="1473" cy="352" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
<path d="M 1331 318 L 1394 352 L 1331 387 L 1269 352 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="1331" y="356">last_axis != -1</text>
</g>
<rect x="30" y="657" 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="105" y="697">EDGE</text>
<text x="105" y="711">on-entry:</text>
<text x="105" y="725">threshold = 0.01</text>
</g>
<path d="M 30 707 L 18 707 Q 8 707 8 697 L 8 42 Q 8 32 18 32 L 214 32" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 219 32 L 212 36 L 214 32 L 212 29 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 30 436 L 18 436 Q 8 436 8 426 L 8 42 Q 8 32 18 32 L 214 32" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 219 32 L 212 36 L 214 32 L 212 29 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 64 535 C 68 531 74 528 80 528 L 130 528 C 136 528 142 531 146 535 L 175 570 C 176 571 176 574 175 575 L 146 610 C 142 614 136 617 130 617 L 80 617 C 74 617 68 614 64 610 L 35 575 C 34 574 34 571 35 570 L 64 535 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="105" y="563">timeout ||</text>
<text x="105" y="577">scroll_event_posted</text>
</g>
<path d="M 105 487 L 105 522" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 105 527 L 102 520 L 105 522 L 109 520 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 260 528 L 261 472" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 261 467 L 264 474 L 261 472 L 257 474 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1196 352 L 1222 352 Q 1232 352 1242 352 L 1266 352" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1258 357 L 1267 352 L 1258 348" 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="1224" y="360" width="24" height="18" stroke-width="0"/>
<text x="1224" y="369">yes</text>
</g>
<path d="M 1331 387 L 1331 401 Q 1331 411 1331 421 L 1331 434" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1327 426 L 1331 435 L 1336 426" 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="1333" y="394" width="24" height="18" stroke-width="0"/>
<text x="1333" y="403">yes</text>
</g>
<path d="M 1394 352 L 1408 352 Q 1418 352 1428 352 L 1456 352" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1448 357 L 1457 352 L 1448 348" 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="1417" y="360" width="18" height="18" stroke-width="0"/>
<text x="1418" y="369">no</text>
</g>
<ellipse cx="1473" cy="461" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
<ellipse cx="1473" cy="461" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
<path d="M 1425 461 L 1438 461 Q 1448 461 1452 461 L 1456 461" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1448 466 L 1457 461 L 1448 457" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<ellipse cx="1134" cy="832" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
<ellipse cx="1134" cy="832" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
<ellipse cx="1134" cy="1382" rx="11" ry="11" fill="#000000" stroke="#ff0000" pointer-events="none"/>
<ellipse cx="1134" cy="1382" rx="15" ry="15" fill="transparent" stroke="#ff0000" pointer-events="none"/>
<path d="M 1134 1287 L 1134 1365" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 1130 1359 L 1134 1366 L 1137 1359" fill="none" stroke="#ff0000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 261 277 L 261 299" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 261 304 L 258 297 L 261 299 L 265 297 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 208 337 L 115 337 Q 105 337 105 347 L 105 376 Q 105 386 105 382 L 105 378" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 105 385 L 100 376 L 105 378 L 109 376 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<g fill="#000000" font-family="Helvetica" font-size="11px">
<rect fill="#ffffff" stroke="none" x="174" y="345" width="24" height="18" stroke-width="0"/>
<text x="175" y="354">yes</text>
</g>
<path d="M 314 337 L 403 337 Q 413 337 413 347 L 413 376 Q 413 386 413 382 L 413 378" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 413 385 L 408 376 L 413 378 L 417 376 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<g fill="#000000" font-family="Helvetica" font-size="11px">
<rect fill="#ffffff" stroke="none" x="350" y="345" width="18" height="18" stroke-width="0"/>
<text x="350" y="354">no</text>
</g>
<path d="M 261 305 L 314 337 L 261 369 L 208 337 Z" fill="#ffd966" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
<text x="261" y="341">get_edge()</text>
</g>
<path d="M 261 406 L 309 436 L 261 466 L 213 436 Z" fill="#ffd966" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<g fill="#000000" font-family="Helvetica" text-anchor="middle" font-size="12px">
<text x="261" y="440">edge</text>
</g>
<path d="M 309 436 L 319 436 Q 328 436 334 436 L 340 436" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 347 436 L 338 441 L 340 436 L 338 432 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<g fill="#000000" font-family="Helvetica" font-size="11px">
<rect fill="#ffffff" stroke="none" x="311" y="444" width="18" height="18" stroke-width="0"/>
<text x="311" y="453">no</text>
</g>
<path d="M 213 436 L 211 436 Q 208 436 198 436 L 188 436" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<path d="M 181 436 L 190 432 L 188 436 L 190 441 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/>
<g fill="#000000" font-family="Helvetica" font-size="11px">
<rect fill="#ffffff" stroke="none" x="189" y="444" width="24" height="18" stroke-width="0"/>
<text x="190" y="453">yes</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

View file

@ -15,6 +15,7 @@ libinput_la_SOURCES = \
evdev-mt-touchpad.h \ evdev-mt-touchpad.h \
evdev-mt-touchpad-tap.c \ evdev-mt-touchpad-tap.c \
evdev-mt-touchpad-buttons.c \ evdev-mt-touchpad-buttons.c \
evdev-mt-touchpad-edge-scroll.c \
filter.c \ filter.c \
filter.h \ filter.h \
filter-private.h \ filter-private.h \

View file

@ -0,0 +1,374 @@
/*
* 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 <math.h>
#include <string.h>
#include <unistd.h>
#include "linux/input.h"
#include "evdev-mt-touchpad.h"
#define DEFAULT_SCROLL_LOCK_TIMEOUT 300 /* ms */
/* Use a reasonably large threshold until locked into scrolling mode, to
avoid accidentally locking in scrolling mode when trying to use the entire
touchpad to move the pointer. The user can wait for the timeout to trigger
to do a small scroll. */
/* In mm for touchpads with valid resolution, see tp_init_accel() */
#define DEFAULT_SCROLL_THRESHOLD 10.0
enum scroll_event {
SCROLL_EVENT_TOUCH,
SCROLL_EVENT_MOTION,
SCROLL_EVENT_RELEASE,
SCROLL_EVENT_TIMEOUT,
SCROLL_EVENT_POSTED,
};
static uint32_t
tp_touch_get_edge(struct tp_dispatch *tp, struct tp_touch *touch)
{
uint32_t edge = EDGE_NONE;
if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE)
return EDGE_NONE;
if (touch->x > tp->scroll.right_edge)
edge |= EDGE_RIGHT;
if (touch->y > tp->scroll.bottom_edge)
edge |= EDGE_BOTTOM;
return edge;
}
static void
tp_edge_scroll_set_state(struct tp_dispatch *tp,
struct tp_touch *t,
enum tp_edge_scroll_touch_state state)
{
libinput_timer_cancel(&t->scroll.timer);
t->scroll.state = state;
switch (state) {
case EDGE_SCROLL_TOUCH_STATE_NONE:
t->scroll.edge = EDGE_NONE;
t->scroll.threshold = DEFAULT_SCROLL_THRESHOLD;
break;
case EDGE_SCROLL_TOUCH_STATE_EDGE_NEW:
t->scroll.edge = tp_touch_get_edge(tp, t);
libinput_timer_set(&t->scroll.timer,
t->millis + DEFAULT_SCROLL_LOCK_TIMEOUT);
break;
case EDGE_SCROLL_TOUCH_STATE_EDGE:
t->scroll.threshold = 0.01; /* Do not allow 0.0 events */
break;
case EDGE_SCROLL_TOUCH_STATE_AREA:
t->scroll.edge = EDGE_NONE;
tp_set_pointer(tp, t);
break;
}
}
static void
tp_edge_scroll_handle_none(struct tp_dispatch *tp,
struct tp_touch *t,
enum scroll_event event)
{
struct libinput *libinput = tp->device->base.seat->libinput;
switch (event) {
case SCROLL_EVENT_TOUCH:
if (tp_touch_get_edge(tp, t)) {
tp_edge_scroll_set_state(tp, t,
EDGE_SCROLL_TOUCH_STATE_EDGE_NEW);
} else {
tp_edge_scroll_set_state(tp, t,
EDGE_SCROLL_TOUCH_STATE_AREA);
}
break;
case SCROLL_EVENT_MOTION:
case SCROLL_EVENT_RELEASE:
case SCROLL_EVENT_TIMEOUT:
case SCROLL_EVENT_POSTED:
log_bug_libinput(libinput,
"unexpect scroll event in none state\n");
break;
}
}
static void
tp_edge_scroll_handle_edge_new(struct tp_dispatch *tp,
struct tp_touch *t,
enum scroll_event event)
{
struct libinput *libinput = tp->device->base.seat->libinput;
switch (event) {
case SCROLL_EVENT_TOUCH:
log_bug_libinput(libinput,
"unexpect scroll event in edge new state\n");
break;
case SCROLL_EVENT_MOTION:
t->scroll.edge &= tp_touch_get_edge(tp, t);
if (!t->scroll.edge)
tp_edge_scroll_set_state(tp, t,
EDGE_SCROLL_TOUCH_STATE_AREA);
break;
case SCROLL_EVENT_RELEASE:
tp_edge_scroll_set_state(tp, t, EDGE_SCROLL_TOUCH_STATE_NONE);
break;
case SCROLL_EVENT_TIMEOUT:
case SCROLL_EVENT_POSTED:
tp_edge_scroll_set_state(tp, t, EDGE_SCROLL_TOUCH_STATE_EDGE);
break;
}
}
static void
tp_edge_scroll_handle_edge(struct tp_dispatch *tp,
struct tp_touch *t,
enum scroll_event event)
{
struct libinput *libinput = tp->device->base.seat->libinput;
switch (event) {
case SCROLL_EVENT_TOUCH:
case SCROLL_EVENT_TIMEOUT:
log_bug_libinput(libinput,
"unexpect scroll event in edge state\n");
break;
case SCROLL_EVENT_MOTION:
/* If started at the bottom right, decide in which dir to scroll */
if (t->scroll.edge == (EDGE_RIGHT | EDGE_BOTTOM)) {
t->scroll.edge &= tp_touch_get_edge(tp, t);
if (!t->scroll.edge)
tp_edge_scroll_set_state(tp, t,
EDGE_SCROLL_TOUCH_STATE_AREA);
}
break;
case SCROLL_EVENT_RELEASE:
tp_edge_scroll_set_state(tp, t, EDGE_SCROLL_TOUCH_STATE_NONE);
break;
case SCROLL_EVENT_POSTED:
break;
}
}
static void
tp_edge_scroll_handle_area(struct tp_dispatch *tp,
struct tp_touch *t,
enum scroll_event event)
{
struct libinput *libinput = tp->device->base.seat->libinput;
switch (event) {
case SCROLL_EVENT_TOUCH:
case SCROLL_EVENT_TIMEOUT:
case SCROLL_EVENT_POSTED:
log_bug_libinput(libinput,
"unexpect scroll event in area state\n");
break;
case SCROLL_EVENT_MOTION:
break;
case SCROLL_EVENT_RELEASE:
tp_edge_scroll_set_state(tp, t, EDGE_SCROLL_TOUCH_STATE_NONE);
break;
}
}
static void
tp_edge_scroll_handle_event(struct tp_dispatch *tp,
struct tp_touch *t,
enum scroll_event event)
{
switch (t->scroll.state) {
case EDGE_SCROLL_TOUCH_STATE_NONE:
tp_edge_scroll_handle_none(tp, t, event);
break;
case EDGE_SCROLL_TOUCH_STATE_EDGE_NEW:
tp_edge_scroll_handle_edge_new(tp, t, event);
break;
case EDGE_SCROLL_TOUCH_STATE_EDGE:
tp_edge_scroll_handle_edge(tp, t, event);
break;
case EDGE_SCROLL_TOUCH_STATE_AREA:
tp_edge_scroll_handle_area(tp, t, event);
break;
}
}
static void
tp_edge_scroll_handle_timeout(uint64_t now, void *data)
{
struct tp_touch *t = data;
tp_edge_scroll_handle_event(t->tp, t, SCROLL_EVENT_TIMEOUT);
}
int
tp_edge_scroll_init(struct tp_dispatch *tp, struct evdev_device *device)
{
struct tp_touch *t;
int width, height;
int edge_width, edge_height;
width = device->abs.absinfo_x->maximum - device->abs.absinfo_x->minimum;
height = device->abs.absinfo_y->maximum - device->abs.absinfo_y->minimum;
switch (tp->model) {
case MODEL_ALPS:
edge_width = width * .15;
edge_height = height * .15;
break;
case MODEL_APPLETOUCH: /* unibody are all clickpads, so N/A */
edge_width = width * .085;
edge_height = height * .085;
break;
default:
/* For elantech and synaptics, note for lenovo #40 series,
* e.g. the T440s min/max are the absolute edges, not the
* recommended ones as usual with synaptics. But these are
* clickpads, so N/A.
*/
edge_width = width * .04;
edge_height = height * .054;
}
tp->scroll.right_edge = device->abs.absinfo_x->maximum - edge_width;
tp->scroll.bottom_edge = device->abs.absinfo_y->maximum - edge_height;
tp_for_each_touch(tp, t) {
t->scroll.direction = -1;
t->scroll.threshold = DEFAULT_SCROLL_THRESHOLD;
libinput_timer_init(&t->scroll.timer,
device->base.seat->libinput,
tp_edge_scroll_handle_timeout, t);
}
return 0;
}
void
tp_destroy_edge_scroll(struct tp_dispatch *tp)
{
struct tp_touch *t;
tp_for_each_touch(tp, t)
libinput_timer_cancel(&t->scroll.timer);
}
void
tp_edge_scroll_handle_state(struct tp_dispatch *tp, uint64_t time)
{
struct tp_touch *t;
tp_for_each_touch(tp, t) {
if (!t->dirty)
continue;
switch (t->state) {
case TOUCH_NONE:
break;
case TOUCH_BEGIN:
tp_edge_scroll_handle_event(tp, t, SCROLL_EVENT_TOUCH);
break;
case TOUCH_UPDATE:
tp_edge_scroll_handle_event(tp, t, SCROLL_EVENT_MOTION);
break;
case TOUCH_END:
tp_edge_scroll_handle_event(tp, t, SCROLL_EVENT_RELEASE);
break;
}
}
}
int
tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
{
struct libinput_device *device = &tp->device->base;
struct tp_touch *t;
enum libinput_pointer_axis axis;
double dx, dy, *delta;
tp_for_each_touch(tp, t) {
if (!t->dirty)
continue;
switch (t->scroll.edge) {
case EDGE_NONE:
if (t->scroll.direction != -1) {
/* Send stop scroll event */
pointer_notify_axis(device, time,
t->scroll.direction, 0.0);
t->scroll.direction = -1;
}
continue;
case EDGE_RIGHT:
axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
delta = &dy;
break;
case EDGE_BOTTOM:
axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
delta = &dx;
break;
default: /* EDGE_RIGHT | EDGE_BOTTOM */
continue; /* Don't know direction yet, skip */
}
tp_get_delta(t, &dx, &dy);
tp_filter_motion(tp, &dx, &dy, time);
if (fabs(*delta) < t->scroll.threshold)
continue;
pointer_notify_axis(device, time, axis, *delta);
t->scroll.direction = axis;
tp_edge_scroll_handle_event(tp, t, SCROLL_EVENT_POSTED);
}
return 0; /* Edge touches are suppressed by edge_scroll_touch_active */
}
void
tp_edge_scroll_stop_events(struct tp_dispatch *tp, uint64_t time)
{
struct libinput_device *device = &tp->device->base;
struct tp_touch *t;
tp_for_each_touch(tp, t) {
if (t->scroll.direction != -1) {
pointer_notify_axis(device, time,
t->scroll.direction, 0.0);
t->scroll.direction = -1;
}
}
}
int
tp_edge_scroll_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
{
return t->scroll.state == EDGE_SCROLL_TOUCH_STATE_AREA;
}

View file

@ -56,7 +56,7 @@ tp_motion_history_offset(struct tp_touch *t, int offset)
return &t->history.samples[offset_index]; return &t->history.samples[offset_index];
} }
static void void
tp_filter_motion(struct tp_dispatch *tp, tp_filter_motion(struct tp_dispatch *tp,
double *dx, double *dy, uint64_t time) double *dx, double *dy, uint64_t time)
{ {
@ -339,7 +339,9 @@ tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
{ {
return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) && return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
!t->palm.is_palm && !t->palm.is_palm &&
!t->pinned.is_pinned && tp_button_touch_active(tp, t); !t->pinned.is_pinned &&
tp_button_touch_active(tp, t) &&
tp_edge_scroll_touch_active(tp, t);
} }
void void
@ -430,15 +432,12 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
} }
static int static int
tp_post_scroll_events(struct tp_dispatch *tp, uint64_t time) tp_twofinger_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
{ {
struct tp_touch *t; struct tp_touch *t;
int nfingers_down = 0; int nfingers_down = 0;
if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_2FG) /* No 2fg scrolling during tap-n-drag */
return 0;
/* No scrolling during tap-n-drag */
if (tp_tap_dragging(tp)) if (tp_tap_dragging(tp))
return 0; return 0;
@ -457,6 +456,60 @@ tp_post_scroll_events(struct tp_dispatch *tp, uint64_t time)
return 1; return 1;
} }
static void
tp_scroll_handle_state(struct tp_dispatch *tp, uint64_t time)
{
/* Note this must be always called, so that it knows the state of
* touches when the scroll-mode changes.
*/
tp_edge_scroll_handle_state(tp, time);
}
static int
tp_post_scroll_events(struct tp_dispatch *tp, uint64_t time)
{
struct libinput *libinput = tp->device->base.seat->libinput;
switch (tp->scroll.method) {
case LIBINPUT_CONFIG_SCROLL_NO_SCROLL:
break;
case LIBINPUT_CONFIG_SCROLL_2FG:
return tp_twofinger_scroll_post_events(tp, time);
case LIBINPUT_CONFIG_SCROLL_EDGE:
return tp_edge_scroll_post_events(tp, time);
case LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN:
log_bug_libinput(libinput, "Unexpected scroll mode\n");
break;
}
return 0;
}
static void
tp_stop_scroll_events(struct tp_dispatch *tp, uint64_t time)
{
struct libinput *libinput = tp->device->base.seat->libinput;
switch (tp->scroll.method) {
case LIBINPUT_CONFIG_SCROLL_NO_SCROLL:
break;
case LIBINPUT_CONFIG_SCROLL_2FG:
evdev_stop_scroll(tp->device, time);
break;
case LIBINPUT_CONFIG_SCROLL_EDGE:
tp_edge_scroll_stop_events(tp, time);
break;
case LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN:
log_bug_libinput(libinput, "Unexpected scroll mode\n");
break;
}
}
static void
tp_destroy_scroll(struct tp_dispatch *tp)
{
tp_destroy_edge_scroll(tp);
}
static void static void
tp_process_state(struct tp_dispatch *tp, uint64_t time) tp_process_state(struct tp_dispatch *tp, uint64_t time)
{ {
@ -490,6 +543,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
} }
tp_button_handle_state(tp, time); tp_button_handle_state(tp, time);
tp_scroll_handle_state(tp, time);
/* /*
* We have a physical button down event on a clickpad. To avoid * We have a physical button down event on a clickpad. To avoid
@ -525,6 +579,7 @@ tp_post_process_state(struct tp_dispatch *tp, uint64_t time)
tp->queued = TOUCHPAD_EVENT_NONE; tp->queued = TOUCHPAD_EVENT_NONE;
} }
static void static void
tp_post_events(struct tp_dispatch *tp, uint64_t time) tp_post_events(struct tp_dispatch *tp, uint64_t time)
{ {
@ -542,7 +597,7 @@ tp_post_events(struct tp_dispatch *tp, uint64_t time)
filter_motion |= tp_post_button_events(tp, time); filter_motion |= tp_post_button_events(tp, time);
if (filter_motion || tp->sendevents.trackpoint_active) { if (filter_motion || tp->sendevents.trackpoint_active) {
evdev_stop_scroll(tp->device, time); tp_stop_scroll_events(tp, time);
return; return;
} }
@ -621,6 +676,7 @@ tp_destroy(struct evdev_dispatch *dispatch)
tp_destroy_tap(tp); tp_destroy_tap(tp);
tp_destroy_buttons(tp); tp_destroy_buttons(tp);
tp_destroy_sendevents(tp); tp_destroy_sendevents(tp);
tp_destroy_scroll(tp);
free(tp->touches); free(tp->touches);
free(tp); free(tp);
@ -912,6 +968,9 @@ tp_scroll_config_scroll_method_get_methods(struct libinput_device *device)
if (tp->ntouches >= 2) if (tp->ntouches >= 2)
methods |= LIBINPUT_CONFIG_SCROLL_2FG; methods |= LIBINPUT_CONFIG_SCROLL_2FG;
if (!tp->buttons.is_clickpad)
methods |= LIBINPUT_CONFIG_SCROLL_EDGE;
return methods; return methods;
} }
@ -925,7 +984,7 @@ tp_scroll_config_scroll_method_set_method(struct libinput_device *device,
if (method == tp->scroll.method) if (method == tp->scroll.method)
return LIBINPUT_CONFIG_STATUS_SUCCESS; return LIBINPUT_CONFIG_STATUS_SUCCESS;
evdev_stop_scroll(evdev, libinput_now(device->seat->libinput)); tp_stop_scroll_events(tp, libinput_now(device->seat->libinput));
tp->scroll.method = method; tp->scroll.method = method;
return LIBINPUT_CONFIG_STATUS_SUCCESS; return LIBINPUT_CONFIG_STATUS_SUCCESS;
@ -940,15 +999,29 @@ tp_scroll_config_scroll_method_get_method(struct libinput_device *device)
return tp->scroll.method; return tp->scroll.method;
} }
static enum libinput_config_scroll_method
tp_scroll_get_default_method(struct tp_dispatch *tp)
{
if (tp->ntouches >= 2)
return LIBINPUT_CONFIG_SCROLL_2FG;
else
return LIBINPUT_CONFIG_SCROLL_EDGE;
}
static enum libinput_config_scroll_method static enum libinput_config_scroll_method
tp_scroll_config_scroll_method_get_default_method(struct libinput_device *device) tp_scroll_config_scroll_method_get_default_method(struct libinput_device *device)
{ {
return LIBINPUT_CONFIG_SCROLL_2FG; struct evdev_device *evdev = (struct evdev_device*)device;
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
return tp_scroll_get_default_method(tp);
} }
static int static int
tp_init_scroll(struct tp_dispatch *tp, struct evdev_device *device) tp_init_scroll(struct tp_dispatch *tp, struct evdev_device *device)
{ {
if (tp_edge_scroll_init(tp, device) != 0)
return -1;
evdev_init_natural_scroll(device); evdev_init_natural_scroll(device);
@ -956,7 +1029,7 @@ tp_init_scroll(struct tp_dispatch *tp, struct evdev_device *device)
tp->scroll.config_method.set_method = tp_scroll_config_scroll_method_set_method; tp->scroll.config_method.set_method = tp_scroll_config_scroll_method_set_method;
tp->scroll.config_method.get_method = tp_scroll_config_scroll_method_get_method; tp->scroll.config_method.get_method = tp_scroll_config_scroll_method_get_method;
tp->scroll.config_method.get_default_method = tp_scroll_config_scroll_method_get_default_method; tp->scroll.config_method.get_default_method = tp_scroll_config_scroll_method_get_default_method;
tp->scroll.method = tp_scroll_config_scroll_method_get_default_method(&tp->device->base); tp->scroll.method = tp_scroll_get_default_method(tp);
tp->device->base.config.scroll_method = &tp->scroll.config_method; tp->device->base.config.scroll_method = &tp->scroll.config_method;
/* In mm for touchpads with valid resolution, see tp_init_accel() */ /* In mm for touchpads with valid resolution, see tp_init_accel() */

View file

@ -103,6 +103,20 @@ enum tp_tap_touch_state {
TAP_TOUCH_STATE_DEAD, /**< exceeded motion/timeout */ TAP_TOUCH_STATE_DEAD, /**< exceeded motion/timeout */
}; };
/* For edge scrolling, so we only care about right and bottom */
enum tp_edge {
EDGE_NONE = 0,
EDGE_RIGHT = (1 << 0),
EDGE_BOTTOM = (1 << 1),
};
enum tp_edge_scroll_touch_state {
EDGE_SCROLL_TOUCH_STATE_NONE,
EDGE_SCROLL_TOUCH_STATE_EDGE_NEW,
EDGE_SCROLL_TOUCH_STATE_EDGE,
EDGE_SCROLL_TOUCH_STATE_AREA,
};
struct tp_motion { struct tp_motion {
int32_t x; int32_t x;
int32_t y; int32_t y;
@ -150,6 +164,14 @@ struct tp_touch {
enum tp_tap_touch_state state; enum tp_tap_touch_state state;
} tap; } tap;
struct {
enum tp_edge_scroll_touch_state state;
uint32_t edge;
int direction;
double threshold;
struct libinput_timer timer;
} scroll;
struct { struct {
bool is_palm; bool is_palm;
int32_t x, y; /* first coordinates if is_palm == true */ int32_t x, y; /* first coordinates if is_palm == true */
@ -214,6 +236,8 @@ struct tp_dispatch {
struct { struct {
struct libinput_device_config_scroll_method config_method; struct libinput_device_config_scroll_method config_method;
enum libinput_config_scroll_method method; enum libinput_config_scroll_method method;
int32_t right_edge;
int32_t bottom_edge;
} scroll; } scroll;
enum touchpad_event queued; enum touchpad_event queued;
@ -250,6 +274,10 @@ tp_get_delta(struct tp_touch *t, double *dx, double *dy);
void void
tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t); tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t);
void
tp_filter_motion(struct tp_dispatch *tp,
double *dx, double *dy, uint64_t time);
int int
tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time); tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time);
@ -304,4 +332,22 @@ tp_tap_resume(struct tp_dispatch *tp, uint64_t time);
bool bool
tp_tap_dragging(struct tp_dispatch *tp); tp_tap_dragging(struct tp_dispatch *tp);
int
tp_edge_scroll_init(struct tp_dispatch *tp, struct evdev_device *device);
void
tp_destroy_edge_scroll(struct tp_dispatch *tp);
void
tp_edge_scroll_handle_state(struct tp_dispatch *tp, uint64_t time);
int
tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time);
void
tp_edge_scroll_stop_events(struct tp_dispatch *tp, uint64_t time);
int
tp_edge_scroll_touch_active(struct tp_dispatch *tp, struct tp_touch *t);
#endif #endif