From db7dc1085e43ccdd796c67174289313ed4852c13 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Sat, 6 Sep 2008 03:03:42 +0930 Subject: Don't lose button up event if timeout is cancelled in the same ReadInput cycle On a left/right button press, middle button emulation springs into action and changes the reported hw state. It then returns a delay that is supposed to set a timer. No button event is posted to the server, the timer ensures that it'll be posted later. If however - in the same cycle - the button up is reported, but with a hardware time > middle emulation timeout, the middle button emulation is canceled. The hw state is reset to button down, and processing continues, reporting the button down event. Since this is in the same cycle, the new delay overrides the previous one and the timer is never set. Introduce a new state into MB emulation that forces the click event if the above situation occurs. Red Hat Bug 233717 --- src/synaptics.c | 28 ++++++++++++++++++++++++++-- src/synapticsstr.h | 4 +++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/synaptics.c b/src/synaptics.c index 8475d1a..7aa5c79 100644 --- a/src/synaptics.c +++ b/src/synaptics.c @@ -878,6 +878,8 @@ HandleMidButtonEmulation(SynapticsPrivate *priv, struct SynapticsHwState *hw, in while (!done) { switch (priv->mid_emu_state) { + case MBE_LEFT_CLICK: + case MBE_RIGHT_CLICK: case MBE_OFF: priv->button_delay_millis = hw->millis; if (hw->left) { @@ -893,7 +895,12 @@ HandleMidButtonEmulation(SynapticsPrivate *priv, struct SynapticsHwState *hw, in hw->millis); if (timeleft > 0) *delay = MIN(*delay, timeleft); - if (!hw->left || (timeleft <= 0)) { + + /* timeout, but within the same ReadInput cycle! */ + if ((timeleft <= 0) && !hw->left) { + priv->mid_emu_state = MBE_LEFT_CLICK; + done = TRUE; + } else if ((!hw->left) || (timeleft <= 0)) { hw->left = TRUE; priv->mid_emu_state = MBE_TIMEOUT; done = TRUE; @@ -909,7 +916,12 @@ HandleMidButtonEmulation(SynapticsPrivate *priv, struct SynapticsHwState *hw, in hw->millis); if (timeleft > 0) *delay = MIN(*delay, timeleft); - if (!hw->right || (timeleft <= 0)) { + + /* timeout, but within the same ReadInput cycle! */ + if ((timeleft <= 0) && !hw->right) { + priv->mid_emu_state = MBE_RIGHT_CLICK; + done = TRUE; + } else if (!hw->right || (timeleft <= 0)) { hw->right = TRUE; priv->mid_emu_state = MBE_TIMEOUT; done = TRUE; @@ -1919,6 +1931,18 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw) if (dx || dy) xf86PostMotionEvent(local->dev, 0, 0, 2, dx, dy); + if (priv->mid_emu_state == MBE_LEFT_CLICK) + { + xf86PostButtonEvent(local->dev, FALSE, 1, 1, 0, 0); + xf86PostButtonEvent(local->dev, FALSE, 1, 0, 0, 0); + priv->mid_emu_state = MBE_OFF; + } else if (priv->mid_emu_state == MBE_RIGHT_CLICK) + { + xf86PostButtonEvent(local->dev, FALSE, 3, 1, 0, 0); + xf86PostButtonEvent(local->dev, FALSE, 3, 0, 0, 0); + priv->mid_emu_state = MBE_OFF; + } + change = buttons ^ priv->lastButtons; while (change) { id = ffs(change); /* number of first set bit 1..32 is returned */ diff --git a/src/synapticsstr.h b/src/synapticsstr.h index ca61a9c..5d61d0e 100644 --- a/src/synapticsstr.h +++ b/src/synapticsstr.h @@ -54,7 +54,9 @@ enum MidButtonEmulation { MBE_RIGHT, /* Right button pressed, waiting for left button or timeout */ MBE_MID, /* Left and right buttons pressed, waiting for both buttons to be released */ - MBE_TIMEOUT /* Waiting for both buttons to be released. */ + MBE_TIMEOUT, /* Waiting for both buttons to be released. */ + MBE_LEFT_CLICK, /* Emulate left button click. */ + MBE_RIGHT_CLICK, /* Emulate right button click. */ }; /* See docs/tapndrag.dia for a state machine diagram */ -- cgit v1.2.3