diff options
author | bru <bru@cvs.openbsd.org> | 2015-09-05 13:52:55 +0000 |
---|---|---|
committer | bru <bru@cvs.openbsd.org> | 2015-09-05 13:52:55 +0000 |
commit | d66d36ac7d36baca5baa8922a68c5bd53bf3efe1 (patch) | |
tree | f3e3917018f80151b4d4774264297295251ff14f /sys/dev/pckbc/pms.c | |
parent | 5f21e2b5b73e5d1945fb5f7f711a569bf6601015 (diff) |
Improve tap-and-drag detection for ALPS touchpads.
The ALPS mechanism for gesture detection can produce long delays between
a packet that signals a tap and the next packet, which either signals
the end of the gesture or the start of a drag-operation. The time spans
can exceed the timeouts used by the generic detection mechanism in the
synaptics driver. Reporting both the touch and the release event when
the second packet has arrived ensures that the tap will be recognized.
ok mpi@ shadchin@
Diffstat (limited to 'sys/dev/pckbc/pms.c')
-rw-r--r-- | sys/dev/pckbc/pms.c | 60 |
1 files changed, 38 insertions, 22 deletions
diff --git a/sys/dev/pckbc/pms.c b/sys/dev/pckbc/pms.c index c0e95c6bfc9..147a130c49c 100644 --- a/sys/dev/pckbc/pms.c +++ b/sys/dev/pckbc/pms.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pms.c,v 1.65 2015/08/23 04:45:23 deraadt Exp $ */ +/* $OpenBSD: pms.c,v 1.66 2015/09/05 13:52:54 bru Exp $ */ /* $NetBSD: psm.c,v 1.11 2000/06/05 22:20:57 sommerfeld Exp $ */ /*- @@ -120,7 +120,8 @@ struct alps_softc { int min_x, min_y; int max_x, max_y; - int old_fin; + + u_int gesture; u_int sec_buttons; /* trackpoint */ @@ -1522,8 +1523,7 @@ pms_proc_alps(struct pms_softc *sc) { struct alps_softc *alps = sc->alps; int x, y, z, w, dx, dy; - u_int buttons; - int fin, ges; + u_int buttons, gesture; if ((alps->model & ALPS_DUALPOINT) && alps_sec_proc(sc)) return; @@ -1558,28 +1558,44 @@ pms_proc_alps(struct pms_softc *sc) y = ALPS_YMAX_BEZEL - y + ALPS_YMIN_BEZEL; if (alps->wsmode == WSMOUSE_NATIVE) { - ges = sc->packet[2] & 0x01; - fin = sc->packet[2] & 0x02; - - /* Simulate click (tap) */ - if (ges && !fin) - z = 35; + if (alps->gesture == ALPS_TAP) { + /* Report a touch with the tap coordinates. */ + wsmouse_input(sc->sc_wsmousedev, buttons, + alps->old_x, alps->old_y, ALPS_PRESSURE, 4, + WSMOUSE_INPUT_ABSOLUTE_X + | WSMOUSE_INPUT_ABSOLUTE_Y + | WSMOUSE_INPUT_ABSOLUTE_Z + | WSMOUSE_INPUT_ABSOLUTE_W); + if (z > 0) { + /* + * The hardware doesn't send a null pressure + * event when dragging starts. + */ + wsmouse_input(sc->sc_wsmousedev, buttons, + alps->old_x, alps->old_y, 0, 0, + WSMOUSE_INPUT_ABSOLUTE_X + | WSMOUSE_INPUT_ABSOLUTE_Y + | WSMOUSE_INPUT_ABSOLUTE_Z + | WSMOUSE_INPUT_ABSOLUTE_W); + } + } - /* Generate a null pressure event (needed for tap & drag) */ - if (ges && fin && !alps->old_fin) - z = 0; + gesture = sc->packet[2] & 0x03; + if (gesture != ALPS_TAP) { + w = z ? 4 : 0; + wsmouse_input(sc->sc_wsmousedev, buttons, x, y, z, w, + WSMOUSE_INPUT_ABSOLUTE_X + | WSMOUSE_INPUT_ABSOLUTE_Y + | WSMOUSE_INPUT_ABSOLUTE_Z + | WSMOUSE_INPUT_ABSOLUTE_W); + } - /* Generate a width value corresponding to one finger */ - if (z > 0) - w = 4; - else - w = 0; + if (alps->gesture != ALPS_DRAG || gesture != ALPS_TAP) + alps->gesture = gesture; - wsmouse_input(sc->sc_wsmousedev, buttons, x, y, z, w, - WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y | - WSMOUSE_INPUT_ABSOLUTE_Z | WSMOUSE_INPUT_ABSOLUTE_W); + alps->old_x = x; + alps->old_y = y; - alps->old_fin = fin; } else { dx = dy = 0; if (z > ALPS_PRESSURE) { |