> I find the mouse emulation code for synaptics touch pads in your patch > really weird. I've tried to understand what it does, and why it > behaves badly for me on the first tap (move the pointer in the upper > right direction every time), but I fail to understand the logic.
your change makes the problem worse on 2 laptops (samsung series 9 and thinkpad x220), where the cursor now jumps to the lower left after every movement. these seem to be due to events that come through after removing all the fingers from the touchpad that need to be ignored. i checked linux and they also ignore these events: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=4f56ce929cab45a3a6e1a81700da52bb9bdbfc0f this also adds support for "clickpads" where there is only one physical button and it's the entire trackpad that moves down, which both of those laptops have. without this change, the click gets ignored. --- pms.c.new Mon Jun 13 16:26:39 2011 +++ pms.c Mon Jun 13 20:06:59 2011 @@ -799,7 +799,9 @@ syn->wsmode = WSMOUSE_COMPAT; syn->count = 0; - printf("%s: Synaptics touchpad, firmware %d.%d\n", DEVNAME(sc), + printf("%s: Synaptics %s, firmware %d.%d\n", DEVNAME(sc), + (syn->capabilities & SYNAPTICS_EXT_CAP_CLICKPAD ? + "clickpad" : "touchpad"), SYNAPTICS_ID_MAJOR(syn->identify), SYNAPTICS_ID_MINOR(syn->identify)); } @@ -882,8 +884,11 @@ buttons |= ((sc->packet[0] & 0x02) & (sc->packet[3] & 0x02)) ? WSMOUSE_BUTTON(3) : 0; - if (syn->capabilities & SYNAPTICS_CAP_MIDDLE_BUTTON) { + if (syn->ext_capabilities & SYNAPTICS_EXT_CAP_CLICKPAD) { buttons |= ((sc->packet[0] & 0x01) ^ (sc->packet[3] & 0x01)) ? + WSMOUSE_BUTTON(1) : 0; + } else if (syn->capabilities & SYNAPTICS_CAP_MIDDLE_BUTTON) { + buttons |= ((sc->packet[0] & 0x01) ^ (sc->packet[3] & 0x01)) ? WSMOUSE_BUTTON(2) : 0; } @@ -906,6 +911,14 @@ y &= ~0x0f; } + /* ignore final events that happen when removing all fingers */ + if (x <= 1 && !z) { + x = syn->old_x; + y = syn->old_y; + w = 0; + buttons = 0; + } + if (syn->wsmode == WSMOUSE_NATIVE) { wsmouse_input(sc->sc_wsmousedev, buttons, x, y, z, w, WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y | @@ -925,10 +938,11 @@ if (dx || dy || buttons != syn->old_buttons) wsmouse_input(sc->sc_wsmousedev, buttons, dx, dy, 0, 0, WSMOUSE_INPUT_DELTA); - syn->old_x = x; - syn->old_y = y; syn->old_buttons = buttons; } + + syn->old_x = x; + syn->old_y = y; } void