mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-04 11:40:30 +01:00
0.7.0
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iEYEABECAAYFAlSBMWUACgkQ4jt+cLRn8L/4JQCgt0u/hImDVk9GLPXpUfFZinRc pIgAn1bZ91n/o4nEhq6zOXSsKRoZvxHL =oj19 -----END PGP SIGNATURE----- Merge tag '0.7.0' into tablet-support 0.7.0 Conflicts: src/libinput-private.h test/device.c test/litest.h
This commit is contained in:
commit
83f97991a0
42 changed files with 7051 additions and 1659 deletions
|
|
@ -1,7 +1,7 @@
|
|||
AC_PREREQ([2.64])
|
||||
|
||||
m4_define([libinput_major_version], [0])
|
||||
m4_define([libinput_minor_version], [6])
|
||||
m4_define([libinput_minor_version], [7])
|
||||
m4_define([libinput_micro_version], [0])
|
||||
m4_define([libinput_version],
|
||||
[libinput_major_version.libinput_minor_version.libinput_micro_version])
|
||||
|
|
@ -20,7 +20,7 @@ AC_SUBST([LIBINPUT_VERSION], [libinput_version])
|
|||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz subdir-objects])
|
||||
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
|
||||
|
||||
# Before making a release, the LIBINPUT_LT_VERSION string should be
|
||||
# modified.
|
||||
|
|
@ -30,7 +30,7 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz subdir-objects])
|
|||
# - If binary compatibility has been broken (eg removed or changed interfaces)
|
||||
# change to C+1:0:0
|
||||
# - If the interface is the same as the previous version, change to C:R+1:A
|
||||
LIBINPUT_LT_VERSION=5:0:0
|
||||
LIBINPUT_LT_VERSION=6:0:1
|
||||
AC_SUBST(LIBINPUT_LT_VERSION)
|
||||
|
||||
AM_SILENT_RULES([yes])
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
262
doc/touchpad-edge-scrolling-state-machine.svg
Normal file
262
doc/touchpad-edge-scrolling-state-machine.svg
Normal 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 &= 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 & 0x01</text>
|
||||
<text x="1133" y="129">old = buttons.old_state & 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 < 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 |
|
|
@ -1,4 +1,5 @@
|
|||
lib_LTLIBRARIES = libinput.la
|
||||
noinst_LTLIBRARIES = libinput-util.la
|
||||
|
||||
include_HEADERS = \
|
||||
libinput.h
|
||||
|
|
@ -7,8 +8,6 @@ libinput_la_SOURCES = \
|
|||
libinput.c \
|
||||
libinput.h \
|
||||
libinput-private.h \
|
||||
libinput-util.c \
|
||||
libinput-util.h \
|
||||
evdev.c \
|
||||
evdev.h \
|
||||
evdev-tablet.c \
|
||||
|
|
@ -17,8 +16,10 @@ libinput_la_SOURCES = \
|
|||
evdev-mt-touchpad.h \
|
||||
evdev-mt-touchpad-tap.c \
|
||||
evdev-mt-touchpad-buttons.c \
|
||||
evdev-mt-touchpad-edge-scroll.c \
|
||||
filter.c \
|
||||
filter.h \
|
||||
filter-private.h \
|
||||
path.h \
|
||||
path.c \
|
||||
udev-seat.c \
|
||||
|
|
@ -29,13 +30,24 @@ libinput_la_SOURCES = \
|
|||
|
||||
libinput_la_LIBADD = $(MTDEV_LIBS) \
|
||||
$(LIBUDEV_LIBS) \
|
||||
$(LIBEVDEV_LIBS)
|
||||
$(LIBEVDEV_LIBS) \
|
||||
libinput-util.la
|
||||
|
||||
libinput_la_CFLAGS = -I$(top_srcdir)/include \
|
||||
$(MTDEV_CFLAGS) \
|
||||
$(LIBUDEV_CFLAGS) \
|
||||
$(LIBEVDEV_CFLAGS) \
|
||||
$(GCC_CFLAGS)
|
||||
|
||||
libinput_util_la_SOURCES = \
|
||||
libinput-util.c \
|
||||
libinput-util.h
|
||||
|
||||
libinput_util_la_LIBADD =
|
||||
libinput_util_la_CFLAGS = -I$(top_srcdir)/include \
|
||||
$(LIBUDEV_CFLAGS) \
|
||||
$(GCC_CFLAGS)
|
||||
|
||||
libinput_la_LDFLAGS = -version-info $(LIBINPUT_LT_VERSION) -shared
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
|
|
|
|||
|
|
@ -565,12 +565,12 @@ tp_init_buttons(struct tp_dispatch *tp,
|
|||
if (tp->buttons.is_clickpad)
|
||||
log_bug_kernel(libinput,
|
||||
"%s: clickpad advertising right button\n",
|
||||
device->sysname);
|
||||
device->devname);
|
||||
} else {
|
||||
if (!tp->buttons.is_clickpad)
|
||||
log_bug_kernel(libinput,
|
||||
"%s: non clickpad without right button?\n",
|
||||
device->sysname);
|
||||
device->devname);
|
||||
}
|
||||
|
||||
absinfo_x = device->abs.absinfo_x;
|
||||
|
|
@ -661,14 +661,17 @@ tp_post_physical_buttons(struct tp_dispatch *tp, uint64_t time)
|
|||
enum libinput_button_state state;
|
||||
|
||||
if ((current & 0x1) ^ (old & 0x1)) {
|
||||
uint32_t b;
|
||||
|
||||
if (!!(current & 0x1))
|
||||
state = LIBINPUT_BUTTON_STATE_PRESSED;
|
||||
else
|
||||
state = LIBINPUT_BUTTON_STATE_RELEASED;
|
||||
|
||||
b = evdev_to_left_handed(tp->device, button);
|
||||
evdev_pointer_notify_button(tp->device,
|
||||
time,
|
||||
button,
|
||||
b,
|
||||
state);
|
||||
}
|
||||
|
||||
|
|
@ -758,10 +761,12 @@ tp_post_softbutton_buttons(struct tp_dispatch *tp, uint64_t time)
|
|||
}
|
||||
|
||||
if ((button & MIDDLE) || ((button & LEFT) && (button & RIGHT)))
|
||||
button = BTN_MIDDLE;
|
||||
button = evdev_to_left_handed(tp->device, BTN_MIDDLE);
|
||||
else if (button & RIGHT)
|
||||
button = BTN_RIGHT;
|
||||
else
|
||||
button = evdev_to_left_handed(tp->device, BTN_RIGHT);
|
||||
else if (button & LEFT)
|
||||
button = evdev_to_left_handed(tp->device, BTN_LEFT);
|
||||
else /* main area is always BTN_LEFT */
|
||||
button = BTN_LEFT;
|
||||
|
||||
tp->buttons.active = button;
|
||||
|
|
|
|||
374
src/evdev-mt-touchpad-edge-scroll.c
Normal file
374
src/evdev-mt-touchpad-edge-scroll.c
Normal 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, NULL, NULL, 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;
|
||||
}
|
||||
|
|
@ -95,16 +95,12 @@ tap_event_to_str(enum tap_event event) {
|
|||
|
||||
static void
|
||||
tp_tap_notify(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
uint64_t time,
|
||||
int nfingers,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
int32_t button;
|
||||
|
||||
if (t && t->tap.state == TAP_TOUCH_STATE_DEAD)
|
||||
return;
|
||||
|
||||
switch (nfingers) {
|
||||
case 1: button = BTN_LEFT; break;
|
||||
case 2: button = BTN_RIGHT; break;
|
||||
|
|
@ -113,6 +109,11 @@ tp_tap_notify(struct tp_dispatch *tp,
|
|||
return;
|
||||
}
|
||||
|
||||
if (state == LIBINPUT_BUTTON_STATE_PRESSED)
|
||||
tp->tap.buttons_pressed |= (1 << nfingers);
|
||||
else
|
||||
tp->tap.buttons_pressed &= ~(1 << nfingers);
|
||||
|
||||
evdev_pointer_notify_button(tp->device,
|
||||
time,
|
||||
button,
|
||||
|
|
@ -169,7 +170,7 @@ tp_tap_touch_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_RELEASE:
|
||||
tp->tap.state = TAP_STATE_TAPPED;
|
||||
tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_set_timer(tp, time);
|
||||
break;
|
||||
case TAP_EVENT_TIMEOUT:
|
||||
|
|
@ -224,11 +225,11 @@ tp_tap_tapped_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_TIMEOUT:
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
case TAP_EVENT_BUTTON:
|
||||
tp->tap.state = TAP_STATE_DEAD;
|
||||
tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -246,8 +247,10 @@ tp_tap_touch2_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_RELEASE:
|
||||
tp->tap.state = TAP_STATE_HOLD;
|
||||
tp_tap_notify(tp, t, time, 2, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_notify(tp, t, time, 2, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
if (t->tap.state == TAP_TOUCH_STATE_TOUCH) {
|
||||
tp_tap_notify(tp, time, 2, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_notify(tp, time, 2, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
tp_tap_clear_timer(tp);
|
||||
break;
|
||||
case TAP_EVENT_MOTION:
|
||||
|
|
@ -304,8 +307,10 @@ tp_tap_touch3_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_RELEASE:
|
||||
tp->tap.state = TAP_STATE_TOUCH_2_HOLD;
|
||||
tp_tap_notify(tp, t, time, 3, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_notify(tp, t, time, 3, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
if (t->tap.state == TAP_TOUCH_STATE_TOUCH) {
|
||||
tp_tap_notify(tp, time, 3, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_notify(tp, time, 3, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
break;
|
||||
case TAP_EVENT_BUTTON:
|
||||
tp->tap.state = TAP_STATE_DEAD;
|
||||
|
|
@ -347,9 +352,9 @@ tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_RELEASE:
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_clear_timer(tp);
|
||||
break;
|
||||
case TAP_EVENT_MOTION:
|
||||
|
|
@ -358,7 +363,7 @@ tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_BUTTON:
|
||||
tp->tap.state = TAP_STATE_DEAD;
|
||||
tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -383,7 +388,7 @@ tp_tap_dragging_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_BUTTON:
|
||||
tp->tap.state = TAP_STATE_DEAD;
|
||||
tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -404,11 +409,11 @@ tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_TIMEOUT:
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
case TAP_EVENT_BUTTON:
|
||||
tp->tap.state = TAP_STATE_DEAD;
|
||||
tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -425,7 +430,7 @@ tp_tap_dragging2_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_TOUCH:
|
||||
tp->tap.state = TAP_STATE_DEAD;
|
||||
tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
case TAP_EVENT_MOTION:
|
||||
case TAP_EVENT_TIMEOUT:
|
||||
|
|
@ -433,7 +438,7 @@ tp_tap_dragging2_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_BUTTON:
|
||||
tp->tap.state = TAP_STATE_DEAD;
|
||||
tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -471,9 +476,6 @@ tp_tap_handle_event(struct tp_dispatch *tp,
|
|||
|
||||
switch(tp->tap.state) {
|
||||
case TAP_STATE_IDLE:
|
||||
if (!tp->tap.enabled)
|
||||
break;
|
||||
|
||||
tp_tap_idle_handle_event(tp, t, event, time);
|
||||
break;
|
||||
case TAP_STATE_TOUCH:
|
||||
|
|
@ -535,12 +537,21 @@ tp_tap_exceeds_motion_threshold(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
return dx * dx + dy * dy > threshold * threshold;
|
||||
}
|
||||
|
||||
static bool
|
||||
tp_tap_enabled(struct tp_dispatch *tp)
|
||||
{
|
||||
return tp->tap.enabled && !tp->tap.suspended;
|
||||
}
|
||||
|
||||
int
|
||||
tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
int filter_motion = 0;
|
||||
|
||||
if (!tp_tap_enabled(tp))
|
||||
return 0;
|
||||
|
||||
/* Handle queued button pressed events from clickpads. For touchpads
|
||||
* with separate physical buttons, ignore button pressed events so they
|
||||
* don't interfere with tapping. */
|
||||
|
|
@ -551,7 +562,8 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
if (!t->dirty || t->state == TOUCH_NONE)
|
||||
continue;
|
||||
|
||||
if (tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS)
|
||||
if (tp->buttons.is_clickpad &&
|
||||
tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS)
|
||||
t->tap.state = TAP_TOUCH_STATE_DEAD;
|
||||
|
||||
if (t->state == TOUCH_BEGIN) {
|
||||
|
|
@ -559,7 +571,7 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
|
|||
tp_tap_handle_event(tp, t, TAP_EVENT_TOUCH, time);
|
||||
} else if (t->state == TOUCH_END) {
|
||||
tp_tap_handle_event(tp, t, TAP_EVENT_RELEASE, time);
|
||||
t->tap.state = TAP_TOUCH_STATE_DEAD;
|
||||
t->tap.state = TAP_TOUCH_STATE_IDLE;
|
||||
} else if (tp->tap.state != TAP_STATE_IDLE &&
|
||||
tp_tap_exceeds_motion_threshold(tp, t)) {
|
||||
struct tp_touch *tmp;
|
||||
|
|
@ -615,6 +627,26 @@ tp_tap_handle_timeout(uint64_t time, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_tap_enabled_update(struct tp_dispatch *tp, bool suspended, bool enabled, uint64_t time)
|
||||
{
|
||||
bool was_enabled = tp_tap_enabled(tp);
|
||||
|
||||
tp->tap.suspended = suspended;
|
||||
tp->tap.enabled = enabled;
|
||||
|
||||
if (tp_tap_enabled(tp) == was_enabled)
|
||||
return;
|
||||
|
||||
if (tp_tap_enabled(tp)) {
|
||||
/* Must restart in DEAD if fingers are down atm */
|
||||
tp->tap.state =
|
||||
tp->nfingers_down ? TAP_STATE_DEAD : TAP_STATE_IDLE;
|
||||
} else {
|
||||
tp_release_all_taps(tp, time);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
tp_tap_config_count(struct libinput_device *device)
|
||||
{
|
||||
|
|
@ -631,13 +663,12 @@ static enum libinput_config_status
|
|||
tp_tap_config_set_enabled(struct libinput_device *device,
|
||||
enum libinput_config_tap_state enabled)
|
||||
{
|
||||
struct evdev_dispatch *dispatch;
|
||||
struct tp_dispatch *tp = NULL;
|
||||
struct evdev_dispatch *dispatch = ((struct evdev_device *) device)->dispatch;
|
||||
struct tp_dispatch *tp = container_of(dispatch, tp, base);
|
||||
|
||||
dispatch = ((struct evdev_device *) device)->dispatch;
|
||||
tp = container_of(dispatch, tp, base);
|
||||
|
||||
tp->tap.enabled = (enabled == LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
tp_tap_enabled_update(tp, tp->tap.suspended,
|
||||
(enabled == LIBINPUT_CONFIG_TAP_ENABLED),
|
||||
libinput_now(device->seat->libinput));
|
||||
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -697,5 +728,37 @@ tp_destroy_tap(struct tp_dispatch *tp)
|
|||
void
|
||||
tp_release_all_taps(struct tp_dispatch *tp, uint64_t now)
|
||||
{
|
||||
tp_tap_handle_timeout(now, tp);
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= 3; i++) {
|
||||
if (tp->tap.buttons_pressed & (1 << i))
|
||||
tp_tap_notify(tp, now, i, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
|
||||
tp->tap.state = tp->nfingers_down ? TAP_STATE_DEAD : TAP_STATE_IDLE;
|
||||
}
|
||||
|
||||
void
|
||||
tp_tap_suspend(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
tp_tap_enabled_update(tp, true, tp->tap.enabled, time);
|
||||
}
|
||||
|
||||
void
|
||||
tp_tap_resume(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
tp_tap_enabled_update(tp, false, tp->tap.enabled, time);
|
||||
}
|
||||
|
||||
bool
|
||||
tp_tap_dragging(struct tp_dispatch *tp)
|
||||
{
|
||||
switch (tp->tap.state) {
|
||||
case TAP_STATE_DRAGGING:
|
||||
case TAP_STATE_DRAGGING_2:
|
||||
case TAP_STATE_DRAGGING_WAIT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#define DEFAULT_ACCEL_NUMERATOR 1200.0
|
||||
#define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
|
||||
#define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT 500 /* ms */
|
||||
|
||||
static inline int
|
||||
tp_hysteresis(int in, int center, int margin)
|
||||
|
|
@ -55,17 +56,24 @@ tp_motion_history_offset(struct tp_touch *t, int offset)
|
|||
return &t->history.samples[offset_index];
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
tp_filter_motion(struct tp_dispatch *tp,
|
||||
double *dx, double *dy, uint64_t time)
|
||||
double *dx, double *dy,
|
||||
double *dx_unaccel, double *dy_unaccel,
|
||||
uint64_t time)
|
||||
{
|
||||
struct motion_params motion;
|
||||
|
||||
motion.dx = *dx * tp->accel.x_scale_coeff;
|
||||
motion.dy = *dy * tp->accel.y_scale_coeff;
|
||||
|
||||
if (dx_unaccel)
|
||||
*dx_unaccel = motion.dx;
|
||||
if (dy_unaccel)
|
||||
*dy_unaccel = motion.dy;
|
||||
|
||||
if (motion.dx != 0.0 || motion.dy != 0.0)
|
||||
filter_dispatch(tp->filter, &motion, tp, time);
|
||||
filter_dispatch(tp->device->pointer.filter, &motion, tp, time);
|
||||
|
||||
*dx = motion.dx;
|
||||
*dy = motion.dy;
|
||||
|
|
@ -338,7 +346,9 @@ tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
{
|
||||
return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
|
||||
!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
|
||||
|
|
@ -397,6 +407,116 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
|||
t->palm.y = t->y;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
int nchanged = 0;
|
||||
double dx = 0, dy =0;
|
||||
double tmpx, tmpy;
|
||||
|
||||
tp_for_each_touch(tp, t) {
|
||||
if (tp_touch_active(tp, t) && t->dirty) {
|
||||
nchanged++;
|
||||
tp_get_delta(t, &tmpx, &tmpy);
|
||||
|
||||
dx += tmpx;
|
||||
dy += tmpy;
|
||||
}
|
||||
/* Stop spurious MOTION events at the end of scrolling */
|
||||
t->is_pointer = false;
|
||||
}
|
||||
|
||||
if (nchanged == 0)
|
||||
return;
|
||||
|
||||
dx /= nchanged;
|
||||
dy /= nchanged;
|
||||
|
||||
tp_filter_motion(tp, &dx, &dy, NULL, NULL, time);
|
||||
|
||||
evdev_post_scroll(tp->device, time, dx, dy);
|
||||
}
|
||||
|
||||
static int
|
||||
tp_twofinger_scroll_post_events(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
int nfingers_down = 0;
|
||||
|
||||
/* No 2fg scrolling during tap-n-drag */
|
||||
if (tp_tap_dragging(tp))
|
||||
return 0;
|
||||
|
||||
/* 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) {
|
||||
evdev_stop_scroll(tp->device, time);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tp_post_twofinger_scroll(tp, time);
|
||||
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
|
||||
tp_process_state(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
|
|
@ -430,6 +550,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t 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
|
||||
|
|
@ -465,63 +586,14 @@ tp_post_process_state(struct tp_dispatch *tp, uint64_t time)
|
|||
tp->queued = TOUCHPAD_EVENT_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
int nchanged = 0;
|
||||
double dx = 0, dy =0;
|
||||
double tmpx, tmpy;
|
||||
|
||||
tp_for_each_touch(tp, t) {
|
||||
if (tp_touch_active(tp, t) && t->dirty) {
|
||||
nchanged++;
|
||||
tp_get_delta(t, &tmpx, &tmpy);
|
||||
|
||||
dx += tmpx;
|
||||
dy += tmpy;
|
||||
}
|
||||
/* Stop spurious MOTION events at the end of scrolling */
|
||||
t->is_pointer = false;
|
||||
}
|
||||
|
||||
if (nchanged == 0)
|
||||
return;
|
||||
|
||||
dx /= nchanged;
|
||||
dy /= nchanged;
|
||||
|
||||
tp_filter_motion(tp, &dx, &dy, time);
|
||||
evdev_post_scroll(tp->device, time, dx, dy);
|
||||
}
|
||||
|
||||
static int
|
||||
tp_post_scroll_events(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t;
|
||||
int nfingers_down = 0;
|
||||
|
||||
/* 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) {
|
||||
evdev_stop_scroll(tp->device, time);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tp_post_twofinger_scroll(tp, time);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_post_events(struct tp_dispatch *tp, uint64_t time)
|
||||
{
|
||||
struct tp_touch *t = tp_current_touch(tp);
|
||||
double dx, dy;
|
||||
int consumed = 0;
|
||||
int filter_motion = 0;
|
||||
double dx_unaccel, dy_unaccel;
|
||||
|
||||
/* Only post (top) button events while suspended */
|
||||
if (tp->device->suspended) {
|
||||
|
|
@ -529,11 +601,11 @@ tp_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
return;
|
||||
}
|
||||
|
||||
consumed |= tp_tap_handle_state(tp, time);
|
||||
consumed |= tp_post_button_events(tp, time);
|
||||
filter_motion |= tp_tap_handle_state(tp, time);
|
||||
filter_motion |= tp_post_button_events(tp, time);
|
||||
|
||||
if (consumed) {
|
||||
evdev_stop_scroll(tp->device, time);
|
||||
if (filter_motion || tp->sendevents.trackpoint_active) {
|
||||
tp_stop_scroll_events(tp, time);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -553,10 +625,12 @@ tp_post_events(struct tp_dispatch *tp, uint64_t time)
|
|||
return;
|
||||
|
||||
tp_get_delta(t, &dx, &dy);
|
||||
tp_filter_motion(tp, &dx, &dy, time);
|
||||
tp_filter_motion(tp, &dx, &dy, &dx_unaccel, &dy_unaccel, time);
|
||||
|
||||
if (dx != 0.0 || dy != 0.0)
|
||||
pointer_notify_motion(&tp->device->base, time, dx, dy);
|
||||
if (dx != 0.0 || dy != 0.0 || dx_unaccel != 0.0 || dy_unaccel != 0.0) {
|
||||
pointer_notify_motion(&tp->device->base, time,
|
||||
dx, dy, dx_unaccel, dy_unaccel);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -593,6 +667,16 @@ tp_process(struct evdev_dispatch *dispatch,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_destroy_sendevents(struct tp_dispatch *tp)
|
||||
{
|
||||
libinput_timer_cancel(&tp->sendevents.trackpoint_timer);
|
||||
|
||||
if (tp->buttons.trackpoint)
|
||||
libinput_device_remove_event_listener(
|
||||
&tp->sendevents.trackpoint_listener);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_destroy(struct evdev_dispatch *dispatch)
|
||||
{
|
||||
|
|
@ -601,14 +685,15 @@ tp_destroy(struct evdev_dispatch *dispatch)
|
|||
|
||||
tp_destroy_tap(tp);
|
||||
tp_destroy_buttons(tp);
|
||||
tp_destroy_sendevents(tp);
|
||||
tp_destroy_scroll(tp);
|
||||
|
||||
filter_destroy(tp->filter);
|
||||
free(tp->touches);
|
||||
free(tp);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_clear_state(struct tp_dispatch *tp, struct evdev_device *device)
|
||||
tp_clear_state(struct tp_dispatch *tp)
|
||||
{
|
||||
uint64_t now = libinput_now(tp->device->base.seat->libinput);
|
||||
struct tp_touch *t;
|
||||
|
|
@ -637,7 +722,7 @@ tp_clear_state(struct tp_dispatch *tp, struct evdev_device *device)
|
|||
static void
|
||||
tp_suspend(struct tp_dispatch *tp, struct evdev_device *device)
|
||||
{
|
||||
tp_clear_state(tp, device);
|
||||
tp_clear_state(tp);
|
||||
|
||||
/* On devices with top softwarebuttons we don't actually suspend the
|
||||
* device, to keep the "trackpoint" buttons working. tp_post_events()
|
||||
|
|
@ -657,7 +742,7 @@ tp_resume(struct tp_dispatch *tp, struct evdev_device *device)
|
|||
{
|
||||
if (tp->buttons.has_topbuttons) {
|
||||
/* tap state-machine is offline while suspended, reset state */
|
||||
tp_clear_state(tp, device);
|
||||
tp_clear_state(tp);
|
||||
/* restore original topbutton area size */
|
||||
tp_init_softbuttons(tp, device, 1.0);
|
||||
evdev_notify_resumed_device(device);
|
||||
|
|
@ -666,6 +751,35 @@ tp_resume(struct tp_dispatch *tp, struct evdev_device *device)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_trackpoint_timeout(uint64_t now, void *data)
|
||||
{
|
||||
struct tp_dispatch *tp = data;
|
||||
|
||||
tp_tap_resume(tp, now);
|
||||
tp->sendevents.trackpoint_active = false;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data)
|
||||
{
|
||||
struct tp_dispatch *tp = data;
|
||||
|
||||
/* Buttons do not count as trackpad activity, as people may use
|
||||
the trackpoint buttons in combination with the touchpad. */
|
||||
if (event->type == LIBINPUT_EVENT_POINTER_BUTTON)
|
||||
return;
|
||||
|
||||
if (!tp->sendevents.trackpoint_active) {
|
||||
evdev_stop_scroll(tp->device, time);
|
||||
tp_tap_suspend(tp, time);
|
||||
tp->sendevents.trackpoint_active = true;
|
||||
}
|
||||
|
||||
libinput_timer_set(&tp->sendevents.trackpoint_timer,
|
||||
time + DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
tp_device_added(struct evdev_device *device,
|
||||
struct evdev_device *added_device)
|
||||
|
|
@ -677,6 +791,9 @@ tp_device_added(struct evdev_device *device,
|
|||
/* Don't send any pending releases to the new trackpoint */
|
||||
tp->buttons.active_is_topbutton = false;
|
||||
tp->buttons.trackpoint = added_device;
|
||||
libinput_device_add_event_listener(&added_device->base,
|
||||
&tp->sendevents.trackpoint_listener,
|
||||
tp_trackpoint_event, tp);
|
||||
}
|
||||
|
||||
if (tp->sendevents.current_mode !=
|
||||
|
|
@ -700,6 +817,8 @@ tp_device_removed(struct evdev_device *device,
|
|||
tp->buttons.active = 0;
|
||||
tp->buttons.active_is_topbutton = false;
|
||||
}
|
||||
libinput_device_remove_event_listener(
|
||||
&tp->sendevents.trackpoint_listener);
|
||||
tp->buttons.trackpoint = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -807,7 +926,6 @@ tp_init_slots(struct tp_dispatch *tp,
|
|||
static int
|
||||
tp_init_accel(struct tp_dispatch *tp, double diagonal)
|
||||
{
|
||||
struct motion_filter *accel;
|
||||
int res_x, res_y;
|
||||
|
||||
if (tp->has_mt) {
|
||||
|
|
@ -824,17 +942,27 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal)
|
|||
|
||||
/*
|
||||
* Not all touchpads report the same amount of units/mm (resolution).
|
||||
* Normalize motion events to a resolution of 15.74 units/mm
|
||||
* (== 400 dpi) as base (unaccelerated) speed. This also evens out any
|
||||
* differences in x and y resolution, so that a circle on the
|
||||
* Normalize motion events to the default mouse DPI as base
|
||||
* (unaccelerated) speed. This also evens out any differences in x
|
||||
* and y resolution, so that a circle on the
|
||||
* touchpad does not turn into an elipse on the screen.
|
||||
*
|
||||
* We pick 400dpi as thats one of the many default resolutions
|
||||
* for USB mice, so we end up with a similar base speed on the device.
|
||||
*/
|
||||
if (res_x > 1 && res_y > 1) {
|
||||
tp->accel.x_scale_coeff = (400/25.4) / res_x;
|
||||
tp->accel.y_scale_coeff = (400/25.4) / res_y;
|
||||
tp->accel.x_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_x;
|
||||
tp->accel.y_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_y;
|
||||
|
||||
/* FIXME: once normalized, touchpads see the same
|
||||
acceleration as mice. that is technically correct but
|
||||
subjectively wrong, we expect a touchpad to be a lot
|
||||
slower than a mouse.
|
||||
For now, apply a magic factor here until this is
|
||||
fixed in the actual filter code.
|
||||
*/
|
||||
{
|
||||
const double MAGIC = 0.4;
|
||||
tp->accel.x_scale_coeff *= MAGIC;
|
||||
tp->accel.y_scale_coeff *= MAGIC;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* For touchpads where the driver does not provide resolution, fall
|
||||
|
|
@ -844,12 +972,88 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal)
|
|||
tp->accel.y_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
|
||||
}
|
||||
|
||||
accel = create_pointer_accelator_filter(
|
||||
pointer_accel_profile_smooth_simple);
|
||||
if (accel == NULL)
|
||||
if (evdev_device_init_pointer_acceleration(tp->device) == -1)
|
||||
return -1;
|
||||
|
||||
tp->filter = accel;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
tp_scroll_config_scroll_method_get_methods(struct libinput_device *device)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
|
||||
uint32_t methods = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
|
||||
|
||||
if (tp->ntouches >= 2)
|
||||
methods |= LIBINPUT_CONFIG_SCROLL_2FG;
|
||||
|
||||
if (!tp->buttons.is_clickpad)
|
||||
methods |= LIBINPUT_CONFIG_SCROLL_EDGE;
|
||||
|
||||
return methods;
|
||||
}
|
||||
|
||||
static enum libinput_config_status
|
||||
tp_scroll_config_scroll_method_set_method(struct libinput_device *device,
|
||||
enum libinput_config_scroll_method method)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
|
||||
|
||||
if (method == tp->scroll.method)
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
|
||||
tp_stop_scroll_events(tp, libinput_now(device->seat->libinput));
|
||||
tp->scroll.method = method;
|
||||
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static enum libinput_config_scroll_method
|
||||
tp_scroll_config_scroll_method_get_method(struct libinput_device *device)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
|
||||
|
||||
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
|
||||
tp_scroll_config_scroll_method_get_default_method(struct libinput_device *device)
|
||||
{
|
||||
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
|
||||
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);
|
||||
|
||||
tp->scroll.config_method.get_methods = tp_scroll_config_scroll_method_get_methods;
|
||||
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_default_method = tp_scroll_config_scroll_method_get_default_method;
|
||||
tp->scroll.method = tp_scroll_get_default_method(tp);
|
||||
tp->device->base.config.scroll_method = &tp->scroll.config_method;
|
||||
|
||||
/* In mm for touchpads with valid resolution, see tp_init_accel() */
|
||||
tp->device->scroll.threshold = 5.0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -885,6 +1089,16 @@ tp_init_palmdetect(struct tp_dispatch *tp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_init_sendevents(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
libinput_timer_init(&tp->sendevents.trackpoint_timer,
|
||||
tp->device->base.seat->libinput,
|
||||
tp_trackpoint_timeout, tp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_init(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
|
|
@ -921,6 +1135,12 @@ tp_init(struct tp_dispatch *tp,
|
|||
if (tp_init_palmdetect(tp, device) != 0)
|
||||
return -1;
|
||||
|
||||
if (tp_init_sendevents(tp, device) != 0)
|
||||
return -1;
|
||||
|
||||
if (tp_init_scroll(tp, device) != 0)
|
||||
return -1;
|
||||
|
||||
device->seat_caps |= EVDEV_DEVICE_POINTER;
|
||||
|
||||
return 0;
|
||||
|
|
@ -930,8 +1150,7 @@ static uint32_t
|
|||
tp_sendevents_get_modes(struct libinput_device *device)
|
||||
{
|
||||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
uint32_t modes = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED |
|
||||
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
|
||||
uint32_t modes = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
|
||||
|
||||
if (evdev->tags & EVDEV_TAG_INTERNAL_TOUCHPAD)
|
||||
modes |= LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
|
||||
|
|
@ -961,6 +1180,11 @@ tp_sendevents_set_mode(struct libinput_device *device,
|
|||
struct evdev_device *evdev = (struct evdev_device*)device;
|
||||
struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
|
||||
|
||||
/* DISABLED overrides any DISABLED_ON_ */
|
||||
if ((mode & LIBINPUT_CONFIG_SEND_EVENTS_DISABLED) &&
|
||||
(mode & LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE))
|
||||
mode &= ~LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
|
||||
|
||||
if (mode == tp->sendevents.current_mode)
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
|
||||
|
|
@ -998,6 +1222,57 @@ tp_sendevents_get_default_mode(struct libinput_device *device)
|
|||
return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_change_to_left_handed(struct evdev_device *device)
|
||||
{
|
||||
struct tp_dispatch *tp = (struct tp_dispatch *)device->dispatch;
|
||||
|
||||
if (device->buttons.want_left_handed == device->buttons.left_handed)
|
||||
return;
|
||||
|
||||
if (tp->buttons.state & 0x3) /* BTN_LEFT|BTN_RIGHT */
|
||||
return;
|
||||
|
||||
/* tapping and clickfinger aren't affected by left-handed config,
|
||||
* so checking physical buttons is enough */
|
||||
|
||||
device->buttons.left_handed = device->buttons.want_left_handed;
|
||||
}
|
||||
|
||||
struct model_lookup_t {
|
||||
uint16_t vendor;
|
||||
uint16_t product_start;
|
||||
uint16_t product_end;
|
||||
enum touchpad_model model;
|
||||
};
|
||||
|
||||
static struct model_lookup_t model_lookup_table[] = {
|
||||
{ 0x0002, 0x0007, 0x0007, MODEL_SYNAPTICS },
|
||||
{ 0x0002, 0x0008, 0x0008, MODEL_ALPS },
|
||||
{ 0x0002, 0x000e, 0x000e, MODEL_ELANTECH },
|
||||
{ 0x05ac, 0, 0x0222, MODEL_APPLETOUCH },
|
||||
{ 0x05ac, 0x0223, 0x0228, MODEL_UNIBODY_MACBOOK },
|
||||
{ 0x05ac, 0x0229, 0x022b, MODEL_APPLETOUCH },
|
||||
{ 0x05ac, 0x022c, 0xffff, MODEL_UNIBODY_MACBOOK },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static enum touchpad_model
|
||||
tp_get_model(struct evdev_device *device)
|
||||
{
|
||||
struct model_lookup_t *lookup;
|
||||
uint16_t vendor = libevdev_get_id_vendor(device->evdev);
|
||||
uint16_t product = libevdev_get_id_product(device->evdev);
|
||||
|
||||
for (lookup = model_lookup_table; lookup->vendor; lookup++) {
|
||||
if (lookup->vendor == vendor &&
|
||||
lookup->product_start <= product &&
|
||||
product <= lookup->product_end)
|
||||
return lookup->model;
|
||||
}
|
||||
return MODEL_UNKNOWN;
|
||||
}
|
||||
|
||||
struct evdev_dispatch *
|
||||
evdev_mt_touchpad_create(struct evdev_device *device)
|
||||
{
|
||||
|
|
@ -1007,6 +1282,8 @@ evdev_mt_touchpad_create(struct evdev_device *device)
|
|||
if (!tp)
|
||||
return NULL;
|
||||
|
||||
tp->model = tp_get_model(device);
|
||||
|
||||
if (tp_init(tp, device) != 0) {
|
||||
tp_destroy(&tp->base);
|
||||
return NULL;
|
||||
|
|
@ -1020,5 +1297,7 @@ evdev_mt_touchpad_create(struct evdev_device *device)
|
|||
tp->sendevents.config.get_mode = tp_sendevents_get_mode;
|
||||
tp->sendevents.config.get_default_mode = tp_sendevents_get_default_mode;
|
||||
|
||||
evdev_init_left_handed(device, tp_change_to_left_handed);
|
||||
|
||||
return &tp->base;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,15 @@ enum touchpad_event {
|
|||
TOUCHPAD_EVENT_BUTTON_RELEASE = (1 << 2),
|
||||
};
|
||||
|
||||
enum touchpad_model {
|
||||
MODEL_UNKNOWN = 0,
|
||||
MODEL_SYNAPTICS,
|
||||
MODEL_ALPS,
|
||||
MODEL_APPLETOUCH,
|
||||
MODEL_ELANTECH,
|
||||
MODEL_UNIBODY_MACBOOK
|
||||
};
|
||||
|
||||
enum touch_state {
|
||||
TOUCH_NONE = 0,
|
||||
TOUCH_BEGIN,
|
||||
|
|
@ -94,6 +103,20 @@ enum tp_tap_touch_state {
|
|||
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 {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
|
|
@ -141,6 +164,14 @@ struct tp_touch {
|
|||
enum tp_tap_touch_state state;
|
||||
} tap;
|
||||
|
||||
struct {
|
||||
enum tp_edge_scroll_touch_state state;
|
||||
uint32_t edge;
|
||||
int direction;
|
||||
double threshold;
|
||||
struct libinput_timer timer;
|
||||
} scroll;
|
||||
|
||||
struct {
|
||||
bool is_palm;
|
||||
int32_t x, y; /* first coordinates if is_palm == true */
|
||||
|
|
@ -156,6 +187,7 @@ struct tp_dispatch {
|
|||
unsigned int slot; /* current slot */
|
||||
bool has_mt;
|
||||
bool semi_mt;
|
||||
enum touchpad_model model;
|
||||
|
||||
unsigned int real_touches; /* number of slots */
|
||||
unsigned int ntouches; /* no slots inc. fakes */
|
||||
|
|
@ -167,8 +199,6 @@ struct tp_dispatch {
|
|||
int32_t margin_y;
|
||||
} hysteresis;
|
||||
|
||||
struct motion_filter *filter;
|
||||
|
||||
struct {
|
||||
double x_scale_coeff;
|
||||
double y_scale_coeff;
|
||||
|
|
@ -203,13 +233,22 @@ struct tp_dispatch {
|
|||
struct evdev_device *trackpoint;
|
||||
} buttons; /* physical buttons */
|
||||
|
||||
struct {
|
||||
struct libinput_device_config_scroll_method config_method;
|
||||
enum libinput_config_scroll_method method;
|
||||
int32_t right_edge;
|
||||
int32_t bottom_edge;
|
||||
} scroll;
|
||||
|
||||
enum touchpad_event queued;
|
||||
|
||||
struct {
|
||||
struct libinput_device_config_tap config;
|
||||
bool enabled;
|
||||
bool suspended;
|
||||
struct libinput_timer timer;
|
||||
enum tp_tap_state state;
|
||||
uint32_t buttons_pressed;
|
||||
} tap;
|
||||
|
||||
struct {
|
||||
|
|
@ -220,6 +259,9 @@ struct tp_dispatch {
|
|||
struct {
|
||||
struct libinput_device_config_send_events config;
|
||||
enum libinput_config_send_events_mode current_mode;
|
||||
bool trackpoint_active;
|
||||
struct libinput_event_listener trackpoint_listener;
|
||||
struct libinput_timer trackpoint_timer;
|
||||
} sendevents;
|
||||
};
|
||||
|
||||
|
|
@ -232,6 +274,12 @@ tp_get_delta(struct tp_touch *t, double *dx, double *dy);
|
|||
void
|
||||
tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t);
|
||||
|
||||
void
|
||||
tp_filter_motion(struct tp_dispatch *tp,
|
||||
double *dx, double *dy,
|
||||
double *dx_unaccel, double *dy_unaccel,
|
||||
uint64_t time);
|
||||
|
||||
int
|
||||
tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time);
|
||||
|
||||
|
|
@ -277,4 +325,31 @@ void
|
|||
tp_release_all_taps(struct tp_dispatch *tp,
|
||||
uint64_t time);
|
||||
|
||||
void
|
||||
tp_tap_suspend(struct tp_dispatch *tp, uint64_t time);
|
||||
|
||||
void
|
||||
tp_tap_resume(struct tp_dispatch *tp, uint64_t time);
|
||||
|
||||
bool
|
||||
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
|
||||
|
|
|
|||
814
src/evdev.c
814
src/evdev.c
File diff suppressed because it is too large
Load diff
73
src/evdev.h
73
src/evdev.h
|
|
@ -69,11 +69,10 @@ struct evdev_device {
|
|||
|
||||
struct evdev_dispatch *dispatch;
|
||||
struct libevdev *evdev;
|
||||
struct udev_device *udev_device;
|
||||
char *output_name;
|
||||
char *devnode;
|
||||
char *sysname;
|
||||
char *syspath;
|
||||
const char *devname;
|
||||
bool was_removed;
|
||||
int fd;
|
||||
struct {
|
||||
const struct input_absinfo *absinfo_x, *absinfo_y;
|
||||
|
|
@ -101,10 +100,26 @@ struct evdev_device {
|
|||
|
||||
struct {
|
||||
struct libinput_timer timer;
|
||||
bool has_middle_button_scroll;
|
||||
bool middle_button_scroll_active;
|
||||
struct libinput_device_config_scroll_method config;
|
||||
/* Currently enabled method, button */
|
||||
enum libinput_config_scroll_method method;
|
||||
uint32_t button;
|
||||
/* set during device init, used at runtime to delay changes
|
||||
* until all buttons are up */
|
||||
enum libinput_config_scroll_method want_method;
|
||||
uint32_t want_button;
|
||||
/* Checks if buttons are down and commits the setting */
|
||||
void (*change_scroll_method)(struct evdev_device *device);
|
||||
bool button_scroll_active;
|
||||
double threshold;
|
||||
uint32_t direction;
|
||||
double buildup_vertical;
|
||||
double buildup_horizontal;
|
||||
|
||||
struct libinput_device_config_natural_scroll config_natural;
|
||||
/* set during device init if we want natural scrolling,
|
||||
* used at runtime to enable/disable the feature */
|
||||
bool natural_scrolling_enabled;
|
||||
} scroll;
|
||||
|
||||
enum evdev_event_type pending_event;
|
||||
|
|
@ -115,6 +130,7 @@ struct evdev_device {
|
|||
int suspended;
|
||||
|
||||
struct {
|
||||
struct libinput_device_config_accel config;
|
||||
struct motion_filter *filter;
|
||||
} pointer;
|
||||
|
||||
|
|
@ -124,6 +140,20 @@ struct evdev_device {
|
|||
/* Key counter used for multiplexing button events internally in
|
||||
* libinput. */
|
||||
uint8_t key_count[KEY_CNT];
|
||||
|
||||
struct {
|
||||
struct libinput_device_config_left_handed config_left_handed;
|
||||
/* left-handed currently enabled */
|
||||
bool left_handed;
|
||||
/* set during device init if we want left_handed config,
|
||||
* used at runtime to delay the effect until buttons are up */
|
||||
bool want_left_handed;
|
||||
/* Checks if buttons are down and commits the setting */
|
||||
void (*change_to_left_handed)(struct evdev_device *device);
|
||||
} buttons;
|
||||
|
||||
int dpi; /* HW resolution */
|
||||
struct ratelimit syn_drop_limit; /* ratelimit for SYN_DROPPED logging */
|
||||
};
|
||||
|
||||
#define EVDEV_UNHANDLED_DEVICE ((struct evdev_device *) 1)
|
||||
|
|
@ -173,9 +203,10 @@ struct evdev_dispatch {
|
|||
|
||||
struct evdev_device *
|
||||
evdev_device_create(struct libinput_seat *seat,
|
||||
const char *devnode,
|
||||
const char *sysname,
|
||||
const char *syspath);
|
||||
struct udev_device *device);
|
||||
|
||||
int
|
||||
evdev_device_init_pointer_acceleration(struct evdev_device *device);
|
||||
|
||||
struct evdev_dispatch *
|
||||
evdev_touchpad_create(struct evdev_device *device);
|
||||
|
|
@ -207,6 +238,9 @@ evdev_device_get_id_product(struct evdev_device *device);
|
|||
unsigned int
|
||||
evdev_device_get_id_vendor(struct evdev_device *device);
|
||||
|
||||
struct udev_device *
|
||||
evdev_device_get_udev_device(struct evdev_device *device);
|
||||
|
||||
void
|
||||
evdev_device_set_default_calibration(struct evdev_device *device,
|
||||
const float calibration[6]);
|
||||
|
|
@ -223,6 +257,9 @@ evdev_device_get_size(struct evdev_device *device,
|
|||
double *w,
|
||||
double *h);
|
||||
|
||||
int
|
||||
evdev_device_has_button(struct evdev_device *device, uint32_t code);
|
||||
|
||||
double
|
||||
evdev_device_transform_x(struct evdev_device *device,
|
||||
double x,
|
||||
|
|
@ -256,6 +293,9 @@ evdev_pointer_notify_button(struct evdev_device *device,
|
|||
int button,
|
||||
enum libinput_button_state state);
|
||||
|
||||
void
|
||||
evdev_init_natural_scroll(struct evdev_device *device);
|
||||
|
||||
void
|
||||
evdev_post_scroll(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
|
|
@ -279,4 +319,21 @@ evdev_convert_to_mm(const struct input_absinfo *absinfo, double v)
|
|||
return value/absinfo->resolution;
|
||||
}
|
||||
|
||||
int
|
||||
evdev_init_left_handed(struct evdev_device *device,
|
||||
void (*change_to_left_handed)(struct evdev_device *));
|
||||
|
||||
static inline uint32_t
|
||||
evdev_to_left_handed(struct evdev_device *device,
|
||||
uint32_t button)
|
||||
{
|
||||
if (device->buttons.left_handed) {
|
||||
if (button == BTN_LEFT)
|
||||
return BTN_RIGHT;
|
||||
else if (button == BTN_RIGHT)
|
||||
return BTN_LEFT;
|
||||
}
|
||||
return button;
|
||||
}
|
||||
|
||||
#endif /* EVDEV_H */
|
||||
|
|
|
|||
45
src/filter-private.h
Normal file
45
src/filter-private.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright © 2012 Jonas Ådahl
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef FILTER_PRIVATE_H
|
||||
#define FILTER_PRIVATE_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
struct motion_filter_interface {
|
||||
void (*filter)(struct motion_filter *filter,
|
||||
struct motion_params *motion,
|
||||
void *data, uint64_t time);
|
||||
void (*destroy)(struct motion_filter *filter);
|
||||
bool (*set_speed)(struct motion_filter *filter,
|
||||
double speed);
|
||||
};
|
||||
|
||||
struct motion_filter {
|
||||
double speed; /* normalized [-1, 1] */
|
||||
struct motion_filter_interface *interface;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
101
src/filter.c
101
src/filter.c
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
|
@ -30,6 +31,7 @@
|
|||
|
||||
#include "filter.h"
|
||||
#include "libinput-util.h"
|
||||
#include "filter-private.h"
|
||||
|
||||
void
|
||||
filter_dispatch(struct motion_filter *filter,
|
||||
|
|
@ -48,12 +50,26 @@ filter_destroy(struct motion_filter *filter)
|
|||
filter->interface->destroy(filter);
|
||||
}
|
||||
|
||||
bool
|
||||
filter_set_speed(struct motion_filter *filter,
|
||||
double speed)
|
||||
{
|
||||
return filter->interface->set_speed(filter, speed);
|
||||
}
|
||||
|
||||
double
|
||||
filter_get_speed(struct motion_filter *filter)
|
||||
{
|
||||
return filter->speed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default parameters for pointer acceleration profiles.
|
||||
*/
|
||||
|
||||
#define DEFAULT_THRESHOLD 0.4 /* in units/ms */
|
||||
#define DEFAULT_ACCELERATION 2.0 /* unitless factor */
|
||||
#define DEFAULT_INCLINE 1.1 /* unitless factor */
|
||||
|
||||
/*
|
||||
* Pointer acceleration filter constants
|
||||
|
|
@ -83,6 +99,10 @@ struct pointer_accelerator {
|
|||
|
||||
struct pointer_tracker *trackers;
|
||||
int cur_tracker;
|
||||
|
||||
double threshold; /* units/ms */
|
||||
double accel; /* unitless factor */
|
||||
double incline; /* incline of the function */
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -119,8 +139,8 @@ tracker_by_offset(struct pointer_accelerator *accel, unsigned int offset)
|
|||
static double
|
||||
calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time)
|
||||
{
|
||||
int dx;
|
||||
int dy;
|
||||
double dx;
|
||||
double dy;
|
||||
double distance;
|
||||
|
||||
dx = tracker->dx;
|
||||
|
|
@ -233,13 +253,36 @@ accelerator_destroy(struct motion_filter *filter)
|
|||
free(accel);
|
||||
}
|
||||
|
||||
static bool
|
||||
accelerator_set_speed(struct motion_filter *filter,
|
||||
double speed)
|
||||
{
|
||||
struct pointer_accelerator *accel_filter =
|
||||
(struct pointer_accelerator *)filter;
|
||||
|
||||
assert(speed >= -1.0 && speed <= 1.0);
|
||||
|
||||
/* delay when accel kicks in */
|
||||
accel_filter->threshold = DEFAULT_THRESHOLD - speed/6.0;
|
||||
|
||||
/* adjust max accel factor */
|
||||
accel_filter->accel = DEFAULT_ACCELERATION + speed;
|
||||
|
||||
/* higher speed -> faster to reach max */
|
||||
accel_filter->incline = DEFAULT_INCLINE + speed/2.0;
|
||||
|
||||
filter->speed = speed;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct motion_filter_interface accelerator_interface = {
|
||||
accelerator_filter,
|
||||
accelerator_destroy
|
||||
accelerator_destroy,
|
||||
accelerator_set_speed,
|
||||
};
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelator_filter(accel_profile_func_t profile)
|
||||
create_pointer_accelerator_filter(accel_profile_func_t profile)
|
||||
{
|
||||
struct pointer_accelerator *filter;
|
||||
|
||||
|
|
@ -258,6 +301,10 @@ create_pointer_accelator_filter(accel_profile_func_t profile)
|
|||
calloc(NUM_POINTER_TRACKERS, sizeof *filter->trackers);
|
||||
filter->cur_tracker = 0;
|
||||
|
||||
filter->threshold = DEFAULT_THRESHOLD;
|
||||
filter->accel = DEFAULT_ACCELERATION;
|
||||
filter->incline = DEFAULT_INCLINE;
|
||||
|
||||
return &filter->base;
|
||||
}
|
||||
|
||||
|
|
@ -270,41 +317,21 @@ calc_penumbral_gradient(double x)
|
|||
}
|
||||
|
||||
double
|
||||
pointer_accel_profile_smooth_simple(struct motion_filter *filter,
|
||||
void *data,
|
||||
double velocity, /* units/ms */
|
||||
uint64_t time)
|
||||
pointer_accel_profile_linear(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in,
|
||||
uint64_t time)
|
||||
{
|
||||
double threshold = DEFAULT_THRESHOLD; /* units/ms */
|
||||
double accel = DEFAULT_ACCELERATION; /* unitless factor */
|
||||
double smooth_accel_coefficient; /* unitless factor */
|
||||
double factor; /* unitless factor */
|
||||
struct pointer_accelerator *accel_filter =
|
||||
(struct pointer_accelerator *)filter;
|
||||
|
||||
if (threshold < 0.1)
|
||||
threshold = 0.1;
|
||||
if (accel < 1.0)
|
||||
accel = 1.0;
|
||||
double s1, s2;
|
||||
const double max_accel = accel_filter->accel; /* unitless factor */
|
||||
const double threshold = accel_filter->threshold; /* units/ms */
|
||||
const double incline = accel_filter->incline;
|
||||
|
||||
/* We use units/ms as velocity but it has no real meaning unless all
|
||||
devices have the same resolution. For touchpads, we normalize to
|
||||
400dpi (15.75 units/mm), but the resolution on USB mice is all
|
||||
over the place. Though most mice these days have either 400
|
||||
dpi (15.75 units/mm), 800 dpi or 1000dpi, excluding gaming mice
|
||||
that can usually adjust it on the fly anyway and currently go up
|
||||
to 8200dpi.
|
||||
*/
|
||||
if (velocity < (threshold / 2.0))
|
||||
return calc_penumbral_gradient(0.5 + velocity / threshold) * 2.0 - 1.0;
|
||||
s1 = min(1, speed_in * 5);
|
||||
s2 = 1 + (speed_in - threshold) * incline;
|
||||
|
||||
if (velocity <= threshold)
|
||||
return 1.0;
|
||||
|
||||
factor = velocity/threshold;
|
||||
if (factor >= accel)
|
||||
return accel;
|
||||
|
||||
/* factor is between 1.0 and accel, scale this to 0.0 - 1.0 */
|
||||
factor = (factor - 1.0) / (accel - 1.0);
|
||||
smooth_accel_coefficient = calc_penumbral_gradient(factor);
|
||||
return 1.0 + (smooth_accel_coefficient * (accel - 1.0));
|
||||
return min(max_accel, s2 > 1 ? s2 : s1);
|
||||
}
|
||||
|
|
|
|||
37
src/filter.h
37
src/filter.h
|
|
@ -25,10 +25,14 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* The HW DPI rate we normalize to before calculating pointer acceleration */
|
||||
#define DEFAULT_MOUSE_DPI 1000
|
||||
|
||||
struct motion_params {
|
||||
double dx, dy; /* in units/ms @ 400dpi */
|
||||
double dx, dy; /* in units/ms @ DEFAULT_MOUSE_DPI resolution */
|
||||
};
|
||||
|
||||
struct motion_filter;
|
||||
|
|
@ -40,17 +44,11 @@ filter_dispatch(struct motion_filter *filter,
|
|||
void
|
||||
filter_destroy(struct motion_filter *filter);
|
||||
|
||||
|
||||
struct motion_filter_interface {
|
||||
void (*filter)(struct motion_filter *filter,
|
||||
struct motion_params *motion,
|
||||
void *data, uint64_t time);
|
||||
void (*destroy)(struct motion_filter *filter);
|
||||
};
|
||||
|
||||
struct motion_filter {
|
||||
struct motion_filter_interface *interface;
|
||||
};
|
||||
bool
|
||||
filter_set_speed(struct motion_filter *filter,
|
||||
double speed);
|
||||
double
|
||||
filter_get_speed(struct motion_filter *filter);
|
||||
|
||||
typedef double (*accel_profile_func_t)(struct motion_filter *filter,
|
||||
void *data,
|
||||
|
|
@ -58,21 +56,16 @@ typedef double (*accel_profile_func_t)(struct motion_filter *filter,
|
|||
uint64_t time);
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelator_filter(accel_profile_func_t filter);
|
||||
create_pointer_accelerator_filter(accel_profile_func_t filter);
|
||||
|
||||
|
||||
/*
|
||||
* Pointer acceleration profiles.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Profile similar which is similar to nonaccelerated but with a smooth
|
||||
* transition between accelerated and non-accelerated.
|
||||
*/
|
||||
double
|
||||
pointer_accel_profile_smooth_simple(struct motion_filter *filter,
|
||||
void *data,
|
||||
double velocity,
|
||||
uint64_t time);
|
||||
|
||||
pointer_accel_profile_linear(struct motion_filter *filter,
|
||||
void *data,
|
||||
double speed_in,
|
||||
uint64_t time);
|
||||
#endif /* FILTER_H */
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ struct libinput_interface_backend {
|
|||
int (*resume)(struct libinput *libinput);
|
||||
void (*suspend)(struct libinput *libinput);
|
||||
void (*destroy)(struct libinput *libinput);
|
||||
int (*device_change_seat)(struct libinput_device *device,
|
||||
const char *seat_name);
|
||||
};
|
||||
|
||||
struct libinput {
|
||||
|
|
@ -111,17 +113,56 @@ struct libinput_device_config_send_events {
|
|||
enum libinput_config_send_events_mode (*get_default_mode)(struct libinput_device *device);
|
||||
};
|
||||
|
||||
struct libinput_device_config_accel {
|
||||
int (*available)(struct libinput_device *device);
|
||||
enum libinput_config_status (*set_speed)(struct libinput_device *device,
|
||||
double speed);
|
||||
double (*get_speed)(struct libinput_device *device);
|
||||
double (*get_default_speed)(struct libinput_device *device);
|
||||
};
|
||||
|
||||
struct libinput_device_config_natural_scroll {
|
||||
int (*has)(struct libinput_device *device);
|
||||
enum libinput_config_status (*set_enabled)(struct libinput_device *device,
|
||||
int enabled);
|
||||
int (*get_enabled)(struct libinput_device *device);
|
||||
int (*get_default_enabled)(struct libinput_device *device);
|
||||
};
|
||||
|
||||
struct libinput_device_config_left_handed {
|
||||
int (*has)(struct libinput_device *device);
|
||||
enum libinput_config_status (*set)(struct libinput_device *device, int left_handed);
|
||||
int (*get)(struct libinput_device *device);
|
||||
int (*get_default)(struct libinput_device *device);
|
||||
};
|
||||
|
||||
struct libinput_device_config_scroll_method {
|
||||
uint32_t (*get_methods)(struct libinput_device *device);
|
||||
enum libinput_config_status (*set_method)(struct libinput_device *device,
|
||||
enum libinput_config_scroll_method method);
|
||||
enum libinput_config_scroll_method (*get_method)(struct libinput_device *device);
|
||||
enum libinput_config_scroll_method (*get_default_method)(struct libinput_device *device);
|
||||
enum libinput_config_status (*set_button)(struct libinput_device *device,
|
||||
uint32_t button);
|
||||
uint32_t (*get_button)(struct libinput_device *device);
|
||||
uint32_t (*get_default_button)(struct libinput_device *device);
|
||||
};
|
||||
|
||||
struct libinput_device_config {
|
||||
struct libinput_device_config_tap *tap;
|
||||
struct libinput_device_config_calibration *calibration;
|
||||
struct libinput_device_config_send_events *sendevents;
|
||||
struct libinput_device_config_accel *accel;
|
||||
struct libinput_device_config_natural_scroll *natural_scroll;
|
||||
struct libinput_device_config_left_handed *left_handed;
|
||||
struct libinput_device_config_scroll_method *scroll_method;
|
||||
};
|
||||
|
||||
struct libinput_device {
|
||||
struct libinput_seat *seat;
|
||||
struct list link;
|
||||
struct list event_listeners;
|
||||
void *user_data;
|
||||
int terminated;
|
||||
int refcount;
|
||||
struct libinput_device_config config;
|
||||
};
|
||||
|
|
@ -135,6 +176,17 @@ struct libinput_tool {
|
|||
void *user_data;
|
||||
};
|
||||
|
||||
struct libinput_event {
|
||||
enum libinput_event_type type;
|
||||
struct libinput_device *device;
|
||||
};
|
||||
|
||||
struct libinput_event_listener {
|
||||
struct list link;
|
||||
void (*notify_func)(uint64_t time, struct libinput_event *ev, void *notify_func_data);
|
||||
void *notify_func_data;
|
||||
};
|
||||
|
||||
typedef void (*libinput_source_dispatch_t)(void *data);
|
||||
|
||||
|
||||
|
|
@ -190,6 +242,18 @@ void
|
|||
libinput_device_init(struct libinput_device *device,
|
||||
struct libinput_seat *seat);
|
||||
|
||||
void
|
||||
libinput_device_add_event_listener(struct libinput_device *device,
|
||||
struct libinput_event_listener *listener,
|
||||
void (*notify_func)(
|
||||
uint64_t time,
|
||||
struct libinput_event *event,
|
||||
void *notify_func_data),
|
||||
void *notify_func_data);
|
||||
|
||||
void
|
||||
libinput_device_remove_event_listener(struct libinput_event_listener *listener);
|
||||
|
||||
void
|
||||
notify_added_device(struct libinput_device *device);
|
||||
|
||||
|
|
@ -198,37 +262,39 @@ notify_removed_device(struct libinput_device *device);
|
|||
|
||||
void
|
||||
keyboard_notify_key(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
uint32_t key,
|
||||
enum libinput_key_state state);
|
||||
|
||||
void
|
||||
pointer_notify_motion(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
double dx,
|
||||
double dy);
|
||||
double dy,
|
||||
double dx_noaccel,
|
||||
double dy_noaccel);
|
||||
|
||||
void
|
||||
pointer_notify_motion_absolute(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
double x,
|
||||
double y);
|
||||
|
||||
void
|
||||
pointer_notify_button(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
int32_t button,
|
||||
enum libinput_button_state state);
|
||||
|
||||
void
|
||||
pointer_notify_axis(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
enum libinput_pointer_axis axis,
|
||||
double value);
|
||||
|
||||
void
|
||||
touch_notify_touch_down(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
int32_t slot,
|
||||
int32_t seat_slot,
|
||||
double x,
|
||||
|
|
@ -236,7 +302,7 @@ touch_notify_touch_down(struct libinput_device *device,
|
|||
|
||||
void
|
||||
touch_notify_touch_motion(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
int32_t slot,
|
||||
int32_t seat_slot,
|
||||
double x,
|
||||
|
|
@ -244,7 +310,7 @@ touch_notify_touch_motion(struct libinput_device *device,
|
|||
|
||||
void
|
||||
touch_notify_touch_up(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
int32_t slot,
|
||||
int32_t seat_slot);
|
||||
|
||||
|
|
@ -276,7 +342,7 @@ tablet_notify_button(struct libinput_device *device,
|
|||
enum libinput_button_state state);
|
||||
void
|
||||
touch_notify_frame(struct libinput_device *device,
|
||||
uint32_t time);
|
||||
uint64_t time);
|
||||
|
||||
static inline uint64_t
|
||||
libinput_now(struct libinput *libinput)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
|
@ -65,3 +67,104 @@ list_empty(const struct list *list)
|
|||
{
|
||||
return list->next == list;
|
||||
}
|
||||
|
||||
void
|
||||
ratelimit_init(struct ratelimit *r, uint64_t ival_ms, unsigned int burst)
|
||||
{
|
||||
r->interval = ival_ms;
|
||||
r->begin = 0;
|
||||
r->burst = burst;
|
||||
r->num = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform rate-limit test. Returns RATELIMIT_PASS if the rate-limited action
|
||||
* is still allowed, RATELIMIT_THRESHOLD if the limit has been reached with
|
||||
* this call, and RATELIMIT_EXCEEDED if you're beyond the threshold.
|
||||
* It's safe to treat the return-value as boolean, if you're not interested in
|
||||
* the exact state. It evaluates to "true" if the threshold hasn't been
|
||||
* exceeded, yet.
|
||||
*
|
||||
* The ratelimit object must be initialized via ratelimit_init().
|
||||
*
|
||||
* Modelled after Linux' lib/ratelimit.c by Dave Young
|
||||
* <hidave.darkstar@gmail.com>, which is licensed GPLv2.
|
||||
*/
|
||||
enum ratelimit_state
|
||||
ratelimit_test(struct ratelimit *r)
|
||||
{
|
||||
struct timespec ts;
|
||||
uint64_t mtime;
|
||||
|
||||
if (r->interval <= 0 || r->burst <= 0)
|
||||
return RATELIMIT_PASS;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
mtime = ts.tv_sec * 1000 + ts.tv_nsec / 1000 / 1000;
|
||||
|
||||
if (r->begin <= 0 || r->begin + r->interval < mtime) {
|
||||
/* reset counter */
|
||||
r->begin = mtime;
|
||||
r->num = 1;
|
||||
return RATELIMIT_PASS;
|
||||
} else if (r->num < r->burst) {
|
||||
/* continue burst */
|
||||
return (++r->num == r->burst) ? RATELIMIT_THRESHOLD
|
||||
: RATELIMIT_PASS;
|
||||
}
|
||||
|
||||
return RATELIMIT_EXCEEDED;
|
||||
}
|
||||
|
||||
/* Helper function to parse the mouse DPI tag from udev.
|
||||
* The tag is of the form:
|
||||
* MOUSE_DPI=400 *1000 2000
|
||||
* or
|
||||
* MOUSE_DPI=400@125 *1000@125 2000@125
|
||||
* Where the * indicates the default value and @number indicates device poll
|
||||
* rate.
|
||||
* Numbers should be in ascending order, and if rates are present they should
|
||||
* be present for all entries.
|
||||
*
|
||||
* When parsing the mouse DPI property, if we find an error we just return 0
|
||||
* since it's obviously invalid, the caller will treat that as an error and
|
||||
* use a reasonable default instead. If the property contains multiple DPI
|
||||
* settings but none flagged as default, we return the last because we're
|
||||
* lazy and that's a silly way to set the property anyway.
|
||||
*/
|
||||
int
|
||||
parse_mouse_dpi_property(const char *prop)
|
||||
{
|
||||
bool is_default = false;
|
||||
int nread, dpi = 0, rate;
|
||||
|
||||
while (*prop != 0) {
|
||||
if (*prop == ' ') {
|
||||
prop++;
|
||||
continue;
|
||||
}
|
||||
if (*prop == '*') {
|
||||
prop++;
|
||||
is_default = true;
|
||||
if (!isdigit(prop[0]))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* While we don't do anything with the rate right now we
|
||||
* will validate that, if it's present, it is non-zero and
|
||||
* positive
|
||||
*/
|
||||
rate = 1;
|
||||
nread = 0;
|
||||
sscanf(prop, "%d@%d%n", &dpi, &rate, &nread);
|
||||
if (!nread)
|
||||
sscanf(prop, "%d%n", &dpi, &nread);
|
||||
if (!nread || dpi <= 0 || rate <= 0 || prop[nread] == '@')
|
||||
return 0;
|
||||
|
||||
if (is_default)
|
||||
break;
|
||||
prop += nread;
|
||||
}
|
||||
return dpi;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -304,4 +304,22 @@ matrix_to_farray6(const struct matrix *m, float out[6])
|
|||
out[5] = m->val[1][2];
|
||||
}
|
||||
|
||||
enum ratelimit_state {
|
||||
RATELIMIT_EXCEEDED,
|
||||
RATELIMIT_THRESHOLD,
|
||||
RATELIMIT_PASS,
|
||||
};
|
||||
|
||||
struct ratelimit {
|
||||
uint64_t interval;
|
||||
uint64_t begin;
|
||||
unsigned int burst;
|
||||
unsigned int num;
|
||||
};
|
||||
|
||||
void ratelimit_init(struct ratelimit *r, uint64_t ival_ms, unsigned int burst);
|
||||
enum ratelimit_state ratelimit_test(struct ratelimit *r);
|
||||
|
||||
int parse_mouse_dpi_property(const char *prop);
|
||||
|
||||
#endif /* LIBINPUT_UTIL_H */
|
||||
|
|
|
|||
339
src/libinput.c
339
src/libinput.c
|
|
@ -42,11 +42,6 @@ struct libinput_source {
|
|||
struct list link;
|
||||
};
|
||||
|
||||
struct libinput_event {
|
||||
enum libinput_event_type type;
|
||||
struct libinput_device *device;
|
||||
};
|
||||
|
||||
struct libinput_event_device_notify {
|
||||
struct libinput_event base;
|
||||
};
|
||||
|
|
@ -64,6 +59,8 @@ struct libinput_event_pointer {
|
|||
uint32_t time;
|
||||
double x;
|
||||
double y;
|
||||
double dx_unaccel;
|
||||
double dy_unaccel;
|
||||
uint32_t button;
|
||||
uint32_t seat_button_count;
|
||||
enum libinput_button_state state;
|
||||
|
|
@ -365,6 +362,20 @@ libinput_event_pointer_get_dy(struct libinput_event_pointer *event)
|
|||
return event->y;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
libinput_event_pointer_get_dx_unaccelerated(
|
||||
struct libinput_event_pointer *event)
|
||||
{
|
||||
return event->dx_unaccel;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
libinput_event_pointer_get_dy_unaccelerated(
|
||||
struct libinput_event_pointer *event)
|
||||
{
|
||||
return event->dy_unaccel;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event)
|
||||
{
|
||||
|
|
@ -867,6 +878,12 @@ libinput_seat_get_user_data(struct libinput_seat *seat)
|
|||
return seat->user_data;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput *
|
||||
libinput_seat_get_context(struct libinput_seat *seat)
|
||||
{
|
||||
return seat->libinput;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT const char *
|
||||
libinput_seat_get_physical_name(struct libinput_seat *seat)
|
||||
{
|
||||
|
|
@ -885,6 +902,7 @@ libinput_device_init(struct libinput_device *device,
|
|||
{
|
||||
device->seat = seat;
|
||||
device->refcount = 1;
|
||||
list_init(&device->event_listeners);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_device *
|
||||
|
|
@ -897,6 +915,7 @@ libinput_device_ref(struct libinput_device *device)
|
|||
static void
|
||||
libinput_device_destroy(struct libinput_device *device)
|
||||
{
|
||||
assert(list_empty(&device->event_listeners));
|
||||
evdev_device_destroy((struct evdev_device *) device);
|
||||
}
|
||||
|
||||
|
|
@ -943,6 +962,26 @@ libinput_dispatch(struct libinput *libinput)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
libinput_device_add_event_listener(struct libinput_device *device,
|
||||
struct libinput_event_listener *listener,
|
||||
void (*notify_func)(
|
||||
uint64_t time,
|
||||
struct libinput_event *event,
|
||||
void *notify_func_data),
|
||||
void *notify_func_data)
|
||||
{
|
||||
listener->notify_func = notify_func;
|
||||
listener->notify_func_data = notify_func_data;
|
||||
list_insert(&device->event_listeners, &listener->link);
|
||||
}
|
||||
|
||||
void
|
||||
libinput_device_remove_event_listener(struct libinput_event_listener *listener)
|
||||
{
|
||||
list_remove(&listener->link);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
update_seat_key_count(struct libinput_seat *seat,
|
||||
int32_t key,
|
||||
|
|
@ -1006,10 +1045,17 @@ post_base_event(struct libinput_device *device,
|
|||
|
||||
static void
|
||||
post_device_event(struct libinput_device *device,
|
||||
uint64_t time,
|
||||
enum libinput_event_type type,
|
||||
struct libinput_event *event)
|
||||
{
|
||||
struct libinput_event_listener *listener, *tmp;
|
||||
|
||||
init_event_base(event, device, type);
|
||||
|
||||
list_for_each_safe(listener, tmp, &device->event_listeners, link)
|
||||
listener->notify_func(time, event, listener->notify_func_data);
|
||||
|
||||
libinput_post_event(device->seat->libinput, event);
|
||||
}
|
||||
|
||||
|
|
@ -1043,7 +1089,7 @@ notify_removed_device(struct libinput_device *device)
|
|||
|
||||
void
|
||||
keyboard_notify_key(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
uint32_t key,
|
||||
enum libinput_key_state state)
|
||||
{
|
||||
|
|
@ -1063,16 +1109,18 @@ keyboard_notify_key(struct libinput_device *device,
|
|||
.seat_key_count = seat_key_count,
|
||||
};
|
||||
|
||||
post_device_event(device,
|
||||
post_device_event(device, time,
|
||||
LIBINPUT_EVENT_KEYBOARD_KEY,
|
||||
&key_event->base);
|
||||
}
|
||||
|
||||
void
|
||||
pointer_notify_motion(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
double dx,
|
||||
double dy)
|
||||
double dy,
|
||||
double dx_unaccel,
|
||||
double dy_unaccel)
|
||||
{
|
||||
struct libinput_event_pointer *motion_event;
|
||||
|
||||
|
|
@ -1084,16 +1132,18 @@ pointer_notify_motion(struct libinput_device *device,
|
|||
.time = time,
|
||||
.x = dx,
|
||||
.y = dy,
|
||||
.dx_unaccel = dx_unaccel,
|
||||
.dy_unaccel = dy_unaccel,
|
||||
};
|
||||
|
||||
post_device_event(device,
|
||||
post_device_event(device, time,
|
||||
LIBINPUT_EVENT_POINTER_MOTION,
|
||||
&motion_event->base);
|
||||
}
|
||||
|
||||
void
|
||||
pointer_notify_motion_absolute(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
|
|
@ -1109,14 +1159,14 @@ pointer_notify_motion_absolute(struct libinput_device *device,
|
|||
.y = y,
|
||||
};
|
||||
|
||||
post_device_event(device,
|
||||
post_device_event(device, time,
|
||||
LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE,
|
||||
&motion_absolute_event->base);
|
||||
}
|
||||
|
||||
void
|
||||
pointer_notify_button(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
int32_t button,
|
||||
enum libinput_button_state state)
|
||||
{
|
||||
|
|
@ -1138,14 +1188,14 @@ pointer_notify_button(struct libinput_device *device,
|
|||
.seat_button_count = seat_button_count,
|
||||
};
|
||||
|
||||
post_device_event(device,
|
||||
post_device_event(device, time,
|
||||
LIBINPUT_EVENT_POINTER_BUTTON,
|
||||
&button_event->base);
|
||||
}
|
||||
|
||||
void
|
||||
pointer_notify_axis(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
enum libinput_pointer_axis axis,
|
||||
double value)
|
||||
{
|
||||
|
|
@ -1161,14 +1211,14 @@ pointer_notify_axis(struct libinput_device *device,
|
|||
.value = value,
|
||||
};
|
||||
|
||||
post_device_event(device,
|
||||
post_device_event(device, time,
|
||||
LIBINPUT_EVENT_POINTER_AXIS,
|
||||
&axis_event->base);
|
||||
}
|
||||
|
||||
void
|
||||
touch_notify_touch_down(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
int32_t slot,
|
||||
int32_t seat_slot,
|
||||
double x,
|
||||
|
|
@ -1188,14 +1238,14 @@ touch_notify_touch_down(struct libinput_device *device,
|
|||
.y = y,
|
||||
};
|
||||
|
||||
post_device_event(device,
|
||||
post_device_event(device, time,
|
||||
LIBINPUT_EVENT_TOUCH_DOWN,
|
||||
&touch_event->base);
|
||||
}
|
||||
|
||||
void
|
||||
touch_notify_touch_motion(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
int32_t slot,
|
||||
int32_t seat_slot,
|
||||
double x,
|
||||
|
|
@ -1215,14 +1265,14 @@ touch_notify_touch_motion(struct libinput_device *device,
|
|||
.y = y,
|
||||
};
|
||||
|
||||
post_device_event(device,
|
||||
post_device_event(device, time,
|
||||
LIBINPUT_EVENT_TOUCH_MOTION,
|
||||
&touch_event->base);
|
||||
}
|
||||
|
||||
void
|
||||
touch_notify_touch_up(struct libinput_device *device,
|
||||
uint32_t time,
|
||||
uint64_t time,
|
||||
int32_t slot,
|
||||
int32_t seat_slot)
|
||||
{
|
||||
|
|
@ -1238,14 +1288,14 @@ touch_notify_touch_up(struct libinput_device *device,
|
|||
.seat_slot = seat_slot,
|
||||
};
|
||||
|
||||
post_device_event(device,
|
||||
post_device_event(device, time,
|
||||
LIBINPUT_EVENT_TOUCH_UP,
|
||||
&touch_event->base);
|
||||
}
|
||||
|
||||
void
|
||||
touch_notify_frame(struct libinput_device *device,
|
||||
uint32_t time)
|
||||
uint64_t time)
|
||||
{
|
||||
struct libinput_event_touch *touch_event;
|
||||
|
||||
|
|
@ -1257,7 +1307,7 @@ touch_notify_frame(struct libinput_device *device,
|
|||
.time = time,
|
||||
};
|
||||
|
||||
post_device_event(device,
|
||||
post_device_event(device, time,
|
||||
LIBINPUT_EVENT_TOUCH_FRAME,
|
||||
&touch_event->base);
|
||||
}
|
||||
|
|
@ -1286,6 +1336,7 @@ tablet_notify_axis(struct libinput_device *device,
|
|||
memcpy(axis_event->axes, axes, sizeof(axis_event->axes));
|
||||
|
||||
post_device_event(device,
|
||||
time,
|
||||
LIBINPUT_EVENT_TABLET_AXIS,
|
||||
&axis_event->base);
|
||||
}
|
||||
|
|
@ -1311,6 +1362,7 @@ tablet_notify_proximity_in(struct libinput_device *device,
|
|||
sizeof(proximity_in_event->axes));
|
||||
|
||||
post_device_event(device,
|
||||
time,
|
||||
LIBINPUT_EVENT_TABLET_PROXIMITY_IN,
|
||||
&proximity_in_event->base);
|
||||
}
|
||||
|
|
@ -1336,6 +1388,7 @@ tablet_notify_proximity_out(struct libinput_device *device,
|
|||
sizeof(proximity_out_update_event->axes));
|
||||
|
||||
post_device_event(device,
|
||||
time,
|
||||
LIBINPUT_EVENT_TABLET_PROXIMITY_OUT,
|
||||
&proximity_out_update_event->base);
|
||||
}
|
||||
|
|
@ -1369,6 +1422,7 @@ tablet_notify_button(struct libinput_device *device,
|
|||
memcpy(button_event->axes, axes, sizeof(button_event->axes));
|
||||
|
||||
post_device_event(device,
|
||||
time,
|
||||
LIBINPUT_EVENT_TABLET_BUTTON,
|
||||
&button_event->base);
|
||||
}
|
||||
|
|
@ -1475,6 +1529,12 @@ libinput_device_get_user_data(struct libinput_device *device)
|
|||
return device->user_data;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput *
|
||||
libinput_device_get_context(struct libinput_device *device)
|
||||
{
|
||||
return libinput_seat_get_context(device->seat);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT const char *
|
||||
libinput_device_get_sysname(struct libinput_device *device)
|
||||
{
|
||||
|
|
@ -1511,6 +1571,25 @@ libinput_device_get_seat(struct libinput_device *device)
|
|||
return device->seat;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_set_seat_logical_name(struct libinput_device *device,
|
||||
const char *name)
|
||||
{
|
||||
struct libinput *libinput = device->seat->libinput;
|
||||
|
||||
if (name == NULL)
|
||||
return -1;
|
||||
|
||||
return libinput->interface_backend->device_change_seat(device,
|
||||
name);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct udev_device *
|
||||
libinput_device_get_udev_device(struct libinput_device *device)
|
||||
{
|
||||
return evdev_device_get_udev_device((struct evdev_device *)device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT void
|
||||
libinput_device_led_update(struct libinput_device *device,
|
||||
enum libinput_led leds)
|
||||
|
|
@ -1552,6 +1631,12 @@ libinput_device_get_size(struct libinput_device *device,
|
|||
height);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_has_button(struct libinput_device *device, uint32_t code)
|
||||
{
|
||||
return evdev_device_has_button((struct evdev_device *)device, code);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_event *
|
||||
libinput_event_device_notify_get_base_event(struct libinput_event_device_notify *event)
|
||||
{
|
||||
|
|
@ -1685,9 +1770,9 @@ libinput_device_config_send_events_get_modes(struct libinput_device *device)
|
|||
|
||||
LIBINPUT_EXPORT enum libinput_config_status
|
||||
libinput_device_config_send_events_set_mode(struct libinput_device *device,
|
||||
enum libinput_config_send_events_mode mode)
|
||||
uint32_t mode)
|
||||
{
|
||||
if ((libinput_device_config_send_events_get_modes(device) & mode) == 0)
|
||||
if ((libinput_device_config_send_events_get_modes(device) & mode) != mode)
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
|
||||
if (device->config.sendevents)
|
||||
|
|
@ -1696,7 +1781,7 @@ libinput_device_config_send_events_set_mode(struct libinput_device *device,
|
|||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_send_events_mode
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_device_config_send_events_get_mode(struct libinput_device *device)
|
||||
{
|
||||
if (device->config.sendevents)
|
||||
|
|
@ -1705,8 +1790,206 @@ libinput_device_config_send_events_get_mode(struct libinput_device *device)
|
|||
return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_send_events_mode
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_device_config_send_events_get_default_mode(struct libinput_device *device)
|
||||
{
|
||||
return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
|
||||
}
|
||||
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_config_accel_is_available(struct libinput_device *device)
|
||||
{
|
||||
return device->config.accel ?
|
||||
device->config.accel->available(device) : 0;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_status
|
||||
libinput_device_config_accel_set_speed(struct libinput_device *device,
|
||||
double speed)
|
||||
{
|
||||
if (speed < -1.0 || speed > 1.0)
|
||||
return LIBINPUT_CONFIG_STATUS_INVALID;
|
||||
|
||||
if (!libinput_device_config_accel_is_available(device))
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
|
||||
return device->config.accel->set_speed(device, speed);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
libinput_device_config_accel_get_speed(struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_accel_is_available(device))
|
||||
return 0;
|
||||
|
||||
return device->config.accel->get_speed(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
libinput_device_config_accel_get_default_speed(struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_accel_is_available(device))
|
||||
return 0;
|
||||
|
||||
return device->config.accel->get_default_speed(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_config_scroll_has_natural_scroll(struct libinput_device *device)
|
||||
{
|
||||
if (!device->config.natural_scroll)
|
||||
return 0;
|
||||
|
||||
return device->config.natural_scroll->has(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_status
|
||||
libinput_device_config_scroll_set_natural_scroll_enabled(struct libinput_device *device,
|
||||
int enabled)
|
||||
{
|
||||
if (!libinput_device_config_scroll_has_natural_scroll(device))
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
|
||||
return device->config.natural_scroll->set_enabled(device, enabled);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_config_scroll_get_natural_scroll_enabled(struct libinput_device *device)
|
||||
{
|
||||
if (!device->config.natural_scroll)
|
||||
return 0;
|
||||
|
||||
return device->config.natural_scroll->get_enabled(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_config_scroll_get_default_natural_scroll_enabled(struct libinput_device *device)
|
||||
{
|
||||
if (!device->config.natural_scroll)
|
||||
return 0;
|
||||
|
||||
return device->config.natural_scroll->get_default_enabled(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_config_buttons_has_left_handed(struct libinput_device *device)
|
||||
{
|
||||
if (!device->config.left_handed)
|
||||
return 0;
|
||||
|
||||
return device->config.left_handed->has(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_status
|
||||
libinput_device_config_buttons_set_left_handed(struct libinput_device *device,
|
||||
int left_handed)
|
||||
{
|
||||
if (!libinput_device_config_buttons_has_left_handed(device))
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
|
||||
return device->config.left_handed->set(device, left_handed);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_config_buttons_get_left_handed(struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_buttons_has_left_handed(device))
|
||||
return 0;
|
||||
|
||||
return device->config.left_handed->get(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_config_buttons_get_default_left_handed(struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_buttons_has_left_handed(device))
|
||||
return 0;
|
||||
|
||||
return device->config.left_handed->get_default(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_device_config_scroll_get_methods(struct libinput_device *device)
|
||||
{
|
||||
if (device->config.scroll_method)
|
||||
return device->config.scroll_method->get_methods(device);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_status
|
||||
libinput_device_config_scroll_set_method(struct libinput_device *device,
|
||||
enum libinput_config_scroll_method method)
|
||||
{
|
||||
/* Check method is a single valid method */
|
||||
switch (method) {
|
||||
case LIBINPUT_CONFIG_SCROLL_NO_SCROLL:
|
||||
case LIBINPUT_CONFIG_SCROLL_2FG:
|
||||
case LIBINPUT_CONFIG_SCROLL_EDGE:
|
||||
case LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN:
|
||||
break;
|
||||
default:
|
||||
return LIBINPUT_CONFIG_STATUS_INVALID;
|
||||
}
|
||||
|
||||
if ((libinput_device_config_scroll_get_methods(device) & method) != method)
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
|
||||
if (device->config.scroll_method)
|
||||
return device->config.scroll_method->set_method(device, method);
|
||||
else /* method must be _NO_SCROLL to get here */
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_scroll_method
|
||||
libinput_device_config_scroll_get_method(struct libinput_device *device)
|
||||
{
|
||||
if (device->config.scroll_method)
|
||||
return device->config.scroll_method->get_method(device);
|
||||
else
|
||||
return LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_scroll_method
|
||||
libinput_device_config_scroll_get_default_method(struct libinput_device *device)
|
||||
{
|
||||
if (device->config.scroll_method)
|
||||
return device->config.scroll_method->get_default_method(device);
|
||||
else
|
||||
return LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_status
|
||||
libinput_device_config_scroll_set_button(struct libinput_device *device,
|
||||
uint32_t button)
|
||||
{
|
||||
if (button && !libinput_device_has_button(device, button))
|
||||
return LIBINPUT_CONFIG_STATUS_INVALID;
|
||||
|
||||
if ((libinput_device_config_scroll_get_methods(device) &
|
||||
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) == 0)
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
|
||||
return device->config.scroll_method->set_button(device, button);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_device_config_scroll_get_button(struct libinput_device *device)
|
||||
{
|
||||
if ((libinput_device_config_scroll_get_methods(device) &
|
||||
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) == 0)
|
||||
return 0;
|
||||
|
||||
return device->config.scroll_method->get_button(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_device_config_scroll_get_default_button(struct libinput_device *device)
|
||||
{
|
||||
if ((libinput_device_config_scroll_get_methods(device) &
|
||||
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) == 0)
|
||||
return 0;
|
||||
|
||||
return device->config.scroll_method->get_default_button(device);
|
||||
}
|
||||
|
|
|
|||
765
src/libinput.h
765
src/libinput.h
File diff suppressed because it is too large
Load diff
184
src/path.c
184
src/path.c
|
|
@ -109,63 +109,34 @@ path_seat_get_named(struct path_input *input,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
path_get_udev_properties(const char *path,
|
||||
char **sysname,
|
||||
char **syspath,
|
||||
char **seat_name,
|
||||
char **seat_logical_name)
|
||||
{
|
||||
struct udev *udev = NULL;
|
||||
struct udev_device *device = NULL;
|
||||
struct stat st;
|
||||
const char *seat;
|
||||
int rc = -1;
|
||||
|
||||
udev = udev_new();
|
||||
if (!udev)
|
||||
goto out;
|
||||
|
||||
if (stat(path, &st) < 0)
|
||||
goto out;
|
||||
|
||||
device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
|
||||
if (!device)
|
||||
goto out;
|
||||
|
||||
*sysname = strdup(udev_device_get_sysname(device));
|
||||
*syspath = strdup(udev_device_get_syspath(device));
|
||||
|
||||
seat = udev_device_get_property_value(device, "ID_SEAT");
|
||||
*seat_name = strdup(seat ? seat : default_seat);
|
||||
|
||||
seat = udev_device_get_property_value(device, "WL_SEAT");
|
||||
*seat_logical_name = strdup(seat ? seat : default_seat_name);
|
||||
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
if (device)
|
||||
udev_device_unref(device);
|
||||
if (udev)
|
||||
udev_unref(udev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct libinput_device *
|
||||
path_device_enable(struct path_input *input, const char *devnode)
|
||||
path_device_enable(struct path_input *input,
|
||||
struct udev_device *udev_device,
|
||||
const char *seat_logical_name_override)
|
||||
{
|
||||
struct path_seat *seat;
|
||||
struct evdev_device *device = NULL;
|
||||
char *sysname = NULL, *syspath = NULL;
|
||||
char *seat_name = NULL, *seat_logical_name = NULL;
|
||||
const char *seat_prop;
|
||||
const char *devnode;
|
||||
|
||||
if (path_get_udev_properties(devnode, &sysname, &syspath,
|
||||
&seat_name, &seat_logical_name) == -1) {
|
||||
log_info(&input->base,
|
||||
"failed to obtain sysname for device '%s'.\n",
|
||||
devnode);
|
||||
return NULL;
|
||||
devnode = udev_device_get_devnode(udev_device);
|
||||
|
||||
seat_prop = udev_device_get_property_value(udev_device, "ID_SEAT");
|
||||
seat_name = strdup(seat_prop ? seat_prop : default_seat);
|
||||
|
||||
if (seat_logical_name_override) {
|
||||
seat_logical_name = strdup(seat_logical_name_override);
|
||||
} else {
|
||||
seat_prop = udev_device_get_property_value(udev_device, "WL_SEAT");
|
||||
seat_logical_name = strdup(seat_prop ? seat_prop : default_seat_name);
|
||||
}
|
||||
|
||||
if (!seat_logical_name) {
|
||||
log_error(&input->base,
|
||||
"failed to create seat name for device '%s'.\n",
|
||||
devnode);
|
||||
goto out;
|
||||
}
|
||||
|
||||
seat = path_seat_get_named(input, seat_name, seat_logical_name);
|
||||
|
|
@ -182,7 +153,7 @@ path_device_enable(struct path_input *input, const char *devnode)
|
|||
}
|
||||
}
|
||||
|
||||
device = evdev_device_create(&seat->base, devnode, sysname, syspath);
|
||||
device = evdev_device_create(&seat->base, udev_device);
|
||||
libinput_seat_unref(&seat->base);
|
||||
|
||||
if (device == EVDEV_UNHANDLED_DEVICE) {
|
||||
|
|
@ -199,8 +170,6 @@ path_device_enable(struct path_input *input, const char *devnode)
|
|||
}
|
||||
|
||||
out:
|
||||
free(sysname);
|
||||
free(syspath);
|
||||
free(seat_name);
|
||||
free(seat_logical_name);
|
||||
|
||||
|
|
@ -214,7 +183,7 @@ path_input_enable(struct libinput *libinput)
|
|||
struct path_device *dev;
|
||||
|
||||
list_for_each(dev, &input->path_list, link) {
|
||||
if (path_device_enable(input, dev->path) == NULL) {
|
||||
if (path_device_enable(input, dev->udev_device, NULL) == NULL) {
|
||||
path_input_disable(libinput);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -229,17 +198,67 @@ path_input_destroy(struct libinput *input)
|
|||
struct path_input *path_input = (struct path_input*)input;
|
||||
struct path_device *dev, *tmp;
|
||||
|
||||
udev_unref(path_input->udev);
|
||||
|
||||
list_for_each_safe(dev, tmp, &path_input->path_list, link) {
|
||||
free(dev->path);
|
||||
udev_device_unref(dev->udev_device);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static struct libinput_device *
|
||||
path_create_device(struct libinput *libinput,
|
||||
struct udev_device *udev_device,
|
||||
const char *seat_name)
|
||||
{
|
||||
struct path_input *input = (struct path_input*)libinput;
|
||||
struct path_device *dev;
|
||||
struct libinput_device *device;
|
||||
|
||||
dev = zalloc(sizeof *dev);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
dev->udev_device = udev_device_ref(udev_device);
|
||||
|
||||
list_insert(&input->path_list, &dev->link);
|
||||
|
||||
device = path_device_enable(input, udev_device, seat_name);
|
||||
|
||||
if (!device) {
|
||||
udev_device_unref(dev->udev_device);
|
||||
list_remove(&dev->link);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
static int
|
||||
path_device_change_seat(struct libinput_device *device,
|
||||
const char *seat_name)
|
||||
{
|
||||
struct libinput *libinput = device->seat->libinput;
|
||||
struct evdev_device *evdev_device = (struct evdev_device *)device;
|
||||
struct udev_device *udev_device = NULL;
|
||||
int rc = -1;
|
||||
|
||||
udev_device = evdev_device->udev_device;
|
||||
udev_device_ref(udev_device);
|
||||
libinput_path_remove_device(device);
|
||||
|
||||
if (path_create_device(libinput, udev_device, seat_name) != NULL)
|
||||
rc = 0;
|
||||
udev_device_unref(udev_device);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct libinput_interface_backend interface_backend = {
|
||||
.resume = path_input_enable,
|
||||
.suspend = path_input_disable,
|
||||
.destroy = path_input_destroy,
|
||||
.device_change_seat = path_device_change_seat,
|
||||
};
|
||||
|
||||
LIBINPUT_EXPORT struct libinput *
|
||||
|
|
@ -247,31 +266,48 @@ libinput_path_create_context(const struct libinput_interface *interface,
|
|||
void *user_data)
|
||||
{
|
||||
struct path_input *input;
|
||||
struct udev *udev;
|
||||
|
||||
if (!interface)
|
||||
return NULL;
|
||||
|
||||
input = zalloc(sizeof *input);
|
||||
if (!input)
|
||||
udev = udev_new();
|
||||
if (!udev)
|
||||
return NULL;
|
||||
|
||||
if (libinput_init(&input->base, interface,
|
||||
input = zalloc(sizeof *input);
|
||||
if (!input ||
|
||||
libinput_init(&input->base, interface,
|
||||
&interface_backend, user_data) != 0) {
|
||||
udev_unref(udev);
|
||||
free(input);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
input->udev = udev;
|
||||
list_init(&input->path_list);
|
||||
|
||||
return &input->base;
|
||||
}
|
||||
|
||||
static inline struct udev_device *
|
||||
udev_device_from_devnode(struct udev *udev, const char *devnode)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(devnode, &st) < 0)
|
||||
return NULL;
|
||||
|
||||
return udev_device_new_from_devnum(udev, 'c', st.st_rdev);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT struct libinput_device *
|
||||
libinput_path_add_device(struct libinput *libinput,
|
||||
const char *path)
|
||||
{
|
||||
struct path_input *input = (struct path_input*)libinput;
|
||||
struct path_device *dev;
|
||||
struct path_input *input = (struct path_input *)libinput;
|
||||
struct udev *udev = input->udev;
|
||||
struct udev_device *udev_device;
|
||||
struct libinput_device *device;
|
||||
|
||||
if (libinput->interface_backend != &interface_backend) {
|
||||
|
|
@ -279,26 +315,14 @@ libinput_path_add_device(struct libinput *libinput,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
dev = zalloc(sizeof *dev);
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
dev->path = strdup(path);
|
||||
if (!dev->path) {
|
||||
free(dev);
|
||||
udev_device = udev_device_from_devnode(udev, path);
|
||||
if (!udev_device) {
|
||||
log_bug_client(libinput, "Invalid path %s\n", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_insert(&input->path_list, &dev->link);
|
||||
|
||||
device = path_device_enable(input, dev->path);
|
||||
|
||||
if (!device) {
|
||||
list_remove(&dev->link);
|
||||
free(dev->path);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
device = path_create_device(libinput, udev_device, NULL);
|
||||
udev_device_unref(udev_device);
|
||||
return device;
|
||||
}
|
||||
|
||||
|
|
@ -317,9 +341,9 @@ libinput_path_remove_device(struct libinput_device *device)
|
|||
}
|
||||
|
||||
list_for_each(dev, &input->path_list, link) {
|
||||
if (strcmp(evdev->devnode, dev->path) == 0) {
|
||||
if (dev->udev_device == evdev->udev_device) {
|
||||
list_remove(&dev->link);
|
||||
free(dev->path);
|
||||
udev_device_unref(dev->udev_device);
|
||||
free(dev);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,12 +28,13 @@
|
|||
|
||||
struct path_input {
|
||||
struct libinput base;
|
||||
struct udev *udev;
|
||||
struct list path_list;
|
||||
};
|
||||
|
||||
struct path_device {
|
||||
struct list link;
|
||||
char *path;
|
||||
struct udev_device *udev_device;
|
||||
};
|
||||
|
||||
struct path_seat {
|
||||
|
|
|
|||
|
|
@ -42,13 +42,13 @@ static struct udev_seat *
|
|||
udev_seat_get_named(struct udev_input *input, const char *seat_name);
|
||||
|
||||
static int
|
||||
device_added(struct udev_device *udev_device, struct udev_input *input)
|
||||
device_added(struct udev_device *udev_device,
|
||||
struct udev_input *input,
|
||||
const char *seat_name)
|
||||
{
|
||||
struct evdev_device *device;
|
||||
const char *devnode;
|
||||
const char *sysname;
|
||||
const char *syspath;
|
||||
const char *device_seat, *seat_name, *output_name;
|
||||
const char *device_seat, *output_name;
|
||||
const char *calibration_values;
|
||||
float calibration[6];
|
||||
struct udev_seat *seat;
|
||||
|
|
@ -61,11 +61,10 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
|
|||
return 0;
|
||||
|
||||
devnode = udev_device_get_devnode(udev_device);
|
||||
sysname = udev_device_get_sysname(udev_device);
|
||||
syspath = udev_device_get_syspath(udev_device);
|
||||
|
||||
/* Search for matching logical seat */
|
||||
seat_name = udev_device_get_property_value(udev_device, "WL_SEAT");
|
||||
if (!seat_name)
|
||||
seat_name = udev_device_get_property_value(udev_device, "WL_SEAT");
|
||||
if (!seat_name)
|
||||
seat_name = default_seat_name;
|
||||
|
||||
|
|
@ -79,7 +78,7 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
|
|||
return -1;
|
||||
}
|
||||
|
||||
device = evdev_device_create(&seat->base, devnode, sysname, syspath);
|
||||
device = evdev_device_create(&seat->base, udev_device);
|
||||
libinput_seat_unref(&seat->base);
|
||||
|
||||
if (device == EVDEV_UNHANDLED_DEVICE) {
|
||||
|
|
@ -94,7 +93,8 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
|
|||
udev_device_get_property_value(udev_device,
|
||||
"LIBINPUT_CALIBRATION_MATRIX");
|
||||
|
||||
if (calibration_values && sscanf(calibration_values,
|
||||
if (device->abs.absinfo_x && device->abs.absinfo_y &&
|
||||
calibration_values && sscanf(calibration_values,
|
||||
"%f %f %f %f %f %f",
|
||||
&calibration[0],
|
||||
&calibration[1],
|
||||
|
|
@ -123,18 +123,20 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
|
|||
static void
|
||||
device_removed(struct udev_device *udev_device, struct udev_input *input)
|
||||
{
|
||||
const char *devnode;
|
||||
struct evdev_device *device, *next;
|
||||
struct udev_seat *seat;
|
||||
const char *syspath;
|
||||
|
||||
devnode = udev_device_get_devnode(udev_device);
|
||||
syspath = udev_device_get_syspath(udev_device);
|
||||
list_for_each(seat, &input->base.seat_list, base.link) {
|
||||
list_for_each_safe(device, next,
|
||||
&seat->base.devices_list, base.link) {
|
||||
if (!strcmp(device->devnode, devnode)) {
|
||||
if (!strcmp(syspath,
|
||||
udev_device_get_syspath(device->udev_device))) {
|
||||
log_info(&input->base,
|
||||
"input device %s, %s removed\n",
|
||||
device->devname, device->devnode);
|
||||
device->devname,
|
||||
udev_device_get_devnode(device->udev_device));
|
||||
evdev_device_remove(device);
|
||||
break;
|
||||
}
|
||||
|
|
@ -163,7 +165,7 @@ udev_input_add_devices(struct udev_input *input, struct udev *udev)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (device_added(device, input) < 0) {
|
||||
if (device_added(device, input, NULL) < 0) {
|
||||
udev_device_unref(device);
|
||||
udev_enumerate_unref(e);
|
||||
return -1;
|
||||
|
|
@ -195,7 +197,7 @@ evdev_udev_handler(void *data)
|
|||
goto out;
|
||||
|
||||
if (!strcmp(action, "add"))
|
||||
device_added(udev_device, input);
|
||||
device_added(udev_device, input, NULL);
|
||||
else if (!strcmp(action, "remove"))
|
||||
device_removed(udev_device, input);
|
||||
|
||||
|
|
@ -331,10 +333,29 @@ udev_seat_get_named(struct udev_input *input, const char *seat_name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
udev_device_change_seat(struct libinput_device *device,
|
||||
const char *seat_name)
|
||||
{
|
||||
struct libinput *libinput = device->seat->libinput;
|
||||
struct udev_input *input = (struct udev_input *)libinput;
|
||||
struct evdev_device *evdev_device = (struct evdev_device *)device;
|
||||
struct udev_device *udev_device = evdev_device->udev_device;
|
||||
int rc;
|
||||
|
||||
udev_device_ref(udev_device);
|
||||
device_removed(udev_device, input);
|
||||
rc = device_added(udev_device, input, seat_name);
|
||||
udev_device_unref(udev_device);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct libinput_interface_backend interface_backend = {
|
||||
.resume = udev_input_enable,
|
||||
.suspend = udev_input_disable,
|
||||
.destroy = udev_input_destroy,
|
||||
.device_change_seat = udev_device_change_seat,
|
||||
};
|
||||
|
||||
LIBINPUT_EXPORT struct libinput *
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ AM_CXXFLAGS = $(GCC_CXXFLAGS)
|
|||
TEST_LIBS = liblitest.la $(CHECK_LIBS) $(LIBUDEV_LIBS) $(LIBEVDEV_LIBS) $(top_builddir)/src/libinput.la
|
||||
noinst_LTLIBRARIES = liblitest.la
|
||||
liblitest_la_SOURCES = \
|
||||
../src/libinput-util.h \
|
||||
../src/libinput-util.c \
|
||||
litest.h \
|
||||
litest-int.h \
|
||||
litest-alps-semi-mt.c \
|
||||
|
|
@ -20,6 +18,8 @@ liblitest_la_SOURCES = \
|
|||
litest-generic-singletouch.c \
|
||||
litest-keyboard.c \
|
||||
litest-mouse.c \
|
||||
litest-ms-surface-cover.c \
|
||||
litest-qemu-usb-tablet.c \
|
||||
litest-synaptics.c \
|
||||
litest-synaptics-st.c \
|
||||
litest-synaptics-t440.c \
|
||||
|
|
@ -29,7 +29,10 @@ liblitest_la_SOURCES = \
|
|||
litest-wacom-intuos-tablet.c \
|
||||
litest-wacom-isdv4-tablet.c \
|
||||
litest-wacom-touch.c \
|
||||
litest-xen-virtual-pointer.c \
|
||||
litest-vmware-virtual-usb-mouse.c \
|
||||
litest.c
|
||||
liblitest_la_LIBADD = $(top_builddir)/src/libinput-util.la
|
||||
|
||||
run_tests = \
|
||||
test-udev \
|
||||
|
|
@ -109,7 +112,7 @@ test_build_std_gnuc90_CFLAGS = -std=gnu90 -Werror
|
|||
# test for linking with the minimal linker flags
|
||||
test_build_linker_SOURCES = build-pedantic.c
|
||||
test_build_linker_CFLAGS = -I$(top_srcdir)/src
|
||||
test_build_linker_LDADD = $(top_builddir)/src/libinput.la
|
||||
test_build_linker_LDADD = $(top_builddir)/src/libinput.la $(top_builddir)/src/libinput-util.la
|
||||
|
||||
# test including from C++
|
||||
test_build_cxx_SOURCES = build-cxx.cc
|
||||
|
|
|
|||
|
|
@ -42,11 +42,24 @@ START_TEST(device_sendevents_config)
|
|||
|
||||
modes = libinput_device_config_send_events_get_modes(device);
|
||||
ck_assert_int_eq(modes,
|
||||
LIBINPUT_CONFIG_SEND_EVENTS_ENABLED|
|
||||
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_sendevents_config_invalid)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device;
|
||||
enum libinput_config_status status;
|
||||
|
||||
device = dev->libinput_device;
|
||||
|
||||
status = libinput_device_config_send_events_set_mode(device,
|
||||
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED | (1 << 4));
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_sendevents_config_touchpad)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -57,12 +70,33 @@ START_TEST(device_sendevents_config_touchpad)
|
|||
|
||||
modes = libinput_device_config_send_events_get_modes(device);
|
||||
ck_assert_int_eq(modes,
|
||||
LIBINPUT_CONFIG_SEND_EVENTS_ENABLED|
|
||||
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE|
|
||||
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_sendevents_config_touchpad_superset)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device;
|
||||
enum libinput_config_status status;
|
||||
uint32_t modes;
|
||||
|
||||
device = dev->libinput_device;
|
||||
|
||||
modes = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED |
|
||||
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
|
||||
|
||||
status = libinput_device_config_send_events_set_mode(device,
|
||||
modes);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
/* DISABLED supersedes the rest, expect the rest to be dropped */
|
||||
modes = libinput_device_config_send_events_get_mode(device);
|
||||
ck_assert_int_eq(modes, LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_sendevents_config_default)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -131,7 +165,7 @@ START_TEST(device_disable_touchpad)
|
|||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 90, 90, 10);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 90, 90, 10, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
|
||||
|
|
@ -404,7 +438,7 @@ START_TEST(device_disable_release_tap)
|
|||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
/* tap happened before suspending, so we still expect the event */
|
||||
|
||||
msleep(300); /* tap-n-drag timeout */
|
||||
litest_timeout_tap();
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
|
|
@ -443,7 +477,7 @@ START_TEST(device_disable_release_tap_n_drag)
|
|||
litest_touch_up(dev, 0);
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
libinput_dispatch(li);
|
||||
msleep(400); /* tap-n-drag timeout */
|
||||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_send_events_set_mode(device,
|
||||
|
|
@ -565,16 +599,60 @@ START_TEST(device_disable_topsoftbutton)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_ids)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
const char *name;
|
||||
unsigned int pid, vid;
|
||||
|
||||
name = libevdev_get_name(dev->evdev);
|
||||
pid = libevdev_get_id_product(dev->evdev);
|
||||
vid = libevdev_get_id_vendor(dev->evdev);
|
||||
|
||||
ck_assert_str_eq(name,
|
||||
libinput_device_get_name(dev->libinput_device));
|
||||
ck_assert_int_eq(pid,
|
||||
libinput_device_get_id_product(dev->libinput_device));
|
||||
ck_assert_int_eq(vid,
|
||||
libinput_device_get_id_vendor(dev->libinput_device));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_get_udev_handle)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct udev_device *udev_device;
|
||||
|
||||
udev_device = libinput_device_get_udev_device(dev->libinput_device);
|
||||
ck_assert_notnull(udev_device);
|
||||
udev_device_unref(udev_device);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_context)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_seat *seat;
|
||||
|
||||
ck_assert(dev->libinput == libinput_device_get_context(dev->libinput_device));
|
||||
seat = libinput_device_get_seat(dev->libinput_device);
|
||||
ck_assert(dev->libinput == libinput_seat_get_context(seat));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
litest_add("device:sendevents", device_sendevents_config, LITEST_ANY, LITEST_TOUCHPAD|LITEST_TABLET);
|
||||
litest_add("device:sendevents", device_sendevents_config_invalid, LITEST_ANY, LITEST_TABLET);
|
||||
litest_add("device:sendevents", device_sendevents_config_touchpad, LITEST_TOUCHPAD, LITEST_TABLET);
|
||||
litest_add("device:sendevents", device_sendevents_config_touchpad_superset, LITEST_TOUCHPAD, LITEST_TABLET);
|
||||
litest_add("device:sendevents", device_sendevents_config_default, LITEST_ANY, LITEST_TABLET);
|
||||
litest_add("device:sendevents", device_disable, LITEST_POINTER, LITEST_TABLET);
|
||||
litest_add("device:sendevents", device_disable, LITEST_RELATIVE, LITEST_TABLET);
|
||||
litest_add("device:sendevents", device_disable_touchpad, LITEST_TOUCHPAD, LITEST_TABLET);
|
||||
litest_add("device:sendevents", device_disable_events_pending, LITEST_POINTER, LITEST_TOUCHPAD|LITEST_TABLET);
|
||||
litest_add("device:sendevents", device_disable_events_pending, LITEST_RELATIVE, LITEST_TOUCHPAD|LITEST_TABLET);
|
||||
litest_add("device:sendevents", device_double_disable, LITEST_ANY, LITEST_TABLET);
|
||||
litest_add("device:sendevents", device_double_enable, LITEST_ANY, LITEST_TABLET);
|
||||
|
||||
litest_add_no_device("device:sendevents", device_reenable_syspath_changed);
|
||||
litest_add_no_device("device:sendevents", device_reenable_device_removed);
|
||||
litest_add_for_device("device:sendevents", device_disable_release_buttons, LITEST_MOUSE);
|
||||
|
|
@ -582,8 +660,11 @@ int main (int argc, char **argv)
|
|||
litest_add("device:sendevents", device_disable_release_tap, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("device:sendevents", device_disable_release_tap_n_drag, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("device:sendevents", device_disable_release_softbutton, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD);
|
||||
|
||||
litest_add("device:sendevents", device_disable_topsoftbutton, LITEST_TOPBUTTONPAD, LITEST_ANY);
|
||||
litest_add("device:id", device_ids, LITEST_ANY, LITEST_ANY);
|
||||
litest_add_for_device("device:context", device_context, LITEST_SYNAPTICS_CLICKPAD);
|
||||
|
||||
litest_add("device:udev", device_get_udev_handle, LITEST_ANY, LITEST_ANY);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ static int events[] = {
|
|||
|
||||
struct litest_test_device litest_mouse_device = {
|
||||
.type = LITEST_MOUSE,
|
||||
.features = LITEST_POINTER | LITEST_BUTTON | LITEST_WHEEL,
|
||||
.features = LITEST_RELATIVE | LITEST_BUTTON | LITEST_WHEEL,
|
||||
.shortname = "mouse",
|
||||
.setup = litest_mouse_setup,
|
||||
.interface = &interface,
|
||||
|
|
|
|||
386
test/litest-ms-surface-cover.c
Normal file
386
test/litest-ms-surface-cover.c
Normal file
|
|
@ -0,0 +1,386 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
|
||||
static void
|
||||
litest_ms_surface_cover_setup(void)
|
||||
{
|
||||
struct litest_device *d = litest_create_device(LITEST_MS_SURFACE_COVER);
|
||||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static struct input_event down[] = {
|
||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
static struct input_event move[] = {
|
||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||
{ .type = -1, .code = -1 },
|
||||
};
|
||||
|
||||
/* We define down/move so that we can emulate fake touches on this device,
|
||||
to make sure nothing crashes. */
|
||||
static struct litest_device_interface interface = {
|
||||
.touch_down_events = down,
|
||||
.touch_move_events = move,
|
||||
};
|
||||
|
||||
static struct input_absinfo absinfo[] = {
|
||||
{ ABS_VOLUME, 0, 1023, 0, 0, 0 },
|
||||
{ ABS_MISC, 0, 255, 0, 0, 0 },
|
||||
{ 41, 0, 255, 0, 0, 0 },
|
||||
{ 42, -127, 127, 0, 0, 0 },
|
||||
{ 43, -127, 127, 0, 0, 0 },
|
||||
{ 44, -127, 127, 0, 0, 0 },
|
||||
{ 45, -127, 127, 0, 0, 0 },
|
||||
{ 46, -127, 127, 0, 0, 0 },
|
||||
{ 47, -127, 127, 0, 0, 0 },
|
||||
/* ABS_MT range overlap starts here */
|
||||
{ 48, -127, 127, 0, 0, 0 }, /* ABS_MT_SLOT */
|
||||
{ 49, -127, 127, 0, 0, 0 },
|
||||
{ 50, -127, 127, 0, 0, 0 },
|
||||
{ 51, -127, 127, 0, 0, 0 },
|
||||
{ 52, -127, 127, 0, 0, 0 },
|
||||
{ 53, -127, 127, 0, 0, 0 },
|
||||
{ 54, -127, 127, 0, 0, 0 },
|
||||
{ 55, -127, 127, 0, 0, 0 },
|
||||
{ 56, -127, 127, 0, 0, 0 },
|
||||
{ 57, -127, 127, 0, 0, 0 },
|
||||
{ 58, -127, 127, 0, 0, 0 },
|
||||
{ 59, -127, 127, 0, 0, 0 },
|
||||
{ 60, -127, 127, 0, 0, 0 },
|
||||
{ 61, -127, 127, 0, 0, 0 }, /* ABS_MT_TOOL_Y */
|
||||
{ 62, -127, 127, 0, 0, 0 },
|
||||
{ .value = -1 },
|
||||
};
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x3,
|
||||
.vendor = 0x45e,
|
||||
.product = 0x7a9,
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
EV_REL, REL_X,
|
||||
EV_REL, REL_Y,
|
||||
EV_REL, REL_HWHEEL,
|
||||
EV_REL, REL_DIAL,
|
||||
EV_REL, REL_WHEEL,
|
||||
EV_KEY, KEY_ESC,
|
||||
EV_KEY, KEY_1,
|
||||
EV_KEY, KEY_2,
|
||||
EV_KEY, KEY_3,
|
||||
EV_KEY, KEY_4,
|
||||
EV_KEY, KEY_5,
|
||||
EV_KEY, KEY_6,
|
||||
EV_KEY, KEY_7,
|
||||
EV_KEY, KEY_8,
|
||||
EV_KEY, KEY_9,
|
||||
EV_KEY, KEY_0,
|
||||
EV_KEY, KEY_MINUS,
|
||||
EV_KEY, KEY_EQUAL,
|
||||
EV_KEY, KEY_BACKSPACE,
|
||||
EV_KEY, KEY_TAB,
|
||||
EV_KEY, KEY_Q,
|
||||
EV_KEY, KEY_W,
|
||||
EV_KEY, KEY_E,
|
||||
EV_KEY, KEY_R,
|
||||
EV_KEY, KEY_T,
|
||||
EV_KEY, KEY_Y,
|
||||
EV_KEY, KEY_U,
|
||||
EV_KEY, KEY_I,
|
||||
EV_KEY, KEY_O,
|
||||
EV_KEY, KEY_P,
|
||||
EV_KEY, KEY_LEFTBRACE,
|
||||
EV_KEY, KEY_RIGHTBRACE,
|
||||
EV_KEY, KEY_ENTER,
|
||||
EV_KEY, KEY_LEFTCTRL,
|
||||
EV_KEY, KEY_A,
|
||||
EV_KEY, KEY_S,
|
||||
EV_KEY, KEY_D,
|
||||
EV_KEY, KEY_F,
|
||||
EV_KEY, KEY_G,
|
||||
EV_KEY, KEY_H,
|
||||
EV_KEY, KEY_J,
|
||||
EV_KEY, KEY_K,
|
||||
EV_KEY, KEY_L,
|
||||
EV_KEY, KEY_SEMICOLON,
|
||||
EV_KEY, KEY_APOSTROPHE,
|
||||
EV_KEY, KEY_GRAVE,
|
||||
EV_KEY, KEY_LEFTSHIFT,
|
||||
EV_KEY, KEY_BACKSLASH,
|
||||
EV_KEY, KEY_Z,
|
||||
EV_KEY, KEY_X,
|
||||
EV_KEY, KEY_C,
|
||||
EV_KEY, KEY_V,
|
||||
EV_KEY, KEY_B,
|
||||
EV_KEY, KEY_N,
|
||||
EV_KEY, KEY_M,
|
||||
EV_KEY, KEY_COMMA,
|
||||
EV_KEY, KEY_DOT,
|
||||
EV_KEY, KEY_SLASH,
|
||||
EV_KEY, KEY_RIGHTSHIFT,
|
||||
EV_KEY, KEY_KPASTERISK,
|
||||
EV_KEY, KEY_LEFTALT,
|
||||
EV_KEY, KEY_SPACE,
|
||||
EV_KEY, KEY_CAPSLOCK,
|
||||
EV_KEY, KEY_F1,
|
||||
EV_KEY, KEY_F2,
|
||||
EV_KEY, KEY_F3,
|
||||
EV_KEY, KEY_F4,
|
||||
EV_KEY, KEY_F5,
|
||||
EV_KEY, KEY_F6,
|
||||
EV_KEY, KEY_F7,
|
||||
EV_KEY, KEY_F8,
|
||||
EV_KEY, KEY_F9,
|
||||
EV_KEY, KEY_F10,
|
||||
EV_KEY, KEY_NUMLOCK,
|
||||
EV_KEY, KEY_SCROLLLOCK,
|
||||
EV_KEY, KEY_KP7,
|
||||
EV_KEY, KEY_KP8,
|
||||
EV_KEY, KEY_KP9,
|
||||
EV_KEY, KEY_KPMINUS,
|
||||
EV_KEY, KEY_KP4,
|
||||
EV_KEY, KEY_KP5,
|
||||
EV_KEY, KEY_KP6,
|
||||
EV_KEY, KEY_KPPLUS,
|
||||
EV_KEY, KEY_KP1,
|
||||
EV_KEY, KEY_KP2,
|
||||
EV_KEY, KEY_KP3,
|
||||
EV_KEY, KEY_KP0,
|
||||
EV_KEY, KEY_KPDOT,
|
||||
EV_KEY, KEY_102ND,
|
||||
EV_KEY, KEY_F11,
|
||||
EV_KEY, KEY_F12,
|
||||
EV_KEY, KEY_RO,
|
||||
EV_KEY, KEY_HENKAN,
|
||||
EV_KEY, KEY_KATAKANAHIRAGANA,
|
||||
EV_KEY, KEY_MUHENKAN,
|
||||
EV_KEY, KEY_KPJPCOMMA,
|
||||
EV_KEY, KEY_KPENTER,
|
||||
EV_KEY, KEY_RIGHTCTRL,
|
||||
EV_KEY, KEY_KPSLASH,
|
||||
EV_KEY, KEY_SYSRQ,
|
||||
EV_KEY, KEY_RIGHTALT,
|
||||
EV_KEY, KEY_HOME,
|
||||
EV_KEY, KEY_UP,
|
||||
EV_KEY, KEY_PAGEUP,
|
||||
EV_KEY, KEY_LEFT,
|
||||
EV_KEY, KEY_RIGHT,
|
||||
EV_KEY, KEY_END,
|
||||
EV_KEY, KEY_DOWN,
|
||||
EV_KEY, KEY_PAGEDOWN,
|
||||
EV_KEY, KEY_INSERT,
|
||||
EV_KEY, KEY_DELETE,
|
||||
EV_KEY, KEY_MUTE,
|
||||
EV_KEY, KEY_VOLUMEDOWN,
|
||||
EV_KEY, KEY_VOLUMEUP,
|
||||
EV_KEY, KEY_POWER,
|
||||
EV_KEY, KEY_KPEQUAL,
|
||||
EV_KEY, KEY_PAUSE,
|
||||
EV_KEY, KEY_KPCOMMA,
|
||||
EV_KEY, KEY_HANGEUL,
|
||||
EV_KEY, KEY_HANJA,
|
||||
EV_KEY, KEY_YEN,
|
||||
EV_KEY, KEY_LEFTMETA,
|
||||
EV_KEY, KEY_RIGHTMETA,
|
||||
EV_KEY, KEY_COMPOSE,
|
||||
EV_KEY, KEY_STOP,
|
||||
EV_KEY, KEY_AGAIN,
|
||||
EV_KEY, KEY_PROPS,
|
||||
EV_KEY, KEY_UNDO,
|
||||
EV_KEY, KEY_FRONT,
|
||||
EV_KEY, KEY_COPY,
|
||||
EV_KEY, KEY_OPEN,
|
||||
EV_KEY, KEY_PASTE,
|
||||
EV_KEY, KEY_FIND,
|
||||
EV_KEY, KEY_CUT,
|
||||
EV_KEY, KEY_HELP,
|
||||
EV_KEY, KEY_MENU,
|
||||
EV_KEY, KEY_CALC,
|
||||
EV_KEY, KEY_SLEEP,
|
||||
EV_KEY, KEY_FILE,
|
||||
EV_KEY, KEY_WWW,
|
||||
EV_KEY, KEY_COFFEE,
|
||||
EV_KEY, KEY_MAIL,
|
||||
EV_KEY, KEY_BOOKMARKS,
|
||||
EV_KEY, KEY_BACK,
|
||||
EV_KEY, KEY_FORWARD,
|
||||
EV_KEY, KEY_EJECTCD,
|
||||
EV_KEY, KEY_NEXTSONG,
|
||||
EV_KEY, KEY_PLAYPAUSE,
|
||||
EV_KEY, KEY_PREVIOUSSONG,
|
||||
EV_KEY, KEY_STOPCD,
|
||||
EV_KEY, KEY_RECORD,
|
||||
EV_KEY, KEY_REWIND,
|
||||
EV_KEY, KEY_PHONE,
|
||||
EV_KEY, KEY_CONFIG,
|
||||
EV_KEY, KEY_HOMEPAGE,
|
||||
EV_KEY, KEY_REFRESH,
|
||||
EV_KEY, KEY_EXIT,
|
||||
EV_KEY, KEY_EDIT,
|
||||
EV_KEY, KEY_SCROLLUP,
|
||||
EV_KEY, KEY_SCROLLDOWN,
|
||||
EV_KEY, KEY_NEW,
|
||||
EV_KEY, KEY_REDO,
|
||||
EV_KEY, KEY_F13,
|
||||
EV_KEY, KEY_F14,
|
||||
EV_KEY, KEY_F15,
|
||||
EV_KEY, KEY_F16,
|
||||
EV_KEY, KEY_F17,
|
||||
EV_KEY, KEY_F18,
|
||||
EV_KEY, KEY_F19,
|
||||
EV_KEY, KEY_F20,
|
||||
EV_KEY, KEY_F21,
|
||||
EV_KEY, KEY_F22,
|
||||
EV_KEY, KEY_F23,
|
||||
EV_KEY, KEY_F24,
|
||||
EV_KEY, KEY_CLOSE,
|
||||
EV_KEY, KEY_PLAY,
|
||||
EV_KEY, KEY_FASTFORWARD,
|
||||
EV_KEY, KEY_BASSBOOST,
|
||||
EV_KEY, KEY_PRINT,
|
||||
EV_KEY, KEY_CAMERA,
|
||||
EV_KEY, KEY_CHAT,
|
||||
EV_KEY, KEY_SEARCH,
|
||||
EV_KEY, KEY_FINANCE,
|
||||
EV_KEY, KEY_CANCEL,
|
||||
EV_KEY, KEY_BRIGHTNESSDOWN,
|
||||
EV_KEY, KEY_BRIGHTNESSUP,
|
||||
EV_KEY, KEY_KBDILLUMTOGGLE,
|
||||
EV_KEY, KEY_SEND,
|
||||
EV_KEY, KEY_REPLY,
|
||||
EV_KEY, KEY_FORWARDMAIL,
|
||||
EV_KEY, KEY_SAVE,
|
||||
EV_KEY, KEY_DOCUMENTS,
|
||||
EV_KEY, KEY_UNKNOWN,
|
||||
EV_KEY, KEY_VIDEO_NEXT,
|
||||
EV_KEY, KEY_BRIGHTNESS_ZERO,
|
||||
EV_KEY, BTN_0,
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
EV_KEY, BTN_MIDDLE,
|
||||
EV_KEY, BTN_SIDE,
|
||||
EV_KEY, BTN_EXTRA,
|
||||
EV_KEY, KEY_SELECT,
|
||||
EV_KEY, KEY_GOTO,
|
||||
EV_KEY, KEY_INFO,
|
||||
EV_KEY, KEY_PROGRAM,
|
||||
EV_KEY, KEY_PVR,
|
||||
EV_KEY, KEY_SUBTITLE,
|
||||
EV_KEY, KEY_ZOOM,
|
||||
EV_KEY, KEY_KEYBOARD,
|
||||
EV_KEY, KEY_PC,
|
||||
EV_KEY, KEY_TV,
|
||||
EV_KEY, KEY_TV2,
|
||||
EV_KEY, KEY_VCR,
|
||||
EV_KEY, KEY_VCR2,
|
||||
EV_KEY, KEY_SAT,
|
||||
EV_KEY, KEY_CD,
|
||||
EV_KEY, KEY_TAPE,
|
||||
EV_KEY, KEY_TUNER,
|
||||
EV_KEY, KEY_PLAYER,
|
||||
EV_KEY, KEY_DVD,
|
||||
EV_KEY, KEY_AUDIO,
|
||||
EV_KEY, KEY_VIDEO,
|
||||
EV_KEY, KEY_MEMO,
|
||||
EV_KEY, KEY_CALENDAR,
|
||||
EV_KEY, KEY_RED,
|
||||
EV_KEY, KEY_GREEN,
|
||||
EV_KEY, KEY_YELLOW,
|
||||
EV_KEY, KEY_BLUE,
|
||||
EV_KEY, KEY_CHANNELUP,
|
||||
EV_KEY, KEY_CHANNELDOWN,
|
||||
EV_KEY, KEY_LAST,
|
||||
EV_KEY, KEY_NEXT,
|
||||
EV_KEY, KEY_RESTART,
|
||||
EV_KEY, KEY_SLOW,
|
||||
EV_KEY, KEY_SHUFFLE,
|
||||
EV_KEY, KEY_PREVIOUS,
|
||||
EV_KEY, KEY_VIDEOPHONE,
|
||||
EV_KEY, KEY_GAMES,
|
||||
EV_KEY, KEY_ZOOMIN,
|
||||
EV_KEY, KEY_ZOOMOUT,
|
||||
EV_KEY, KEY_ZOOMRESET,
|
||||
EV_KEY, KEY_WORDPROCESSOR,
|
||||
EV_KEY, KEY_EDITOR,
|
||||
EV_KEY, KEY_SPREADSHEET,
|
||||
EV_KEY, KEY_GRAPHICSEDITOR,
|
||||
EV_KEY, KEY_PRESENTATION,
|
||||
EV_KEY, KEY_DATABASE,
|
||||
EV_KEY, KEY_NEWS,
|
||||
EV_KEY, KEY_VOICEMAIL,
|
||||
EV_KEY, KEY_ADDRESSBOOK,
|
||||
EV_KEY, KEY_MESSENGER,
|
||||
EV_KEY, KEY_DISPLAYTOGGLE,
|
||||
EV_KEY, KEY_SPELLCHECK,
|
||||
EV_KEY, KEY_LOGOFF,
|
||||
EV_KEY, KEY_MEDIA_REPEAT,
|
||||
EV_KEY, KEY_IMAGES,
|
||||
EV_KEY, 576,
|
||||
EV_KEY, 577,
|
||||
EV_KEY, 578,
|
||||
EV_KEY, 579,
|
||||
EV_KEY, 580,
|
||||
EV_KEY, 581,
|
||||
EV_KEY, 582,
|
||||
EV_KEY, 592,
|
||||
EV_KEY, 593,
|
||||
EV_KEY, 608,
|
||||
EV_KEY, 609,
|
||||
EV_KEY, 610,
|
||||
EV_KEY, 611,
|
||||
EV_KEY, 612,
|
||||
EV_KEY, 613,
|
||||
EV_LED, LED_NUML,
|
||||
EV_LED, LED_CAPSL,
|
||||
EV_LED, LED_SCROLLL,
|
||||
EV_REP, REP_DELAY,
|
||||
-1, -1,
|
||||
};
|
||||
|
||||
struct litest_test_device litest_ms_surface_cover_device = {
|
||||
.type = LITEST_MS_SURFACE_COVER,
|
||||
.features = LITEST_KEYBOARD | LITEST_RELATIVE | LITEST_FAKE_MT,
|
||||
.shortname = "MS surface cover",
|
||||
.setup = litest_ms_surface_cover_setup,
|
||||
.interface = &interface,
|
||||
|
||||
.name = "MICROSOFT SAM",
|
||||
.id = &input_id,
|
||||
.events = events,
|
||||
.absinfo = absinfo,
|
||||
};
|
||||
101
test/litest-qemu-usb-tablet.c
Normal file
101
test/litest-qemu-usb-tablet.c
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
#include <assert.h>
|
||||
|
||||
static void
|
||||
litest_qemu_tablet_touch_setup(void)
|
||||
{
|
||||
struct litest_device *d = litest_create_device(LITEST_QEMU_TABLET);
|
||||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static void touch_down(struct litest_device *d, unsigned int slot,
|
||||
double x, double y)
|
||||
{
|
||||
assert(slot == 0);
|
||||
|
||||
litest_event(d, EV_ABS, ABS_X, litest_scale(d, ABS_X, x));
|
||||
litest_event(d, EV_ABS, ABS_Y, litest_scale(d, ABS_Y, y));
|
||||
litest_event(d, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
static void touch_move(struct litest_device *d, unsigned int slot,
|
||||
double x, double y)
|
||||
{
|
||||
assert(slot == 0);
|
||||
|
||||
litest_event(d, EV_ABS, ABS_X, litest_scale(d, ABS_X, x));
|
||||
litest_event(d, EV_ABS, ABS_Y, litest_scale(d, ABS_Y, y));
|
||||
litest_event(d, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
static void touch_up(struct litest_device *d, unsigned int slot)
|
||||
{
|
||||
assert(slot == 0);
|
||||
litest_event(d, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
static struct litest_device_interface interface = {
|
||||
.touch_down = touch_down,
|
||||
.touch_move = touch_move,
|
||||
.touch_up = touch_up,
|
||||
};
|
||||
|
||||
static struct input_absinfo absinfo[] = {
|
||||
{ ABS_X, 0, 32767, 0, 0, 0 },
|
||||
{ ABS_Y, 0, 32767, 0, 0, 0 },
|
||||
{ .value = -1 },
|
||||
};
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x03,
|
||||
.vendor = 0x627,
|
||||
.product = 0x01,
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
EV_KEY, BTN_MIDDLE,
|
||||
EV_REL, REL_WHEEL,
|
||||
-1, -1,
|
||||
};
|
||||
|
||||
struct litest_test_device litest_qemu_tablet_device = {
|
||||
.type = LITEST_QEMU_TABLET,
|
||||
.features = LITEST_WHEEL | LITEST_BUTTON | LITEST_ABSOLUTE,
|
||||
.shortname = "qemu tablet",
|
||||
.setup = litest_qemu_tablet_touch_setup,
|
||||
.interface = &interface,
|
||||
|
||||
.name = "QEMU 0.12.1 QEMU USB Tablet",
|
||||
.id = &input_id,
|
||||
.events = events,
|
||||
.absinfo = absinfo,
|
||||
};
|
||||
|
|
@ -56,7 +56,7 @@ static int events[] = {
|
|||
|
||||
struct litest_test_device litest_trackpoint_device = {
|
||||
.type = LITEST_TRACKPOINT,
|
||||
.features = LITEST_POINTER | LITEST_BUTTON | LITEST_POINTINGSTICK,
|
||||
.features = LITEST_RELATIVE | LITEST_BUTTON | LITEST_POINTINGSTICK,
|
||||
.shortname = "trackpoint",
|
||||
.setup = litest_trackpoint_setup,
|
||||
.interface = &interface,
|
||||
|
|
|
|||
115
test/litest-vmware-virtual-usb-mouse.c
Normal file
115
test/litest-vmware-virtual-usb-mouse.c
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
#include <assert.h>
|
||||
|
||||
static void
|
||||
litest_vmware_virtmouse_touch_setup(void)
|
||||
{
|
||||
struct litest_device *d = litest_create_device(LITEST_VMWARE_VIRTMOUSE);
|
||||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static void touch_down(struct litest_device *d, unsigned int slot,
|
||||
double x, double y)
|
||||
{
|
||||
assert(slot == 0);
|
||||
|
||||
litest_event(d, EV_ABS, ABS_X, litest_scale(d, ABS_X, x));
|
||||
litest_event(d, EV_ABS, ABS_Y, litest_scale(d, ABS_Y, y));
|
||||
litest_event(d, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
static void touch_move(struct litest_device *d, unsigned int slot,
|
||||
double x, double y)
|
||||
{
|
||||
assert(slot == 0);
|
||||
|
||||
litest_event(d, EV_ABS, ABS_X, litest_scale(d, ABS_X, x));
|
||||
litest_event(d, EV_ABS, ABS_Y, litest_scale(d, ABS_Y, y));
|
||||
litest_event(d, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
static void touch_up(struct litest_device *d, unsigned int slot)
|
||||
{
|
||||
assert(slot == 0);
|
||||
litest_event(d, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
static struct litest_device_interface interface = {
|
||||
.touch_down = touch_down,
|
||||
.touch_move = touch_move,
|
||||
.touch_up = touch_up,
|
||||
};
|
||||
|
||||
static struct input_absinfo absinfo[] = {
|
||||
{ ABS_X, 0, 32767, 0, 0, 0 },
|
||||
{ ABS_Y, 0, 32767, 0, 0, 0 },
|
||||
{ .value = -1 },
|
||||
};
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x03,
|
||||
.vendor = 0xe0f,
|
||||
.product = 0x03,
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
EV_KEY, BTN_MIDDLE,
|
||||
EV_KEY, BTN_SIDE,
|
||||
EV_KEY, BTN_EXTRA,
|
||||
EV_KEY, BTN_FORWARD,
|
||||
EV_KEY, BTN_BACK,
|
||||
EV_KEY, BTN_TASK,
|
||||
EV_KEY, 280,
|
||||
EV_KEY, 281,
|
||||
EV_KEY, 282,
|
||||
EV_KEY, 283,
|
||||
EV_KEY, 284,
|
||||
EV_KEY, 285,
|
||||
EV_KEY, 286,
|
||||
EV_KEY, 287,
|
||||
EV_REL, REL_WHEEL,
|
||||
EV_REL, REL_HWHEEL,
|
||||
-1, -1,
|
||||
};
|
||||
|
||||
struct litest_test_device litest_vmware_virtmouse_device = {
|
||||
.type = LITEST_VMWARE_VIRTMOUSE,
|
||||
.features = LITEST_WHEEL | LITEST_BUTTON | LITEST_ABSOLUTE,
|
||||
.shortname = "vmware virtmouse",
|
||||
.setup = litest_vmware_virtmouse_touch_setup,
|
||||
.interface = &interface,
|
||||
|
||||
.name = "VMware VMware Virtual USB Mouse",
|
||||
.id = &input_id,
|
||||
.events = events,
|
||||
.absinfo = absinfo,
|
||||
};
|
||||
106
test/litest-xen-virtual-pointer.c
Normal file
106
test/litest-xen-virtual-pointer.c
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "litest.h"
|
||||
#include "litest-int.h"
|
||||
#include <assert.h>
|
||||
|
||||
static void
|
||||
litest_xen_virtual_pointer_touch_setup(void)
|
||||
{
|
||||
struct litest_device *d = litest_create_device(LITEST_XEN_VIRTUAL_POINTER);
|
||||
litest_set_current_device(d);
|
||||
}
|
||||
|
||||
static void touch_down(struct litest_device *d, unsigned int slot,
|
||||
double x, double y)
|
||||
{
|
||||
assert(slot == 0);
|
||||
|
||||
litest_event(d, EV_ABS, ABS_X, litest_scale(d, ABS_X, x));
|
||||
litest_event(d, EV_ABS, ABS_Y, litest_scale(d, ABS_Y, y));
|
||||
litest_event(d, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
static void touch_move(struct litest_device *d, unsigned int slot,
|
||||
double x, double y)
|
||||
{
|
||||
assert(slot == 0);
|
||||
|
||||
litest_event(d, EV_ABS, ABS_X, litest_scale(d, ABS_X, x));
|
||||
litest_event(d, EV_ABS, ABS_Y, litest_scale(d, ABS_Y, y));
|
||||
litest_event(d, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
static void touch_up(struct litest_device *d, unsigned int slot)
|
||||
{
|
||||
assert(slot == 0);
|
||||
litest_event(d, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
static struct litest_device_interface interface = {
|
||||
.touch_down = touch_down,
|
||||
.touch_move = touch_move,
|
||||
.touch_up = touch_up,
|
||||
};
|
||||
|
||||
static struct input_absinfo absinfo[] = {
|
||||
{ ABS_X, 0, 800, 0, 0, 0 },
|
||||
{ ABS_Y, 0, 800, 0, 0, 0 },
|
||||
{ .value = -1 },
|
||||
};
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x01,
|
||||
.vendor = 0x5853,
|
||||
.product = 0xfffe,
|
||||
};
|
||||
|
||||
static int events[] = {
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
EV_KEY, BTN_MIDDLE,
|
||||
EV_KEY, BTN_SIDE,
|
||||
EV_KEY, BTN_EXTRA,
|
||||
EV_KEY, BTN_FORWARD,
|
||||
EV_KEY, BTN_BACK,
|
||||
EV_KEY, BTN_TASK,
|
||||
EV_REL, REL_WHEEL,
|
||||
-1, -1,
|
||||
};
|
||||
|
||||
struct litest_test_device litest_xen_virtual_pointer_device = {
|
||||
.type = LITEST_XEN_VIRTUAL_POINTER,
|
||||
.features = LITEST_WHEEL | LITEST_BUTTON | LITEST_ABSOLUTE,
|
||||
.shortname = "xen pointer",
|
||||
.setup = litest_xen_virtual_pointer_touch_setup,
|
||||
.interface = &interface,
|
||||
|
||||
.name = "Xen Virtual Pointer",
|
||||
.id = &input_id,
|
||||
.events = events,
|
||||
.absinfo = absinfo,
|
||||
};
|
||||
|
|
@ -91,6 +91,9 @@ extern struct litest_test_device litest_wacom_intuos_tablet_device;
|
|||
extern struct litest_test_device litest_wacom_isdv4_tablet_device;
|
||||
extern struct litest_test_device litest_alps_device;
|
||||
extern struct litest_test_device litest_generic_singletouch_device;
|
||||
extern struct litest_test_device litest_qemu_tablet_device;
|
||||
extern struct litest_test_device litest_xen_virtual_pointer_device;
|
||||
extern struct litest_test_device litest_vmware_virtmouse_device;
|
||||
|
||||
struct litest_test_device* devices[] = {
|
||||
&litest_synaptics_clickpad_device,
|
||||
|
|
@ -107,6 +110,9 @@ struct litest_test_device* devices[] = {
|
|||
&litest_wacom_isdv4_tablet_device,
|
||||
&litest_alps_device,
|
||||
&litest_generic_singletouch_device,
|
||||
&litest_qemu_tablet_device,
|
||||
&litest_xen_virtual_pointer_device,
|
||||
&litest_vmware_virtmouse_device,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
@ -642,7 +648,12 @@ void
|
|||
litest_event(struct litest_device *d, unsigned int type,
|
||||
unsigned int code, int value)
|
||||
{
|
||||
int ret = libevdev_uinput_write_event(d->uinput, type, code, value);
|
||||
int ret;
|
||||
|
||||
if (d->skip_ev_syn && type == EV_SYN && code == SYN_REPORT)
|
||||
return;
|
||||
|
||||
ret = libevdev_uinput_write_event(d->uinput, type, code, value);
|
||||
ck_assert_int_eq(ret, 0);
|
||||
}
|
||||
|
||||
|
|
@ -765,12 +776,18 @@ litest_touch_move_to(struct litest_device *d,
|
|||
unsigned int slot,
|
||||
double x_from, double y_from,
|
||||
double x_to, double y_to,
|
||||
int steps)
|
||||
int steps, int sleep_ms)
|
||||
{
|
||||
for (int i = 0; i < steps - 1; i++)
|
||||
for (int i = 0; i < steps - 1; i++) {
|
||||
litest_touch_move(d, slot,
|
||||
x_from + (x_to - x_from)/steps * i,
|
||||
y_from + (y_to - y_from)/steps * i);
|
||||
if (sleep_ms) {
|
||||
libinput_dispatch(d->libinput);
|
||||
msleep(sleep_ms);
|
||||
libinput_dispatch(d->libinput);
|
||||
}
|
||||
}
|
||||
litest_touch_move(d, slot, x_to, y_to);
|
||||
}
|
||||
|
||||
|
|
@ -877,6 +894,28 @@ litest_button_click(struct litest_device *d, unsigned int button, bool is_press)
|
|||
litest_event(d, ev->type, ev->code, ev->value);
|
||||
}
|
||||
|
||||
void
|
||||
litest_button_scroll(struct litest_device *dev,
|
||||
unsigned int button,
|
||||
double dx, double dy)
|
||||
{
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_button_click(dev, button, 1);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_buttonscroll();
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_event(dev, EV_REL, REL_X, dx);
|
||||
litest_event(dev, EV_REL, REL_Y, dy);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
litest_button_click(dev, button, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
void
|
||||
litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press)
|
||||
{
|
||||
|
|
@ -1182,7 +1221,10 @@ litest_assert_button_event(struct libinput *li, unsigned int button,
|
|||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
void litest_assert_scroll(struct libinput *li, unsigned int axis, int dir)
|
||||
void
|
||||
litest_assert_scroll(struct libinput *li,
|
||||
enum libinput_pointer_axis axis,
|
||||
int minimum_movement)
|
||||
{
|
||||
struct libinput_event *event, *next_event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
|
|
@ -1200,14 +1242,14 @@ void litest_assert_scroll(struct libinput *li, unsigned int axis, int dir)
|
|||
|
||||
if (next_event) {
|
||||
/* Normal scroll event, check dir */
|
||||
if (dir > 0) {
|
||||
if (minimum_movement > 0) {
|
||||
ck_assert_int_ge(
|
||||
libinput_event_pointer_get_axis_value(ptrev),
|
||||
dir);
|
||||
minimum_movement);
|
||||
} else {
|
||||
ck_assert_int_le(
|
||||
libinput_event_pointer_get_axis_value(ptrev),
|
||||
dir);
|
||||
minimum_movement);
|
||||
}
|
||||
} else {
|
||||
/* Last scroll event, must be 0 */
|
||||
|
|
@ -1220,3 +1262,36 @@ void litest_assert_scroll(struct libinput *li, unsigned int axis, int dir)
|
|||
next_event = libinput_get_event(li);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
litest_timeout_tap(void)
|
||||
{
|
||||
msleep(200);
|
||||
}
|
||||
|
||||
void
|
||||
litest_timeout_softbuttons(void)
|
||||
{
|
||||
msleep(300);
|
||||
}
|
||||
|
||||
void
|
||||
litest_timeout_buttonscroll(void)
|
||||
{
|
||||
msleep(300);
|
||||
}
|
||||
|
||||
void
|
||||
litest_push_event_frame(struct litest_device *dev)
|
||||
{
|
||||
assert(!dev->skip_ev_syn);
|
||||
dev->skip_ev_syn = true;
|
||||
}
|
||||
|
||||
void
|
||||
litest_pop_event_frame(struct litest_device *dev)
|
||||
{
|
||||
assert(dev->skip_ev_syn);
|
||||
dev->skip_ev_syn = false;
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,10 +45,14 @@ enum litest_device_type {
|
|||
LITEST_WACOM_TOUCH = -9,
|
||||
LITEST_ALPS_SEMI_MT = -10,
|
||||
LITEST_GENERIC_SINGLETOUCH = -11,
|
||||
LITEST_WACOM_BAMBOO = -12,
|
||||
LITEST_WACOM_CINTIQ = -13,
|
||||
LITEST_WACOM_INTUOS = -14,
|
||||
LITEST_WACOM_ISDV4 = -15,
|
||||
LITEST_MS_SURFACE_COVER = -12,
|
||||
LITEST_QEMU_TABLET = -13,
|
||||
LITEST_XEN_VIRTUAL_POINTER = -14,
|
||||
LITEST_VMWARE_VIRTMOUSE = -15,
|
||||
LITEST_WACOM_BAMBOO = -16,
|
||||
LITEST_WACOM_CINTIQ = -17,
|
||||
LITEST_WACOM_INTUOS = -18,
|
||||
LITEST_WACOM_ISDV4 = -19,
|
||||
};
|
||||
|
||||
enum litest_device_feature {
|
||||
|
|
@ -58,7 +62,7 @@ enum litest_device_feature {
|
|||
LITEST_CLICKPAD = 1 << 1,
|
||||
LITEST_BUTTON = 1 << 2,
|
||||
LITEST_KEYS = 1 << 3,
|
||||
LITEST_POINTER = 1 << 4,
|
||||
LITEST_RELATIVE = 1 << 4,
|
||||
LITEST_WHEEL = 1 << 5,
|
||||
LITEST_TOUCH = 1 << 6,
|
||||
LITEST_SINGLE_TOUCH = 1 << 7,
|
||||
|
|
@ -66,9 +70,11 @@ enum litest_device_feature {
|
|||
LITEST_TOPBUTTONPAD = 1 << 9,
|
||||
LITEST_SEMI_MT = 1 << 10,
|
||||
LITEST_POINTINGSTICK = 1 << 11,
|
||||
LITEST_TABLET = 1 << 12,
|
||||
LITEST_DISTANCE = 1 << 13,
|
||||
LITEST_TOOL_SERIAL = 1 << 14,
|
||||
LITEST_FAKE_MT = 1 << 12,
|
||||
LITEST_ABSOLUTE = 1 << 13,
|
||||
LITEST_TABLET = 1 << 14,
|
||||
LITEST_DISTANCE = 1 << 15,
|
||||
LITEST_TOOL_SERIAL = 1 << 16,
|
||||
};
|
||||
|
||||
struct litest_device {
|
||||
|
|
@ -80,6 +86,8 @@ struct litest_device {
|
|||
struct litest_device_interface *interface;
|
||||
|
||||
int ntouches_down;
|
||||
bool skip_ev_syn;
|
||||
|
||||
void *private; /* device-specific data */
|
||||
};
|
||||
|
||||
|
|
@ -145,7 +153,7 @@ void litest_touch_move_to(struct litest_device *d,
|
|||
unsigned int slot,
|
||||
double x_from, double y_from,
|
||||
double x_to, double y_to,
|
||||
int steps);
|
||||
int steps, int sleep_ms);
|
||||
void litest_tablet_proximity_in(struct litest_device *d,
|
||||
int x, int y,
|
||||
struct axis_replacement *axes);
|
||||
|
|
@ -156,6 +164,9 @@ void litest_tablet_motion(struct litest_device *d,
|
|||
void litest_button_click(struct litest_device *d,
|
||||
unsigned int button,
|
||||
bool is_press);
|
||||
void litest_button_scroll(struct litest_device *d,
|
||||
unsigned int button,
|
||||
double dx, double dy);
|
||||
void litest_keyboard_key(struct litest_device *d,
|
||||
unsigned int key,
|
||||
bool is_press);
|
||||
|
|
@ -166,7 +177,9 @@ void litest_assert_empty_queue(struct libinput *li);
|
|||
void litest_assert_button_event(struct libinput *li,
|
||||
unsigned int button,
|
||||
enum libinput_button_state state);
|
||||
void litest_assert_scroll(struct libinput *li, unsigned int axis, int dir);
|
||||
void litest_assert_scroll(struct libinput *li,
|
||||
enum libinput_pointer_axis axis,
|
||||
int minimum_movement);
|
||||
|
||||
struct libevdev_uinput * litest_create_uinput_device(const char *name,
|
||||
struct input_id *id,
|
||||
|
|
@ -193,6 +206,13 @@ struct libevdev_uinput * litest_create_uinput_abs_device(const char *name,
|
|||
#define litest_assert_double_ge(a_, b_)\
|
||||
ck_assert_int_ge((int)(a_ * 256), (int)(b_ * 256))
|
||||
|
||||
void litest_timeout_tap(void);
|
||||
void litest_timeout_softbuttons(void);
|
||||
void litest_timeout_buttonscroll(void);
|
||||
|
||||
void litest_push_event_frame(struct litest_device *dev);
|
||||
void litest_pop_event_frame(struct litest_device *dev);
|
||||
|
||||
#ifndef ck_assert_notnull
|
||||
#define ck_assert_notnull(ptr) ck_assert_ptr_ne(ptr, NULL)
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -125,11 +125,13 @@ START_TEST(log_priority)
|
|||
|
||||
libinput_path_add_device(li, "/tmp");
|
||||
|
||||
ck_assert_int_eq(log_handler_called, 0);
|
||||
ck_assert_int_eq(log_handler_called, 1);
|
||||
|
||||
libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_INFO);
|
||||
libinput_path_add_device(li, "/tmp");
|
||||
ck_assert_int_gt(log_handler_called, 0);
|
||||
/* event0 is usually Lid Switch which prints an info that
|
||||
we don't handle it */
|
||||
libinput_path_add_device(li, "/dev/input/event0");
|
||||
ck_assert_int_gt(log_handler_called, 1);
|
||||
|
||||
log_handler_called = 0;
|
||||
|
||||
|
|
|
|||
104
test/misc.c
104
test/misc.c
|
|
@ -429,25 +429,6 @@ START_TEST(context_ref_counting)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_ids)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
const char *name;
|
||||
unsigned int pid, vid;
|
||||
|
||||
name = libevdev_get_name(dev->evdev);
|
||||
pid = libevdev_get_id_product(dev->evdev);
|
||||
vid = libevdev_get_id_vendor(dev->evdev);
|
||||
|
||||
ck_assert_str_eq(name,
|
||||
libinput_device_get_name(dev->libinput_device));
|
||||
ck_assert_int_eq(pid,
|
||||
libinput_device_get_id_product(dev->libinput_device));
|
||||
ck_assert_int_eq(vid,
|
||||
libinput_device_get_id_vendor(dev->libinput_device));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(config_status_string)
|
||||
{
|
||||
const char *strs[3];
|
||||
|
|
@ -546,6 +527,87 @@ START_TEST(matrix_helpers)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(ratelimit_helpers)
|
||||
{
|
||||
struct ratelimit rl;
|
||||
unsigned int i, j;
|
||||
|
||||
/* 10 attempts every 100ms */
|
||||
ratelimit_init(&rl, 100, 10);
|
||||
|
||||
for (j = 0; j < 3; ++j) {
|
||||
/* a burst of 9 attempts must succeed */
|
||||
for (i = 0; i < 9; ++i) {
|
||||
ck_assert_int_eq(ratelimit_test(&rl),
|
||||
RATELIMIT_PASS);
|
||||
}
|
||||
|
||||
/* the 10th attempt reaches the threshold */
|
||||
ck_assert_int_eq(ratelimit_test(&rl), RATELIMIT_THRESHOLD);
|
||||
|
||||
/* ..then further attempts must fail.. */
|
||||
ck_assert_int_eq(ratelimit_test(&rl), RATELIMIT_EXCEEDED);
|
||||
|
||||
/* ..regardless of how often we try. */
|
||||
for (i = 0; i < 100; ++i) {
|
||||
ck_assert_int_eq(ratelimit_test(&rl),
|
||||
RATELIMIT_EXCEEDED);
|
||||
}
|
||||
|
||||
/* ..even after waiting 20ms */
|
||||
msleep(20);
|
||||
for (i = 0; i < 100; ++i) {
|
||||
ck_assert_int_eq(ratelimit_test(&rl),
|
||||
RATELIMIT_EXCEEDED);
|
||||
}
|
||||
|
||||
/* but after 100ms the counter is reset */
|
||||
msleep(90); /* +10ms to account for time drifts */
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
struct parser_test {
|
||||
char *tag;
|
||||
int expected_dpi;
|
||||
};
|
||||
|
||||
START_TEST(dpi_parser)
|
||||
{
|
||||
struct parser_test tests[] = {
|
||||
{ "450 *1800 3200", 1800 },
|
||||
{ "*450 1800 3200", 450 },
|
||||
{ "450 1800 *3200", 3200 },
|
||||
{ "450 1800 3200", 3200 },
|
||||
{ "450 1800 failboat", 0 },
|
||||
{ "450 1800 *failboat", 0 },
|
||||
{ "0 450 1800 *3200", 0 },
|
||||
{ "450@37 1800@12 *3200@6", 3200 },
|
||||
{ "450@125 1800@125 *3200@125 ", 3200 },
|
||||
{ "450@125 *1800@125 3200@125", 1800 },
|
||||
{ "*this @string fails", 0 },
|
||||
{ "12@34 *45@", 0 },
|
||||
{ "12@a *45@", 0 },
|
||||
{ "12@a *45@25", 0 },
|
||||
{ " * 12, 450, 800", 0 },
|
||||
{ " *12, 450, 800", 12 },
|
||||
{ "*12, *450, 800", 12 },
|
||||
{ "*-23412, 450, 800", 0 },
|
||||
{ "112@125, 450@125, 800@125, 900@-125", 0 },
|
||||
{ "", 0 },
|
||||
{ " ", 0 },
|
||||
{ "* ", 0 },
|
||||
{ NULL }
|
||||
};
|
||||
int i, dpi;
|
||||
|
||||
for (i = 0; tests[i].tag != NULL; i++) {
|
||||
dpi = parse_mouse_dpi_property(tests[i].tag);
|
||||
ck_assert_int_eq(dpi, tests[i].expected_dpi);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
litest_add_no_device("events:conversion", event_conversion_device_notify);
|
||||
litest_add_no_device("events:conversion", event_conversion_pointer);
|
||||
|
|
@ -554,9 +616,11 @@ int main (int argc, char **argv) {
|
|||
litest_add_no_device("events:conversion", event_conversion_touch);
|
||||
litest_add_no_device("bitfield_helpers", bitfield_helpers);
|
||||
litest_add_no_device("context:refcount", context_ref_counting);
|
||||
litest_add("device:id", device_ids, LITEST_ANY, LITEST_ANY);
|
||||
litest_add_no_device("config:status string", config_status_string);
|
||||
|
||||
litest_add_no_device("misc:matrix", matrix_helpers);
|
||||
litest_add_no_device("misc:ratelimit", ratelimit_helpers);
|
||||
litest_add_no_device("misc:dpi parser", dpi_parser);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
71
test/path.c
71
test/path.c
|
|
@ -162,6 +162,74 @@ START_TEST(path_added_seat)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(path_seat_change)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_device *device;
|
||||
struct libinput_seat *seat1, *seat2;
|
||||
const char *seat1_name;
|
||||
const char *seat2_name = "new seat";
|
||||
int rc;
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_DEVICE_ADDED);
|
||||
|
||||
device = libinput_event_get_device(event);
|
||||
libinput_device_ref(device);
|
||||
|
||||
seat1 = libinput_device_get_seat(device);
|
||||
libinput_seat_ref(seat1);
|
||||
|
||||
seat1_name = libinput_seat_get_logical_name(seat1);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
rc = libinput_device_set_seat_logical_name(device,
|
||||
seat2_name);
|
||||
ck_assert_int_eq(rc, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert(event != NULL);
|
||||
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_DEVICE_REMOVED);
|
||||
|
||||
ck_assert(libinput_event_get_device(event) == device);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert(event != NULL);
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_DEVICE_ADDED);
|
||||
ck_assert(libinput_event_get_device(event) != device);
|
||||
libinput_device_unref(device);
|
||||
|
||||
device = libinput_event_get_device(event);
|
||||
seat2 = libinput_device_get_seat(device);
|
||||
|
||||
ck_assert_str_ne(libinput_seat_get_logical_name(seat2),
|
||||
seat1_name);
|
||||
ck_assert_str_eq(libinput_seat_get_logical_name(seat2),
|
||||
seat2_name);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
libinput_seat_unref(seat1);
|
||||
|
||||
/* litest: swap the new device in, so cleanup works */
|
||||
libinput_device_unref(dev->libinput_device);
|
||||
libinput_device_ref(device);
|
||||
dev->libinput_device = device;
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(path_added_device)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -805,7 +873,8 @@ main(int argc, char **argv)
|
|||
litest_add_no_device("path:suspend", path_add_device_suspend_resume);
|
||||
litest_add_no_device("path:suspend", path_add_device_suspend_resume_fail);
|
||||
litest_add_no_device("path:suspend", path_add_device_suspend_resume_remove_device);
|
||||
litest_add_for_device("path:seat events", path_added_seat, LITEST_SYNAPTICS_CLICKPAD);
|
||||
litest_add_for_device("path:seat", path_added_seat, LITEST_SYNAPTICS_CLICKPAD);
|
||||
litest_add_for_device("path:seat", path_seat_change, LITEST_SYNAPTICS_CLICKPAD);
|
||||
litest_add("path:device events", path_added_device, LITEST_ANY, LITEST_ANY);
|
||||
litest_add("path:device events", path_device_sysname, LITEST_ANY, LITEST_ANY);
|
||||
litest_add_for_device("path:device events", path_add_device, LITEST_SYNAPTICS_CLICKPAD);
|
||||
|
|
|
|||
358
test/pointer.c
358
test/pointer.c
|
|
@ -29,15 +29,43 @@
|
|||
#include <libinput.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <values.h>
|
||||
|
||||
#include "libinput-util.h"
|
||||
#include "litest.h"
|
||||
|
||||
static struct libinput_event_pointer *
|
||||
get_accelerated_motion_event(struct libinput *li)
|
||||
{
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
|
||||
while (1) {
|
||||
event = libinput_get_event(li);
|
||||
ck_assert_notnull(event);
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
ck_assert_notnull(ptrev);
|
||||
|
||||
if (fabs(libinput_event_pointer_get_dx(ptrev)) < DBL_MIN &&
|
||||
fabs(libinput_event_pointer_get_dy(ptrev)) < DBL_MIN) {
|
||||
libinput_event_destroy(event);
|
||||
continue;
|
||||
}
|
||||
|
||||
return ptrev;
|
||||
}
|
||||
|
||||
ck_abort_msg("No accelerated pointer motion event found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
test_relative_event(struct litest_device *dev, int dx, int dy)
|
||||
{
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
double ev_dx, ev_dy;
|
||||
double expected_dir;
|
||||
|
|
@ -56,12 +84,7 @@ test_relative_event(struct litest_device *dev, int dx, int dy)
|
|||
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert(event != NULL);
|
||||
ck_assert_int_eq(libinput_event_get_type(event), LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
ck_assert(ptrev != NULL);
|
||||
ptrev = get_accelerated_motion_event(li);
|
||||
|
||||
expected_length = sqrt(4 * dx*dx + 4 * dy*dy);
|
||||
expected_dir = atan2(dx, dy);
|
||||
|
|
@ -78,7 +101,7 @@ test_relative_event(struct litest_device *dev, int dx, int dy)
|
|||
* indifference). */
|
||||
ck_assert(fabs(expected_dir - actual_dir) < M_PI_2);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
libinput_event_destroy(libinput_event_pointer_get_base_event(ptrev));
|
||||
|
||||
litest_drain_events(dev->libinput);
|
||||
}
|
||||
|
|
@ -101,6 +124,95 @@ START_TEST(pointer_motion_relative)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
static void
|
||||
test_absolute_event(struct litest_device *dev, double x, double y)
|
||||
{
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
double ex, ey;
|
||||
|
||||
litest_touch_down(dev, 0, x, y);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE);
|
||||
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
ck_assert(ptrev != NULL);
|
||||
|
||||
ex = libinput_event_pointer_get_absolute_x_transformed(ptrev, 100);
|
||||
ey = libinput_event_pointer_get_absolute_y_transformed(ptrev, 100);
|
||||
ck_assert_int_eq(ex + 0.5, x);
|
||||
ck_assert_int_eq(ey + 0.5, y);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
|
||||
START_TEST(pointer_motion_absolute)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
test_absolute_event(dev, 0, 100);
|
||||
test_absolute_event(dev, 100, 0);
|
||||
test_absolute_event(dev, 50, 50);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void
|
||||
test_unaccel_event(struct litest_device *dev, int dx, int dy)
|
||||
{
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
double ev_dx, ev_dy;
|
||||
|
||||
litest_event(dev, EV_REL, REL_X, dx);
|
||||
litest_event(dev, EV_REL, REL_Y, dy);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert_notnull(event);
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
ck_assert(ptrev != NULL);
|
||||
|
||||
ev_dx = libinput_event_pointer_get_dx_unaccelerated(ptrev);
|
||||
ev_dy = libinput_event_pointer_get_dy_unaccelerated(ptrev);
|
||||
|
||||
ck_assert_int_eq(dx, ev_dx);
|
||||
ck_assert_int_eq(dy, ev_dy);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
|
||||
litest_drain_events(dev->libinput);
|
||||
}
|
||||
|
||||
START_TEST(pointer_motion_unaccel)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
test_unaccel_event(dev, 10, 0);
|
||||
test_unaccel_event(dev, 10, 10);
|
||||
test_unaccel_event(dev, 10, -10);
|
||||
test_unaccel_event(dev, 0, 10);
|
||||
|
||||
test_unaccel_event(dev, -10, 0);
|
||||
test_unaccel_event(dev, -10, 10);
|
||||
test_unaccel_event(dev, -10, -10);
|
||||
test_unaccel_event(dev, 0, -10);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void
|
||||
test_button_event(struct litest_device *dev, unsigned int button, int state)
|
||||
{
|
||||
|
|
@ -242,6 +354,9 @@ test_wheel_event(struct litest_device *dev, int which, int amount)
|
|||
const int scroll_step = 10;
|
||||
int expected = amount * scroll_step;
|
||||
|
||||
if (libinput_device_config_scroll_get_natural_scroll_enabled(dev->libinput_device))
|
||||
expected *= -1;
|
||||
|
||||
/* mouse scroll wheels are 'upside down' */
|
||||
if (which == REL_WHEEL)
|
||||
amount *= -1;
|
||||
|
|
@ -287,6 +402,56 @@ START_TEST(pointer_scroll_wheel)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_scroll_natural_defaults)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
||||
ck_assert_int_ge(libinput_device_config_scroll_has_natural_scroll(dev->libinput_device), 1);
|
||||
ck_assert_int_eq(libinput_device_config_scroll_get_natural_scroll_enabled(dev->libinput_device), 0);
|
||||
ck_assert_int_eq(libinput_device_config_scroll_get_default_natural_scroll_enabled(dev->libinput_device), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_scroll_natural_enable_config)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
enum libinput_config_status status;
|
||||
|
||||
status = libinput_device_config_scroll_set_natural_scroll_enabled(dev->libinput_device, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
ck_assert_int_eq(libinput_device_config_scroll_get_natural_scroll_enabled(dev->libinput_device), 1);
|
||||
|
||||
status = libinput_device_config_scroll_set_natural_scroll_enabled(dev->libinput_device, 0);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
ck_assert_int_eq(libinput_device_config_scroll_get_natural_scroll_enabled(dev->libinput_device), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_scroll_natural_wheel)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
libinput_device_config_scroll_set_natural_scroll_enabled(device, 1);
|
||||
|
||||
test_wheel_event(dev, REL_WHEEL, -1);
|
||||
test_wheel_event(dev, REL_WHEEL, 1);
|
||||
|
||||
test_wheel_event(dev, REL_WHEEL, -5);
|
||||
test_wheel_event(dev, REL_WHEEL, 6);
|
||||
|
||||
if (libevdev_has_event_code(dev->evdev, EV_REL, REL_HWHEEL)) {
|
||||
test_wheel_event(dev, REL_HWHEEL, -1);
|
||||
test_wheel_event(dev, REL_HWHEEL, 1);
|
||||
|
||||
test_wheel_event(dev, REL_HWHEEL, -5);
|
||||
test_wheel_event(dev, REL_HWHEEL, 6);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_seat_button_count)
|
||||
{
|
||||
const int num_devices = 4;
|
||||
|
|
@ -396,15 +561,188 @@ START_TEST(pointer_no_calibration)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_left_handed_defaults)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *d = dev->libinput_device;
|
||||
int rc;
|
||||
|
||||
rc = libinput_device_config_buttons_has_left_handed(d);
|
||||
ck_assert_int_ne(rc, 0);
|
||||
|
||||
rc = libinput_device_config_buttons_get_left_handed(d);
|
||||
ck_assert_int_eq(rc, 0);
|
||||
|
||||
rc = libinput_device_config_buttons_get_default_left_handed(d);
|
||||
ck_assert_int_eq(rc, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_left_handed)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *d = dev->libinput_device;
|
||||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_button_click(dev, BTN_RIGHT, 1);
|
||||
litest_button_click(dev, BTN_RIGHT, 0);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
if (libevdev_has_event_code(dev->evdev,
|
||||
EV_KEY,
|
||||
BTN_MIDDLE)) {
|
||||
litest_button_click(dev, BTN_MIDDLE, 1);
|
||||
litest_button_click(dev, BTN_MIDDLE, 0);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_left_handed_during_click)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *d = dev->libinput_device;
|
||||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
/* Change while button is down, expect correct release event */
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_left_handed_during_click_multiple_buttons)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *d = dev->libinput_device;
|
||||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
/* No left-handed until all buttons were down */
|
||||
litest_button_click(dev, BTN_RIGHT, 1);
|
||||
litest_button_click(dev, BTN_RIGHT, 0);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_scroll_button)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
/* Make left button switch to scrolling mode */
|
||||
libinput_device_config_scroll_set_method(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN);
|
||||
libinput_device_config_scroll_set_button(dev->libinput_device,
|
||||
BTN_LEFT);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_button_scroll(dev, BTN_LEFT, 1, 6);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 6);
|
||||
litest_button_scroll(dev, BTN_LEFT, 1, -7);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -7);
|
||||
litest_button_scroll(dev, BTN_LEFT, 8, 1);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 8);
|
||||
litest_button_scroll(dev, BTN_LEFT, -9, 1);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -9);
|
||||
|
||||
/* scroll smaller than the threshold should not generate events */
|
||||
litest_button_scroll(dev, BTN_LEFT, 1, 1);
|
||||
/* left press without movement should not generate events */
|
||||
litest_button_scroll(dev, BTN_LEFT, 0, 0);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* Restore default scroll behavior */
|
||||
libinput_device_config_scroll_set_method(dev->libinput_device,
|
||||
libinput_device_config_scroll_get_default_method(
|
||||
dev->libinput_device));
|
||||
libinput_device_config_scroll_set_button(dev->libinput_device,
|
||||
libinput_device_config_scroll_get_default_button(
|
||||
dev->libinput_device));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
|
||||
litest_add("pointer:motion", pointer_motion_relative, LITEST_POINTER, LITEST_ANY);
|
||||
litest_add("pointer:motion", pointer_motion_relative, LITEST_RELATIVE, LITEST_ANY);
|
||||
litest_add("pointer:motion", pointer_motion_absolute, LITEST_ABSOLUTE, LITEST_ANY);
|
||||
litest_add("pointer:motion", pointer_motion_unaccel, LITEST_RELATIVE, LITEST_ANY);
|
||||
litest_add("pointer:button", pointer_button, LITEST_BUTTON, LITEST_CLICKPAD);
|
||||
litest_add_no_device("pointer:button_auto_release", pointer_button_auto_release);
|
||||
litest_add("pointer:scroll", pointer_scroll_wheel, LITEST_WHEEL, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_button, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_natural_defaults, LITEST_WHEEL, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_natural_enable_config, LITEST_WHEEL, LITEST_ANY);
|
||||
litest_add("pointer:scroll", pointer_scroll_natural_wheel, LITEST_WHEEL, LITEST_ANY);
|
||||
litest_add_no_device("pointer:seat button count", pointer_seat_button_count);
|
||||
|
||||
litest_add("pointer:calibration", pointer_no_calibration, LITEST_ANY, LITEST_TOUCH|LITEST_SINGLE_TOUCH);
|
||||
litest_add("pointer:calibration", pointer_no_calibration, LITEST_ANY, LITEST_TOUCH|LITEST_SINGLE_TOUCH|LITEST_ABSOLUTE);
|
||||
|
||||
/* tests touchpads too */
|
||||
litest_add("pointer:left-handed", pointer_left_handed_defaults, LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:left-handed", pointer_left_handed, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:left-handed", pointer_left_handed_during_click, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:left-handed", pointer_left_handed_during_click_multiple_buttons, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
69
test/touch.c
69
test/touch.c
|
|
@ -401,6 +401,70 @@ START_TEST(touch_calibration_translation)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touch_no_left_handed)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *d = dev->libinput_device;
|
||||
enum libinput_config_status status;
|
||||
int rc;
|
||||
|
||||
rc = libinput_device_config_buttons_has_left_handed(d);
|
||||
ck_assert_int_eq(rc, 0);
|
||||
|
||||
rc = libinput_device_config_buttons_get_left_handed(d);
|
||||
ck_assert_int_eq(rc, 0);
|
||||
|
||||
rc = libinput_device_config_buttons_get_default_left_handed(d);
|
||||
ck_assert_int_eq(rc, 0);
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 0);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(fake_mt_exists)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_device *device;
|
||||
|
||||
litest_wait_for_event_of_type(li, LIBINPUT_EVENT_DEVICE_ADDED, -1);
|
||||
event = libinput_get_event(li);
|
||||
device = libinput_event_get_device(event);
|
||||
|
||||
ck_assert(!libinput_device_has_capability(device,
|
||||
LIBINPUT_DEVICE_CAP_TOUCH));
|
||||
|
||||
/* This test may need fixing if we add other fake-mt devices that
|
||||
* have different capabilities */
|
||||
ck_assert(libinput_device_has_capability(device,
|
||||
LIBINPUT_DEVICE_CAP_POINTER));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(fake_mt_no_touch_events)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 70, 70, 5, 10);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_down(dev, 1, 70, 70);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 90, 40, 10, 10);
|
||||
litest_touch_move_to(dev, 0, 70, 70, 40, 50, 10, 10);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
|
@ -415,5 +479,10 @@ main(int argc, char **argv)
|
|||
litest_add("touch:calibration", touch_calibration_translation, LITEST_TOUCH, LITEST_TOUCHPAD);
|
||||
litest_add("touch:calibration", touch_calibration_translation, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD);
|
||||
|
||||
litest_add("touch:left-handed", touch_no_left_handed, LITEST_TOUCH, LITEST_ANY);
|
||||
|
||||
litest_add("touch:fake-mt", fake_mt_exists, LITEST_FAKE_MT, LITEST_ANY);
|
||||
litest_add("touch:fake-mt", fake_mt_no_touch_events, LITEST_FAKE_MT, LITEST_ANY);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
587
test/touchpad.c
587
test/touchpad.c
|
|
@ -41,7 +41,7 @@ START_TEST(touchpad_1fg_motion)
|
|||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 80, 50, 5);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 80, 50, 5, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
|
@ -72,8 +72,8 @@ START_TEST(touchpad_2fg_no_motion)
|
|||
|
||||
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_move_to(dev, 0, 20, 20, 80, 80, 5, 0);
|
||||
litest_touch_move_to(dev, 1, 70, 20, 80, 50, 5, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ START_TEST(touchpad_1fg_tap)
|
|||
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
msleep(300); /* tap-n-drag timeout */
|
||||
litest_timeout_tap();
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ START_TEST(touchpad_1fg_tap_n_drag)
|
|||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 80, 80, 5);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 80, 80, 5, 40);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
|
@ -150,7 +150,7 @@ START_TEST(touchpad_1fg_tap_n_drag)
|
|||
|
||||
/* lift finger, set down again, should continue dragging */
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 80, 80, 5);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 80, 80, 5, 40);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
|
@ -162,7 +162,7 @@ START_TEST(touchpad_1fg_tap_n_drag)
|
|||
|
||||
ck_assert_int_eq(libinput_next_event_type(li), LIBINPUT_EVENT_NONE);
|
||||
|
||||
msleep(300); /* tap-n-drag timeout */
|
||||
litest_timeout_tap();
|
||||
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
|
@ -185,7 +185,7 @@ START_TEST(touchpad_1fg_tap_n_drag_timeout)
|
|||
litest_touch_up(dev, 0);
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
libinput_dispatch(li);
|
||||
msleep(300);
|
||||
litest_timeout_tap();
|
||||
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
|
@ -200,6 +200,93 @@ START_TEST(touchpad_1fg_tap_n_drag_timeout)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_2fg_tap_n_drag)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
|
||||
libinput_device_config_tap_set_enabled(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_down(dev, 1, 60, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 80, 80, 5, 40);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
while (libinput_next_event_type(li) == LIBINPUT_EVENT_POINTER_MOTION) {
|
||||
event = libinput_get_event(li);
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
|
||||
/* This will wait for the DRAGGING_WAIT timeout */
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_2fg_tap_n_drag_3fg_btntool)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
|
||||
libinput_device_config_tap_set_enabled(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_down(dev, 1, 60, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 80, 80, 5, 40);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
||||
while (libinput_next_event_type(li) == LIBINPUT_EVENT_POINTER_MOTION) {
|
||||
event = libinput_get_event(li);
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* Putting down a third finger should end the drag */
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 1);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
/* Releasing the fingers should not cause any events */
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 0);
|
||||
litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_2fg_tap)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -219,7 +306,7 @@ START_TEST(touchpad_2fg_tap)
|
|||
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
msleep(300); /* tap-n-drag timeout */
|
||||
litest_timeout_tap();
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
|
|
@ -246,7 +333,7 @@ START_TEST(touchpad_2fg_tap_inverted)
|
|||
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
msleep(300); /* tap-n-drag timeout */
|
||||
litest_timeout_tap();
|
||||
litest_assert_button_event(li, BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
|
|
@ -274,7 +361,7 @@ START_TEST(touchpad_1fg_tap_click)
|
|||
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
libinput_dispatch(li);
|
||||
msleep(200);
|
||||
litest_timeout_tap();
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
|
|
@ -400,7 +487,7 @@ START_TEST(touchpad_no_2fg_tap_after_move)
|
|||
-> no event
|
||||
*/
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 90, 90, 10);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 90, 90, 10, 0);
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
litest_touch_down(dev, 1, 70, 50);
|
||||
|
|
@ -423,7 +510,7 @@ START_TEST(touchpad_no_2fg_tap_after_timeout)
|
|||
*/
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
libinput_dispatch(dev->libinput);
|
||||
msleep(300);
|
||||
litest_timeout_tap();
|
||||
libinput_dispatch(dev->libinput);
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
|
|
@ -450,7 +537,7 @@ START_TEST(touchpad_no_first_fg_tap_after_move)
|
|||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_down(dev, 1, 70, 50);
|
||||
libinput_dispatch(dev->libinput);
|
||||
litest_touch_move_to(dev, 1, 70, 50, 90, 90, 10);
|
||||
litest_touch_move_to(dev, 1, 70, 50, 90, 90, 10, 0);
|
||||
libinput_dispatch(dev->libinput);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
|
|
@ -516,7 +603,7 @@ START_TEST(touchpad_1fg_tap_n_drag_click)
|
|||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 80, 50, 10);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 80, 50, 10, 0);
|
||||
|
||||
litest_assert_button_event(li, BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
|
|
@ -577,7 +664,7 @@ START_TEST(touchpad_3fg_tap)
|
|||
|
||||
litest_assert_button_event(li, BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
msleep(300); /* tap-n-drag timeout */
|
||||
litest_timeout_tap();
|
||||
litest_assert_button_event(li, BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
|
|
@ -613,7 +700,7 @@ START_TEST(touchpad_3fg_tap_btntool)
|
|||
|
||||
litest_assert_button_event(li, BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
msleep(300); /* tap-n-drag timeout */
|
||||
litest_timeout_tap();
|
||||
litest_assert_button_event(li, BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
|
|
@ -648,7 +735,7 @@ START_TEST(touchpad_3fg_tap_btntool_inverted)
|
|||
|
||||
litest_assert_button_event(li, BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
msleep(300); /* tap-n-drag timeout */
|
||||
litest_timeout_tap();
|
||||
litest_assert_button_event(li, BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
|
|
@ -750,7 +837,7 @@ START_TEST(clickpad_1fg_tap_click)
|
|||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
msleep(200);
|
||||
litest_timeout_tap();
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
|
|
@ -803,7 +890,7 @@ START_TEST(clickpad_click_n_drag)
|
|||
|
||||
/* now put a second finger down */
|
||||
litest_touch_down(dev, 1, 70, 70);
|
||||
litest_touch_move_to(dev, 1, 70, 70, 80, 50, 5);
|
||||
litest_touch_move_to(dev, 1, 70, 70, 80, 50, 5, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
|
@ -997,14 +1084,14 @@ START_TEST(clickpad_softbutton_left_1st_fg_move)
|
|||
litest_assert_empty_queue(li);
|
||||
|
||||
/* move out of the area, then wait for softbutton timer */
|
||||
litest_touch_move_to(dev, 0, 20, 90, 90, 20, 10);
|
||||
litest_touch_move_to(dev, 0, 20, 90, 90, 20, 10, 0);
|
||||
libinput_dispatch(li);
|
||||
msleep(400);
|
||||
litest_timeout_softbuttons();
|
||||
libinput_dispatch(li);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* move down left, expect motion */
|
||||
litest_touch_move_to(dev, 0, 90, 20, 20, 90, 10);
|
||||
litest_touch_move_to(dev, 0, 90, 20, 20, 90, 10, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
|
|
@ -1070,7 +1157,7 @@ START_TEST(clickpad_softbutton_left_2nd_fg_move)
|
|||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_touch_down(dev, 1, 20, 20);
|
||||
litest_touch_move_to(dev, 1, 20, 20, 80, 20, 10);
|
||||
litest_touch_move_to(dev, 1, 20, 20, 80, 20, 10, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
|
|
@ -1086,8 +1173,12 @@ START_TEST(clickpad_softbutton_left_2nd_fg_move)
|
|||
x = libinput_event_pointer_get_dx(p);
|
||||
y = libinput_event_pointer_get_dy(p);
|
||||
|
||||
ck_assert(x > 0);
|
||||
ck_assert(y == 0);
|
||||
/* Ignore events only containing an unaccelerated motion
|
||||
* vector. */
|
||||
if (x != 0 || y != 0) {
|
||||
ck_assert(x > 0);
|
||||
ck_assert(y == 0);
|
||||
}
|
||||
|
||||
libinput_event_destroy(event);
|
||||
libinput_dispatch(li);
|
||||
|
|
@ -1097,7 +1188,7 @@ START_TEST(clickpad_softbutton_left_2nd_fg_move)
|
|||
|
||||
/* second finger down */
|
||||
litest_touch_down(dev, 1, 20, 20);
|
||||
litest_touch_move_to(dev, 1, 20, 20, 20, 80, 10);
|
||||
litest_touch_move_to(dev, 1, 20, 20, 20, 80, 10, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
|
|
@ -1148,7 +1239,7 @@ START_TEST(clickpad_softbutton_left_to_right)
|
|||
*/
|
||||
|
||||
litest_touch_down(dev, 0, 20, 90);
|
||||
litest_touch_move_to(dev, 0, 20, 90, 90, 90, 10);
|
||||
litest_touch_move_to(dev, 0, 20, 90, 90, 90, 10, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
|
|
@ -1182,7 +1273,7 @@ START_TEST(clickpad_softbutton_right_to_left)
|
|||
*/
|
||||
|
||||
litest_touch_down(dev, 0, 90, 90);
|
||||
litest_touch_move_to(dev, 0, 90, 90, 20, 90, 10);
|
||||
litest_touch_move_to(dev, 0, 90, 90, 20, 90, 10, 0);
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
|
|
@ -1302,13 +1393,13 @@ START_TEST(clickpad_topsoftbuttons_move_out_ignore)
|
|||
|
||||
litest_touch_down(dev, 0, 50, 5);
|
||||
libinput_dispatch(li);
|
||||
msleep(200);
|
||||
litest_timeout_softbuttons();
|
||||
libinput_dispatch(li);
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_touch_move_to(dev, 0, 50, 5, 80, 90, 20);
|
||||
litest_touch_move_to(dev, 0, 50, 5, 80, 90, 20, 0);
|
||||
libinput_dispatch(li);
|
||||
msleep(400);
|
||||
litest_timeout_softbuttons();
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||
|
|
@ -1323,20 +1414,20 @@ START_TEST(clickpad_topsoftbuttons_move_out_ignore)
|
|||
END_TEST
|
||||
|
||||
static void
|
||||
test_2fg_scroll(struct litest_device *dev, double dx, double dy, int sleep)
|
||||
test_2fg_scroll(struct litest_device *dev, double dx, double dy, int want_sleep)
|
||||
{
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_touch_down(dev, 0, 47, 50);
|
||||
litest_touch_down(dev, 1, 53, 50);
|
||||
|
||||
litest_touch_move_to(dev, 0, 47, 50, 47 + dx, 50 + dy, 5);
|
||||
litest_touch_move_to(dev, 1, 53, 50, 53 + dx, 50 + dy, 5);
|
||||
litest_touch_move_to(dev, 0, 47, 50, 47 + dx, 50 + dy, 5, 0);
|
||||
litest_touch_move_to(dev, 1, 53, 50, 53 + dx, 50 + dy, 5, 0);
|
||||
|
||||
/* Avoid a small scroll being seen as a tap */
|
||||
if (sleep) {
|
||||
if (want_sleep) {
|
||||
libinput_dispatch(li);
|
||||
msleep(sleep);
|
||||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
|
|
@ -1368,6 +1459,96 @@ START_TEST(touchpad_2fg_scroll)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_2fg_scroll_slow_distance)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 20, 30);
|
||||
litest_touch_down(dev, 1, 40, 30);
|
||||
litest_touch_move_to(dev, 0, 20, 30, 20, 50, 60, 10);
|
||||
litest_touch_move_to(dev, 1, 40, 30, 40, 50, 60, 10);
|
||||
litest_touch_up(dev, 1);
|
||||
litest_touch_up(dev, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert_notnull(event);
|
||||
|
||||
/* last event is value 0, tested elsewhere */
|
||||
while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE) {
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_POINTER_AXIS);
|
||||
ptrev = libinput_event_get_pointer_event(event);
|
||||
|
||||
ck_assert_int_eq(libinput_event_pointer_get_axis(ptrev),
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
||||
ck_assert(libinput_event_pointer_get_axis_value(ptrev) > 0.0);
|
||||
|
||||
/* this is to verify we test the right thing, if the value
|
||||
is greater than scroll.threshold we triggered the wrong
|
||||
condition */
|
||||
ck_assert(libinput_event_pointer_get_axis_value(ptrev) < 5.0);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
event = libinput_get_event(li);
|
||||
}
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_scroll_natural_defaults)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
||||
ck_assert_int_ge(libinput_device_config_scroll_has_natural_scroll(dev->libinput_device), 1);
|
||||
ck_assert_int_eq(libinput_device_config_scroll_get_natural_scroll_enabled(dev->libinput_device), 0);
|
||||
ck_assert_int_eq(libinput_device_config_scroll_get_default_natural_scroll_enabled(dev->libinput_device), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_scroll_natural_enable_config)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
enum libinput_config_status status;
|
||||
|
||||
status = libinput_device_config_scroll_set_natural_scroll_enabled(dev->libinput_device, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
ck_assert_int_eq(libinput_device_config_scroll_get_natural_scroll_enabled(dev->libinput_device), 1);
|
||||
|
||||
status = libinput_device_config_scroll_set_natural_scroll_enabled(dev->libinput_device, 0);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
ck_assert_int_eq(libinput_device_config_scroll_get_natural_scroll_enabled(dev->libinput_device), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_scroll_natural)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
libinput_device_config_scroll_set_natural_scroll_enabled(dev->libinput_device, 1);
|
||||
|
||||
test_2fg_scroll(dev, 0.1, 40, 0);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -10);
|
||||
test_2fg_scroll(dev, 0.1, -40, 0);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 10);
|
||||
test_2fg_scroll(dev, 40, 0.1, 0);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -10);
|
||||
test_2fg_scroll(dev, -40, 0.1, 0);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 10);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_tap_is_available)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -1436,13 +1617,13 @@ START_TEST(touchpad_palm_detect_at_edge)
|
|||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 99, 50);
|
||||
litest_touch_move_to(dev, 0, 99, 50, 99, 70, 5);
|
||||
litest_touch_move_to(dev, 0, 99, 50, 99, 70, 5, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_touch_down(dev, 0, 5, 50);
|
||||
litest_touch_move_to(dev, 0, 5, 50, 5, 70, 5);
|
||||
litest_touch_move_to(dev, 0, 5, 50, 5, 70, 5, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
|
@ -1460,13 +1641,13 @@ START_TEST(touchpad_palm_detect_at_bottom_corners)
|
|||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 99, 95);
|
||||
litest_touch_move_to(dev, 0, 99, 95, 99, 99, 10);
|
||||
litest_touch_move_to(dev, 0, 99, 95, 99, 99, 10, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_touch_down(dev, 0, 5, 95);
|
||||
litest_touch_move_to(dev, 0, 5, 95, 5, 99, 5);
|
||||
litest_touch_move_to(dev, 0, 5, 95, 5, 99, 5, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
|
@ -1484,13 +1665,13 @@ START_TEST(touchpad_palm_detect_at_top_corners)
|
|||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 99, 5);
|
||||
litest_touch_move_to(dev, 0, 99, 5, 99, 9, 10);
|
||||
litest_touch_move_to(dev, 0, 99, 5, 99, 9, 10, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_touch_down(dev, 0, 5, 5);
|
||||
litest_touch_move_to(dev, 0, 5, 5, 5, 9, 5);
|
||||
litest_touch_move_to(dev, 0, 5, 5, 5, 9, 5, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
|
@ -1506,7 +1687,7 @@ START_TEST(touchpad_palm_detect_palm_stays_palm)
|
|||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 99, 20);
|
||||
litest_touch_move_to(dev, 0, 99, 20, 75, 99, 5);
|
||||
litest_touch_move_to(dev, 0, 99, 20, 75, 99, 5, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
|
|
@ -1525,7 +1706,7 @@ START_TEST(touchpad_palm_detect_palm_becomes_pointer)
|
|||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 99, 50);
|
||||
litest_touch_move_to(dev, 0, 99, 50, 0, 70, 5);
|
||||
litest_touch_move_to(dev, 0, 99, 50, 0, 70, 5, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
|
@ -1558,11 +1739,11 @@ START_TEST(touchpad_palm_detect_no_palm_moving_into_edges)
|
|||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 99, 50, 5);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 99, 50, 5, 0);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_move_to(dev, 0, 99, 50, 99, 90, 5);
|
||||
litest_touch_move_to(dev, 0, 99, 50, 99, 90, 5, 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
type = libinput_next_event_type(li);
|
||||
|
|
@ -1582,14 +1763,314 @@ START_TEST(touchpad_palm_detect_no_palm_moving_into_edges)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_left_handed)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *d = dev->libinput_device;
|
||||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_button_click(dev, BTN_RIGHT, 1);
|
||||
litest_button_click(dev, BTN_RIGHT, 0);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
if (libevdev_has_event_code(dev->evdev,
|
||||
EV_KEY,
|
||||
BTN_MIDDLE)) {
|
||||
litest_button_click(dev, BTN_MIDDLE, 1);
|
||||
litest_button_click(dev, BTN_MIDDLE, 0);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_MIDDLE,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_left_handed_clickpad)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *d = dev->libinput_device;
|
||||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_touch_down(dev, 0, 10, 90);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_touch_down(dev, 0, 90, 90);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_left_handed_clickfinger)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *d = dev->libinput_device;
|
||||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_touch_down(dev, 0, 10, 90);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
/* Clickfinger is unaffected by left-handed setting */
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_touch_down(dev, 0, 10, 90);
|
||||
litest_touch_down(dev, 1, 30, 90);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_left_handed_tapping)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *d = dev->libinput_device;
|
||||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
libinput_device_config_tap_set_enabled(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
|
||||
/* Tapping is unaffected by left-handed setting */
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_left_handed_tapping_2fg)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *d = dev->libinput_device;
|
||||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
libinput_device_config_tap_set_enabled(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_down(dev, 1, 70, 50);
|
||||
litest_touch_up(dev, 0);
|
||||
litest_touch_up(dev, 1);
|
||||
|
||||
libinput_dispatch(li);
|
||||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
|
||||
/* Tapping is unaffected by left-handed setting */
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_left_handed_delayed)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *d = dev->libinput_device;
|
||||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
/* left-handed takes effect now */
|
||||
litest_button_click(dev, BTN_RIGHT, 1);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 0);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_button_click(dev, BTN_RIGHT, 0);
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_RIGHT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_left_handed_clickpad_delayed)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *d = dev->libinput_device;
|
||||
struct libinput *li = dev->libinput;
|
||||
enum libinput_config_status status;
|
||||
|
||||
litest_drain_events(li);
|
||||
litest_touch_down(dev, 0, 10, 90);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
|
||||
/* left-handed takes effect now */
|
||||
litest_drain_events(li);
|
||||
litest_touch_down(dev, 0, 90, 90);
|
||||
litest_button_click(dev, BTN_LEFT, 1);
|
||||
libinput_dispatch(li);
|
||||
|
||||
status = libinput_device_config_buttons_set_left_handed(d, 0);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
litest_assert_button_event(li,
|
||||
BTN_LEFT,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
|
||||
litest_add("touchpad:motion", touchpad_1fg_motion, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:motion", touchpad_2fg_no_motion, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
|
||||
litest_add("touchpad:tap", touchpad_1fg_tap, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:tap", touchpad_1fg_tap_n_drag, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:tap", touchpad_1fg_tap_n_drag_timeout, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:tap", touchpad_2fg_tap_n_drag, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:tap", touchpad_2fg_tap_n_drag_3fg_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD);
|
||||
litest_add("touchpad:tap", touchpad_2fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:tap", touchpad_2fg_tap_inverted, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:tap", touchpad_1fg_tap_click, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
|
|
@ -1640,6 +2121,10 @@ int main(int argc, char **argv) {
|
|||
litest_add("touchpad:topsoftbuttons", clickpad_topsoftbuttons_move_out_ignore, LITEST_TOPBUTTONPAD, LITEST_ANY);
|
||||
|
||||
litest_add("touchpad:scroll", touchpad_2fg_scroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:scroll", touchpad_2fg_scroll_slow_distance, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:scroll", touchpad_scroll_natural_defaults, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_scroll_natural_enable_config, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:scroll", touchpad_scroll_natural, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
|
||||
litest_add("touchpad:palm", touchpad_palm_detect_at_edge, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:palm", touchpad_palm_detect_at_bottom_corners, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
|
|
@ -1648,5 +2133,13 @@ int main(int argc, char **argv) {
|
|||
litest_add("touchpad:palm", touchpad_palm_detect_palm_stays_palm, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:palm", touchpad_palm_detect_no_palm_moving_into_edges, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
|
||||
litest_add("touchpad:left-handed", touchpad_left_handed, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
litest_add("touchpad:left-handed", touchpad_left_handed_clickpad, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD);
|
||||
litest_add("touchpad:left-handed", touchpad_left_handed_clickfinger, LITEST_APPLE_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:left-handed", touchpad_left_handed_tapping, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("touchpad:left-handed", touchpad_left_handed_tapping_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:left-handed", touchpad_left_handed_delayed, LITEST_TOUCHPAD, LITEST_CLICKPAD);
|
||||
litest_add("touchpad:left-handed", touchpad_left_handed_clickpad_delayed, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,26 +49,6 @@ START_TEST(trackpoint_middlebutton)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
static void
|
||||
test_2fg_scroll(struct litest_device *dev, double dx, double dy)
|
||||
{
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_button_click(dev, BTN_MIDDLE, 1);
|
||||
|
||||
libinput_dispatch(li);
|
||||
msleep(300);
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_event(dev, EV_REL, REL_X, dx);
|
||||
litest_event(dev, EV_REL, REL_Y, dy);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
litest_button_click(dev, BTN_MIDDLE, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
}
|
||||
|
||||
START_TEST(trackpoint_scroll)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -76,27 +56,61 @@ START_TEST(trackpoint_scroll)
|
|||
|
||||
litest_drain_events(li);
|
||||
|
||||
test_2fg_scroll(dev, 1, 6);
|
||||
litest_button_scroll(dev, BTN_MIDDLE, 1, 6);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 6);
|
||||
test_2fg_scroll(dev, 1, -7);
|
||||
litest_button_scroll(dev, BTN_MIDDLE, 1, -7);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -7);
|
||||
test_2fg_scroll(dev, 8, 1);
|
||||
litest_button_scroll(dev, BTN_MIDDLE, 8, 1);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 8);
|
||||
test_2fg_scroll(dev, -9, 1);
|
||||
litest_button_scroll(dev, BTN_MIDDLE, -9, 1);
|
||||
litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -9);
|
||||
|
||||
/* scroll smaller than the threshold should not generate events */
|
||||
test_2fg_scroll(dev, 1, 1);
|
||||
litest_button_scroll(dev, BTN_MIDDLE, 1, 1);
|
||||
/* long middle press without movement should not generate events */
|
||||
test_2fg_scroll(dev, 0, 0);
|
||||
litest_button_scroll(dev, BTN_MIDDLE, 0, 0);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(trackpoint_middlebutton_noscroll)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
|
||||
/* Disable middle button scrolling */
|
||||
libinput_device_config_scroll_set_method(dev->libinput_device,
|
||||
LIBINPUT_CONFIG_SCROLL_NO_SCROLL);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* A long middle button click + motion should get reported normally now */
|
||||
litest_button_scroll(dev, BTN_MIDDLE, 0, 10);
|
||||
|
||||
litest_assert_button_event(li, BTN_MIDDLE, 1);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert(event != NULL);
|
||||
ck_assert_int_eq(libinput_event_get_type(event), LIBINPUT_EVENT_POINTER_MOTION);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
litest_assert_button_event(li, BTN_MIDDLE, 0);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* Restore default scroll behavior */
|
||||
libinput_device_config_scroll_set_method(dev->libinput_device,
|
||||
libinput_device_config_scroll_get_default_method(
|
||||
dev->libinput_device));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
litest_add("trackpoint:middlebutton", trackpoint_middlebutton, LITEST_POINTINGSTICK, LITEST_ANY);
|
||||
litest_add("trackpoint:middlebutton", trackpoint_middlebutton_noscroll, LITEST_POINTINGSTICK, LITEST_ANY);
|
||||
litest_add("trackpoint:scroll", trackpoint_scroll, LITEST_POINTINGSTICK, LITEST_ANY);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
|
|
|
|||
78
test/udev.c
78
test/udev.c
|
|
@ -175,6 +175,81 @@ START_TEST(udev_added_seat_default)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
/**
|
||||
* This test only works if there's at least one device in the system that is
|
||||
* assigned the default seat. Should cover the 99% case.
|
||||
*/
|
||||
START_TEST(udev_change_seat)
|
||||
{
|
||||
struct libinput *li;
|
||||
struct udev *udev;
|
||||
struct libinput_event *event;
|
||||
struct libinput_device *device;
|
||||
struct libinput_seat *seat1, *seat2;
|
||||
const char *seat1_name;
|
||||
const char *seat2_name = "new seat";
|
||||
int rc;
|
||||
|
||||
udev = udev_new();
|
||||
ck_assert(udev != NULL);
|
||||
|
||||
li = libinput_udev_create_context(&simple_interface, NULL, udev);
|
||||
ck_assert(li != NULL);
|
||||
ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert(event != NULL);
|
||||
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_DEVICE_ADDED);
|
||||
|
||||
device = libinput_event_get_device(event);
|
||||
libinput_device_ref(device);
|
||||
|
||||
seat1 = libinput_device_get_seat(device);
|
||||
libinput_seat_ref(seat1);
|
||||
|
||||
seat1_name = libinput_seat_get_logical_name(seat1);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
rc = libinput_device_set_seat_logical_name(device,
|
||||
seat2_name);
|
||||
ck_assert_int_eq(rc, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_DEVICE_REMOVED);
|
||||
|
||||
ck_assert(libinput_event_get_device(event) == device);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
event = libinput_get_event(li);
|
||||
ck_assert_int_eq(libinput_event_get_type(event),
|
||||
LIBINPUT_EVENT_DEVICE_ADDED);
|
||||
ck_assert(libinput_event_get_device(event) != device);
|
||||
libinput_device_unref(device);
|
||||
|
||||
device = libinput_event_get_device(event);
|
||||
seat2 = libinput_device_get_seat(device);
|
||||
|
||||
ck_assert_str_ne(libinput_seat_get_logical_name(seat2),
|
||||
seat1_name);
|
||||
ck_assert_str_eq(libinput_seat_get_logical_name(seat2),
|
||||
seat2_name);
|
||||
libinput_event_destroy(event);
|
||||
|
||||
libinput_seat_unref(seat1);
|
||||
|
||||
libinput_unref(li);
|
||||
udev_unref(udev);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(udev_double_suspend)
|
||||
{
|
||||
struct libinput *li;
|
||||
|
|
@ -414,7 +489,8 @@ main(int argc, char **argv)
|
|||
litest_add_no_device("udev:create", udev_create_seat0);
|
||||
litest_add_no_device("udev:create", udev_create_empty_seat);
|
||||
|
||||
litest_add_no_device("udev:seat events", udev_added_seat_default);
|
||||
litest_add_no_device("udev:seat", udev_added_seat_default);
|
||||
litest_add_no_device("udev:seat", udev_change_seat);
|
||||
|
||||
litest_add_for_device("udev:suspend", udev_double_suspend, LITEST_SYNAPTICS_CLICKPAD);
|
||||
litest_add_for_device("udev:suspend", udev_double_resume, LITEST_SYNAPTICS_CLICKPAD);
|
||||
|
|
|
|||
|
|
@ -269,15 +269,38 @@ print_device_notify(struct libinput_event *ev)
|
|||
struct libinput_device *dev = libinput_event_get_device(ev);
|
||||
struct libinput_seat *seat = libinput_device_get_seat(dev);
|
||||
double w, h;
|
||||
uint32_t scroll_methods;
|
||||
|
||||
printf("%s %s",
|
||||
printf("%-30s %s %s",
|
||||
libinput_device_get_name(dev),
|
||||
libinput_seat_get_physical_name(seat),
|
||||
libinput_seat_get_logical_name(seat));
|
||||
|
||||
if (libinput_device_get_size(dev, &w, &h) == 0)
|
||||
printf("\tsize %.2f/%.2fmm", w, h);
|
||||
|
||||
if (libinput_device_config_tap_get_finger_count((dev)))
|
||||
printf(" tap");
|
||||
if (libinput_device_config_buttons_has_left_handed((dev)))
|
||||
printf(" left");
|
||||
if (libinput_device_config_scroll_has_natural_scroll((dev)))
|
||||
printf(" scroll-nat");
|
||||
if (libinput_device_config_calibration_has_matrix((dev)))
|
||||
printf(" calib");
|
||||
|
||||
scroll_methods = libinput_device_config_scroll_get_methods(dev);
|
||||
if (scroll_methods != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) {
|
||||
printf(" scroll");
|
||||
if (scroll_methods & LIBINPUT_CONFIG_SCROLL_2FG)
|
||||
printf("-2fg");
|
||||
if (scroll_methods & LIBINPUT_CONFIG_SCROLL_EDGE)
|
||||
printf("-edge");
|
||||
if (scroll_methods & LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN)
|
||||
printf("-button");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ struct window {
|
|||
|
||||
/* l/m/r mouse buttons */
|
||||
int l, m, r;
|
||||
|
||||
struct libinput_device *devices[50];
|
||||
};
|
||||
|
||||
static int
|
||||
|
|
@ -211,18 +213,69 @@ window_init(struct window *w)
|
|||
gtk_widget_show_all(w->win);
|
||||
}
|
||||
|
||||
static void
|
||||
window_cleanup(struct window *w)
|
||||
{
|
||||
struct libinput_device **dev;
|
||||
ARRAY_FOR_EACH(w->devices, dev) {
|
||||
if (*dev)
|
||||
libinput_device_unref(*dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
change_ptraccel(struct window *w, double amount)
|
||||
{
|
||||
struct libinput_device **dev;
|
||||
|
||||
ARRAY_FOR_EACH(w->devices, dev) {
|
||||
double speed;
|
||||
enum libinput_config_status status;
|
||||
|
||||
if (*dev == NULL)
|
||||
continue;
|
||||
|
||||
if (!libinput_device_config_accel_is_available(*dev))
|
||||
continue;
|
||||
|
||||
speed = libinput_device_config_accel_get_speed(*dev);
|
||||
speed = clip(speed + amount, -1, 1);
|
||||
|
||||
status = libinput_device_config_accel_set_speed(*dev, speed);
|
||||
|
||||
if (status != LIBINPUT_CONFIG_STATUS_SUCCESS) {
|
||||
msg("%s: failed to change accel to %.2f (%s)\n",
|
||||
libinput_device_get_name(*dev),
|
||||
speed,
|
||||
libinput_config_status_to_str(status));
|
||||
} else {
|
||||
printf("%s: speed is %.2f\n",
|
||||
libinput_device_get_name(*dev),
|
||||
speed);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handle_event_device_notify(struct libinput_event *ev)
|
||||
{
|
||||
struct libinput_device *dev = libinput_event_get_device(ev);
|
||||
struct libinput *li;
|
||||
struct window *w;
|
||||
const char *type;
|
||||
int i;
|
||||
|
||||
if (libinput_event_get_type(ev) == LIBINPUT_EVENT_DEVICE_ADDED)
|
||||
type = "added";
|
||||
else
|
||||
type = "removed";
|
||||
|
||||
msg("%s %s\n", libinput_device_get_sysname(dev), type);
|
||||
msg("%s %-30s %s\n",
|
||||
libinput_device_get_sysname(dev),
|
||||
libinput_device_get_name(dev),
|
||||
type);
|
||||
|
||||
if (libinput_device_config_tap_get_finger_count(dev) > 0) {
|
||||
enum libinput_config_status status;
|
||||
|
|
@ -232,6 +285,26 @@ handle_event_device_notify(struct libinput_event *ev)
|
|||
error("%s: Failed to enable tapping\n",
|
||||
libinput_device_get_sysname(dev));
|
||||
}
|
||||
|
||||
li = libinput_event_get_context(ev);
|
||||
w = libinput_get_user_data(li);
|
||||
|
||||
if (libinput_event_get_type(ev) == LIBINPUT_EVENT_DEVICE_ADDED) {
|
||||
for (i = 0; i < ARRAY_LENGTH(w->devices); i++) {
|
||||
if (w->devices[i] == NULL) {
|
||||
w->devices[i] = libinput_device_ref(dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_LENGTH(w->devices); i++) {
|
||||
if (w->devices[i] == dev) {
|
||||
libinput_device_unref(w->devices[i]);
|
||||
w->devices[i] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -309,9 +382,24 @@ static int
|
|||
handle_event_keyboard(struct libinput_event *ev, struct window *w)
|
||||
{
|
||||
struct libinput_event_keyboard *k = libinput_event_get_keyboard_event(ev);
|
||||
unsigned int key = libinput_event_keyboard_get_key(k);
|
||||
|
||||
if (libinput_event_keyboard_get_key(k) == KEY_ESC)
|
||||
if (libinput_event_keyboard_get_key_state(k) ==
|
||||
LIBINPUT_KEY_STATE_RELEASED)
|
||||
return 0;
|
||||
|
||||
switch(key) {
|
||||
case KEY_ESC:
|
||||
return 1;
|
||||
case KEY_UP:
|
||||
change_ptraccel(w, 0.1);
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
change_ptraccel(w, -0.1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -479,6 +567,7 @@ main(int argc, char *argv[])
|
|||
|
||||
gtk_main();
|
||||
|
||||
window_cleanup(&w);
|
||||
libinput_unref(li);
|
||||
udev_unref(udev);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue