1e8a9312aStsutsui/* 2e8a9312aStsutsui * 3e8a9312aStsutsui * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. 4e8a9312aStsutsui * Copyright 1993 by David Dawes <dawes@xfree86.org> 5e8a9312aStsutsui * Copyright 2002 by SuSE Linux AG, Author: Egbert Eich 6e8a9312aStsutsui * Copyright 1994-2002 by The XFree86 Project, Inc. 7e8a9312aStsutsui * Copyright 2002 by Paul Elliott 8e8a9312aStsutsui * 9e8a9312aStsutsui * Permission to use, copy, modify, distribute, and sell this software and its 10e8a9312aStsutsui * documentation for any purpose is hereby granted without fee, provided that 11e8a9312aStsutsui * the above copyright notice appear in all copies and that both that 12e8a9312aStsutsui * copyright notice and this permission notice appear in supporting 13e8a9312aStsutsui * documentation, and that the names of copyright holders not be 14e8a9312aStsutsui * used in advertising or publicity pertaining to distribution of the 15e8a9312aStsutsui * software without specific, written prior permission. The copyright holders 16e8a9312aStsutsui * make no representations about the suitability of this 17e8a9312aStsutsui * software for any purpose. It is provided "as is" without express or 18e8a9312aStsutsui * implied warranty. 19e8a9312aStsutsui * 20e8a9312aStsutsui * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 21e8a9312aStsutsui * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 22e8a9312aStsutsui * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 23e8a9312aStsutsui * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 24e8a9312aStsutsui * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 25e8a9312aStsutsui * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 26e8a9312aStsutsui * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 27e8a9312aStsutsui * 28e8a9312aStsutsui */ 29e8a9312aStsutsui 30e8a9312aStsutsui/* 31e8a9312aStsutsui * 3 button emulation stuff 32e8a9312aStsutsui * based on the emulation method in xf86-input-mouse/dist/src/mouse.c 33e8a9312aStsutsui */ 34e8a9312aStsutsui 35e8a9312aStsutsui#include "inpututils.h" 36e8a9312aStsutsui#include "mouseEmu3btn.h" 37e8a9312aStsutsui 38e8a9312aStsutsuistatic CARD32 buttonTimer(MouseEmu3btnPtr pEmu3btn); 39e8a9312aStsutsuistatic void Emulate3ButtonsSetEnabled(MouseEmu3btnPtr pEmu3btn, Bool enable); 40e8a9312aStsutsuistatic Bool Emulate3ButtonsSoft(MouseEmu3btnPtr pEmu3btn); 41e8a9312aStsutsui 42e8a9312aStsutsuistatic void MouseBlockHandler(void *data, void *waitTime); 43e8a9312aStsutsuistatic void MouseWakeupHandler(void *data, int i); 44e8a9312aStsutsui 45e8a9312aStsutsui/********************************************************************** 46e8a9312aStsutsui * 47e8a9312aStsutsui * Emulate3Button support code 48e8a9312aStsutsui * 49e8a9312aStsutsui **********************************************************************/ 50e8a9312aStsutsui 51e8a9312aStsutsui 52e8a9312aStsutsui/* 53e8a9312aStsutsui * Lets create a simple finite-state machine for 3 button emulation: 54e8a9312aStsutsui * 55e8a9312aStsutsui * We track buttons 1 and 3 (left and right). There are 11 states: 56e8a9312aStsutsui * 0 ground - initial state 57e8a9312aStsutsui * 1 delayed left - left pressed, waiting for right 58e8a9312aStsutsui * 2 delayed right - right pressed, waiting for left 59e8a9312aStsutsui * 3 pressed middle - right and left pressed, emulated middle sent 60e8a9312aStsutsui * 4 pressed left - left pressed and sent 61e8a9312aStsutsui * 5 pressed right - right pressed and sent 62e8a9312aStsutsui * 6 released left - left released after emulated middle 63e8a9312aStsutsui * 7 released right - right released after emulated middle 64e8a9312aStsutsui * 8 repressed left - left pressed after released left 65e8a9312aStsutsui * 9 repressed right - right pressed after released right 66e8a9312aStsutsui * 10 pressed both - both pressed, not emulating middle 67e8a9312aStsutsui */ 68e8a9312aStsutsui#define ST_INVALID -1 69e8a9312aStsutsui#define ST_GROUND 0 /* initial state */ 70e8a9312aStsutsui#define ST_DELAYED_LEFT 1 /* left pressed and waiting timeout */ 71e8a9312aStsutsui#define ST_DELAYED_RIGHT 2 /* right pressed and waiting timeout */ 72e8a9312aStsutsui#define ST_PRESSED_MIDDLE 3 /* middle pressed deteremined */ 73e8a9312aStsutsui#define ST_PRESSED_LEFT 4 /* left pressed determined */ 74e8a9312aStsutsui#define ST_PRESSED_RIGHT 5 /* right pressed determined */ 75e8a9312aStsutsui#define ST_RELEASED_LEFT 6 /* left released after pressed both */ 76e8a9312aStsutsui#define ST_RELEASED_RIGHT 7 /* right released after pressed both */ 77e8a9312aStsutsui#define ST_REPRESSED_LEFT 8 /* left repressed after release */ 78e8a9312aStsutsui#define ST_REPRESSED_RIGHT 9 /* right repressed after release */ 79e8a9312aStsutsui#define ST_PRESSED_BOTH 10 /* both pressed (not as middle) */ 80e8a9312aStsutsui#define NSTATES 11 81e8a9312aStsutsui 82e8a9312aStsutsui/* 83e8a9312aStsutsui * At each state, we need handlers for the following events 84e8a9312aStsutsui * 0: no buttons down 85e8a9312aStsutsui * 1: left button down 86e8a9312aStsutsui * 2: right button down 87e8a9312aStsutsui * 3: both buttons down 88e8a9312aStsutsui * 4: emulate3Timeout passed without a button change 89e8a9312aStsutsui * Note that button events are not deltas, they are the set of buttons being 90e8a9312aStsutsui * pressed now. It's possible (ie, mouse hardware does it) to go from (eg) 91e8a9312aStsutsui * left down to right down without anything in between, so all cases must be 92e8a9312aStsutsui * handled. 93e8a9312aStsutsui * 94e8a9312aStsutsui * a handler consists of three values: 95e8a9312aStsutsui * 0: action1 96e8a9312aStsutsui * 1: action2 97e8a9312aStsutsui * 2: new emulation state 98e8a9312aStsutsui */ 99e8a9312aStsutsuistruct button_event { 100e8a9312aStsutsui int type; /* ButtonNone / ButtonPress / ButtonRelease */ 101e8a9312aStsutsui#define ButtonNone 0 102e8a9312aStsutsui int button; 103e8a9312aStsutsui#define ButtonLeft Button1 104e8a9312aStsutsui#define ButtonMiddle Button2 105e8a9312aStsutsui#define ButtonRight Button3 106e8a9312aStsutsui}; 107e8a9312aStsutsui 108e8a9312aStsutsuistruct button_action { 109e8a9312aStsutsui struct button_event event1; 110e8a9312aStsutsui struct button_event event2; 111e8a9312aStsutsui int new_state; 112e8a9312aStsutsui}; 113e8a9312aStsutsui 114e8a9312aStsutsui/* The set of buttons being pressed passed from DDX mouse events */ 115e8a9312aStsutsui#define BMASK_LEFT 0x01 116e8a9312aStsutsui#define BMASK_MIDDLE 0x02 117e8a9312aStsutsui#define BMASK_RIGHT 0x04 118e8a9312aStsutsui 119e8a9312aStsutsui/* Event index values per buttons being pressed */ 120e8a9312aStsutsui#define EMU_BUTTONS_NONE 0 121e8a9312aStsutsui#define EMU_BUTTONS_LEFT 1 122e8a9312aStsutsui#define EMU_BUTTONS_RIGHT 2 123e8a9312aStsutsui#define EMU_BUTTONS_BOTH 3 124e8a9312aStsutsui#define NEMU_BUTTONSTATE 4 125e8a9312aStsutsui 126e8a9312aStsutsui#define BMASKTOINDEX(bmask) \ 127e8a9312aStsutsui ((((bmask) & BMASK_RIGHT) >> 1) | ((bmask) & BMASK_LEFT)) 128e8a9312aStsutsui 129e8a9312aStsutsuistruct button_state { 130e8a9312aStsutsui struct button_action buttons[NEMU_BUTTONSTATE]; 131e8a9312aStsutsui struct button_action timeout; 132e8a9312aStsutsui}; 133e8a9312aStsutsui 134e8a9312aStsutsui/* 135e8a9312aStsutsui * The comment preceeding each section is the current emulation state. 136e8a9312aStsutsui * The comments to the right are of the form 137e8a9312aStsutsui * <button state> (<events>) -> <new emulation state> 138e8a9312aStsutsui * which should be read as 139e8a9312aStsutsui * If the buttons are in <button state>, generate <events> then go to 140e8a9312aStsutsui * <new emulation state>. 141e8a9312aStsutsui */ 142e8a9312aStsutsuistatic const struct button_state stateTab[NSTATES] = { 143e8a9312aStsutsui 144e8a9312aStsutsui /* 0 ground - initial state */ 145e8a9312aStsutsui [ST_GROUND] = { 146e8a9312aStsutsui 147e8a9312aStsutsui .buttons[EMU_BUTTONS_NONE] = { 148e8a9312aStsutsui /* nothing -> ground (no change) */ 149e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 150e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 151e8a9312aStsutsui .new_state = ST_GROUND, 152e8a9312aStsutsui }, 153e8a9312aStsutsui 154e8a9312aStsutsui .buttons[EMU_BUTTONS_LEFT] = { 155e8a9312aStsutsui /* left -> delayed left */ 156e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 157e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 158e8a9312aStsutsui .new_state = ST_DELAYED_LEFT, 159e8a9312aStsutsui }, 160e8a9312aStsutsui 161e8a9312aStsutsui .buttons[EMU_BUTTONS_RIGHT] = { 162e8a9312aStsutsui /* right -> delayed right */ 163e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 164e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 165e8a9312aStsutsui .new_state = ST_DELAYED_RIGHT, 166e8a9312aStsutsui }, 167e8a9312aStsutsui 168e8a9312aStsutsui .buttons[EMU_BUTTONS_BOTH] = { 169e8a9312aStsutsui /* left & right (middle press) -> pressed middle */ 170e8a9312aStsutsui .event1 = { ButtonPress, ButtonMiddle }, 171e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 172e8a9312aStsutsui .new_state = ST_PRESSED_MIDDLE, 173e8a9312aStsutsui }, 174e8a9312aStsutsui 175e8a9312aStsutsui .timeout = { 176e8a9312aStsutsui /* timeout N/A */ 177e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 178e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 179e8a9312aStsutsui .new_state = ST_INVALID, 180e8a9312aStsutsui }, 181e8a9312aStsutsui }, 182e8a9312aStsutsui 183e8a9312aStsutsui /* 1 delayed left - left pressed, waiting for right */ 184e8a9312aStsutsui [ST_DELAYED_LEFT] = { 185e8a9312aStsutsui 186e8a9312aStsutsui .buttons[EMU_BUTTONS_NONE] = { 187e8a9312aStsutsui /* nothing (left event) -> ground */ 188e8a9312aStsutsui .event1 = { ButtonPress, ButtonLeft }, 189e8a9312aStsutsui .event2 = { ButtonRelease, ButtonLeft }, 190e8a9312aStsutsui .new_state = ST_GROUND, 191e8a9312aStsutsui }, 192e8a9312aStsutsui 193e8a9312aStsutsui .buttons[EMU_BUTTONS_LEFT] = { 194e8a9312aStsutsui /* left -> delayed left (no change) */ 195e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 196e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 197e8a9312aStsutsui .new_state = ST_DELAYED_LEFT, 198e8a9312aStsutsui }, 199e8a9312aStsutsui 200e8a9312aStsutsui .buttons[EMU_BUTTONS_RIGHT] = { 201e8a9312aStsutsui /* right (left event) -> delayed right */ 202e8a9312aStsutsui .event1 = { ButtonPress, ButtonLeft }, 203e8a9312aStsutsui .event2 = { ButtonRelease, ButtonLeft }, 204e8a9312aStsutsui .new_state = ST_DELAYED_RIGHT, 205e8a9312aStsutsui }, 206e8a9312aStsutsui 207e8a9312aStsutsui .buttons[EMU_BUTTONS_BOTH] = { 208e8a9312aStsutsui /* left & right (middle press) -> pressed middle */ 209e8a9312aStsutsui .event1 = { ButtonPress, ButtonMiddle }, 210e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 211e8a9312aStsutsui .new_state = ST_PRESSED_MIDDLE, 212e8a9312aStsutsui }, 213e8a9312aStsutsui 214e8a9312aStsutsui .timeout = { 215e8a9312aStsutsui /* timeout (left press) -> pressed left */ 216e8a9312aStsutsui .event1 = { ButtonPress, ButtonLeft }, 217e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 218e8a9312aStsutsui .new_state = ST_PRESSED_LEFT, 219e8a9312aStsutsui }, 220e8a9312aStsutsui }, 221e8a9312aStsutsui 222e8a9312aStsutsui /* 2 delayed right - right pressed, waiting for left */ 223e8a9312aStsutsui [ST_DELAYED_RIGHT] = { 224e8a9312aStsutsui 225e8a9312aStsutsui .buttons[EMU_BUTTONS_NONE] = { 226e8a9312aStsutsui /* nothing (right event) -> ground */ 227e8a9312aStsutsui .event1 = { ButtonPress, ButtonRight }, 228e8a9312aStsutsui .event2 = { ButtonRelease, ButtonRight }, 229e8a9312aStsutsui .new_state = ST_GROUND, 230e8a9312aStsutsui }, 231e8a9312aStsutsui 232e8a9312aStsutsui .buttons[EMU_BUTTONS_LEFT] = { 233e8a9312aStsutsui /* left (right event) -> delayed left */ 234e8a9312aStsutsui .event1 = { ButtonPress, ButtonRight }, 235e8a9312aStsutsui .event2 = { ButtonRelease, ButtonRight }, 236e8a9312aStsutsui .new_state = ST_DELAYED_LEFT, 237e8a9312aStsutsui }, 238e8a9312aStsutsui 239e8a9312aStsutsui .buttons[EMU_BUTTONS_RIGHT] = { 240e8a9312aStsutsui /* right -> delayed right (no change) */ 241e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 242e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 243e8a9312aStsutsui .new_state = ST_DELAYED_RIGHT, 244e8a9312aStsutsui }, 245e8a9312aStsutsui 246e8a9312aStsutsui .buttons[EMU_BUTTONS_BOTH] = { 247e8a9312aStsutsui /* left & right (middle press) -> pressed middle */ 248e8a9312aStsutsui .event1 = { ButtonPress, ButtonMiddle }, 249e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 250e8a9312aStsutsui .new_state = ST_PRESSED_MIDDLE, 251e8a9312aStsutsui }, 252e8a9312aStsutsui 253e8a9312aStsutsui .timeout = { 254e8a9312aStsutsui /* timeout (right press) -> pressed right */ 255e8a9312aStsutsui .event1 = { ButtonPress, ButtonRight }, 256e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 257e8a9312aStsutsui .new_state = ST_PRESSED_RIGHT, 258e8a9312aStsutsui }, 259e8a9312aStsutsui }, 260e8a9312aStsutsui 261e8a9312aStsutsui /* 3 pressed middle - right and left pressed, emulated middle sent */ 262e8a9312aStsutsui [ST_PRESSED_MIDDLE] = { 263e8a9312aStsutsui 264e8a9312aStsutsui .buttons[EMU_BUTTONS_NONE] = { 265e8a9312aStsutsui /* nothing (middle release) -> ground */ 266e8a9312aStsutsui .event1 = { ButtonRelease, ButtonMiddle }, 267e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 268e8a9312aStsutsui .new_state = ST_GROUND, 269e8a9312aStsutsui }, 270e8a9312aStsutsui 271e8a9312aStsutsui .buttons[EMU_BUTTONS_LEFT] = { 272e8a9312aStsutsui /* left -> released right */ 273e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 274e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 275e8a9312aStsutsui .new_state = ST_RELEASED_RIGHT, 276e8a9312aStsutsui }, 277e8a9312aStsutsui 278e8a9312aStsutsui .buttons[EMU_BUTTONS_RIGHT] = { 279e8a9312aStsutsui /* right -> released left */ 280e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 281e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 282e8a9312aStsutsui .new_state = ST_RELEASED_LEFT, 283e8a9312aStsutsui }, 284e8a9312aStsutsui 285e8a9312aStsutsui .buttons[EMU_BUTTONS_BOTH] = { 286e8a9312aStsutsui /* left & right -> pressed middle (no change) */ 287e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 288e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 289e8a9312aStsutsui .new_state = ST_PRESSED_MIDDLE, 290e8a9312aStsutsui }, 291e8a9312aStsutsui 292e8a9312aStsutsui .timeout = { 293e8a9312aStsutsui /* timeout N/A */ 294e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 295e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 296e8a9312aStsutsui .new_state = ST_INVALID, 297e8a9312aStsutsui }, 298e8a9312aStsutsui }, 299e8a9312aStsutsui 300e8a9312aStsutsui /* 4 pressed left - left pressed and sent */ 301e8a9312aStsutsui [ST_PRESSED_LEFT] = { 302e8a9312aStsutsui 303e8a9312aStsutsui .buttons[EMU_BUTTONS_NONE] = { 304e8a9312aStsutsui /* nothing (left release) -> ground */ 305e8a9312aStsutsui .event1 = { ButtonRelease, ButtonLeft }, 306e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 307e8a9312aStsutsui .new_state = ST_GROUND, 308e8a9312aStsutsui }, 309e8a9312aStsutsui 310e8a9312aStsutsui .buttons[EMU_BUTTONS_LEFT] = { 311e8a9312aStsutsui /* left -> pressed left (no change) */ 312e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 313e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 314e8a9312aStsutsui .new_state = ST_PRESSED_LEFT, 315e8a9312aStsutsui }, 316e8a9312aStsutsui 317e8a9312aStsutsui .buttons[EMU_BUTTONS_RIGHT] = { 318e8a9312aStsutsui /* right (left release) -> delayed right */ 319e8a9312aStsutsui .event1 = { ButtonRelease, ButtonLeft }, 320e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 321e8a9312aStsutsui .new_state = ST_DELAYED_RIGHT, 322e8a9312aStsutsui }, 323e8a9312aStsutsui 324e8a9312aStsutsui .buttons[EMU_BUTTONS_BOTH] = { 325e8a9312aStsutsui /* left & right (right press) -> pressed both */ 326e8a9312aStsutsui .event1 = { ButtonPress, ButtonRight }, 327e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 328e8a9312aStsutsui .new_state = ST_PRESSED_BOTH, 329e8a9312aStsutsui }, 330e8a9312aStsutsui 331e8a9312aStsutsui .timeout = { 332e8a9312aStsutsui /* timeout N/A */ 333e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 334e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 335e8a9312aStsutsui .new_state = ST_INVALID, 336e8a9312aStsutsui }, 337e8a9312aStsutsui }, 338e8a9312aStsutsui 339e8a9312aStsutsui /* 5 pressed right - right pressed and sent */ 340e8a9312aStsutsui [ST_PRESSED_RIGHT] = { 341e8a9312aStsutsui 342e8a9312aStsutsui .buttons[EMU_BUTTONS_NONE] = { 343e8a9312aStsutsui /* nothing (right release) -> ground */ 344e8a9312aStsutsui .event1 = { ButtonRelease, ButtonRight }, 345e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 346e8a9312aStsutsui .new_state = ST_GROUND, 347e8a9312aStsutsui }, 348e8a9312aStsutsui 349e8a9312aStsutsui .buttons[EMU_BUTTONS_LEFT] = { 350e8a9312aStsutsui /* left (right release) -> delayed left */ 351e8a9312aStsutsui .event1 = { ButtonRelease, ButtonRight }, 352e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 353e8a9312aStsutsui .new_state = ST_DELAYED_LEFT, 354e8a9312aStsutsui }, 355e8a9312aStsutsui 356e8a9312aStsutsui .buttons[EMU_BUTTONS_RIGHT] = { 357e8a9312aStsutsui /* right -> pressed right (no change) */ 358e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 359e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 360e8a9312aStsutsui .new_state = ST_PRESSED_RIGHT, 361e8a9312aStsutsui }, 362e8a9312aStsutsui 363e8a9312aStsutsui .buttons[EMU_BUTTONS_BOTH] = { 364e8a9312aStsutsui /* left & right (left press) -> pressed both */ 365e8a9312aStsutsui .event1 = { ButtonPress, ButtonLeft }, 366e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 367e8a9312aStsutsui .new_state = ST_PRESSED_BOTH, 368e8a9312aStsutsui }, 369e8a9312aStsutsui 370e8a9312aStsutsui .timeout = { 371e8a9312aStsutsui /* timeout N/A */ 372e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 373e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 374e8a9312aStsutsui .new_state = ST_INVALID, 375e8a9312aStsutsui }, 376e8a9312aStsutsui }, 377e8a9312aStsutsui 378e8a9312aStsutsui /* 6 released left - left released after emulated middle */ 379e8a9312aStsutsui [ST_RELEASED_LEFT] = { 380e8a9312aStsutsui 381e8a9312aStsutsui .buttons[EMU_BUTTONS_NONE] = { 382e8a9312aStsutsui /* nothing (middle release) -> ground */ 383e8a9312aStsutsui .event1 = { ButtonRelease, ButtonMiddle }, 384e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 385e8a9312aStsutsui .new_state = ST_GROUND, 386e8a9312aStsutsui }, 387e8a9312aStsutsui 388e8a9312aStsutsui .buttons[EMU_BUTTONS_LEFT] = { 389e8a9312aStsutsui /* left (middle release) -> delayed left */ 390e8a9312aStsutsui .event1 = { ButtonRelease, ButtonMiddle }, 391e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 392e8a9312aStsutsui .new_state = ST_DELAYED_LEFT, 393e8a9312aStsutsui }, 394e8a9312aStsutsui 395e8a9312aStsutsui .buttons[EMU_BUTTONS_RIGHT] = { 396e8a9312aStsutsui /* right -> released left (no change) */ 397e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 398e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 399e8a9312aStsutsui .new_state = ST_RELEASED_LEFT, 400e8a9312aStsutsui }, 401e8a9312aStsutsui 402e8a9312aStsutsui .buttons[EMU_BUTTONS_BOTH] = { 403e8a9312aStsutsui /* left & right (left press) -> repressed left */ 404e8a9312aStsutsui .event1 = { ButtonPress, ButtonLeft }, 405e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 406e8a9312aStsutsui .new_state = ST_REPRESSED_LEFT, 407e8a9312aStsutsui }, 408e8a9312aStsutsui 409e8a9312aStsutsui .timeout = { 410e8a9312aStsutsui /* timeout N/A */ 411e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 412e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 413e8a9312aStsutsui .new_state = ST_INVALID, 414e8a9312aStsutsui }, 415e8a9312aStsutsui }, 416e8a9312aStsutsui 417e8a9312aStsutsui /* 7 released right - right released after emulated middle */ 418e8a9312aStsutsui [ST_RELEASED_RIGHT] = { 419e8a9312aStsutsui 420e8a9312aStsutsui .buttons[EMU_BUTTONS_NONE] = { 421e8a9312aStsutsui /* nothing (middle release) -> ground */ 422e8a9312aStsutsui .event1 = { ButtonRelease, ButtonMiddle }, 423e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 424e8a9312aStsutsui .new_state = ST_GROUND, 425e8a9312aStsutsui }, 426e8a9312aStsutsui 427e8a9312aStsutsui .buttons[EMU_BUTTONS_LEFT] = { 428e8a9312aStsutsui /* left -> released right (no change) */ 429e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 430e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 431e8a9312aStsutsui .new_state = ST_RELEASED_RIGHT, 432e8a9312aStsutsui }, 433e8a9312aStsutsui 434e8a9312aStsutsui .buttons[EMU_BUTTONS_RIGHT] = { 435e8a9312aStsutsui /* right (middle release) -> delayed right */ 436e8a9312aStsutsui .event1 = { ButtonRelease, ButtonMiddle }, 437e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 438e8a9312aStsutsui .new_state = ST_DELAYED_RIGHT, 439e8a9312aStsutsui }, 440e8a9312aStsutsui 441e8a9312aStsutsui .buttons[EMU_BUTTONS_BOTH] = { 442e8a9312aStsutsui /* left & right (right press) -> repressed right */ 443e8a9312aStsutsui .event1 = { ButtonPress, ButtonRight }, 444e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 445e8a9312aStsutsui .new_state = ST_REPRESSED_RIGHT, 446e8a9312aStsutsui }, 447e8a9312aStsutsui 448e8a9312aStsutsui .timeout = { 449e8a9312aStsutsui /* timeout N/A */ 450e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 451e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 452e8a9312aStsutsui .new_state = ST_INVALID, 453e8a9312aStsutsui }, 454e8a9312aStsutsui }, 455e8a9312aStsutsui 456e8a9312aStsutsui /* 8 repressed left - left pressed after released left */ 457e8a9312aStsutsui [ST_REPRESSED_LEFT] = { 458e8a9312aStsutsui 459e8a9312aStsutsui .buttons[EMU_BUTTONS_NONE] = { 460e8a9312aStsutsui /* nothing (middle release, left release) -> ground */ 461e8a9312aStsutsui .event1 = { ButtonRelease, ButtonMiddle }, 462e8a9312aStsutsui .event2 = { ButtonRelease, ButtonLeft }, 463e8a9312aStsutsui .new_state = ST_GROUND, 464e8a9312aStsutsui }, 465e8a9312aStsutsui 466e8a9312aStsutsui .buttons[EMU_BUTTONS_LEFT] = { 467e8a9312aStsutsui /* left (middle release) -> pressed left */ 468e8a9312aStsutsui .event1 = { ButtonRelease, ButtonMiddle }, 469e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 470e8a9312aStsutsui .new_state = ST_PRESSED_LEFT, 471e8a9312aStsutsui }, 472e8a9312aStsutsui 473e8a9312aStsutsui .buttons[EMU_BUTTONS_RIGHT] = { 474e8a9312aStsutsui /* right (left release) -> released left */ 475e8a9312aStsutsui .event1 = { ButtonRelease, ButtonLeft }, 476e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 477e8a9312aStsutsui .new_state = ST_RELEASED_LEFT, 478e8a9312aStsutsui }, 479e8a9312aStsutsui 480e8a9312aStsutsui .buttons[EMU_BUTTONS_BOTH] = { 481e8a9312aStsutsui /* left & right -> repressed left (no change) */ 482e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 483e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 484e8a9312aStsutsui .new_state = ST_REPRESSED_LEFT, 485e8a9312aStsutsui }, 486e8a9312aStsutsui 487e8a9312aStsutsui .timeout = { 488e8a9312aStsutsui /* timeout N/A */ 489e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 490e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 491e8a9312aStsutsui .new_state = ST_INVALID, 492e8a9312aStsutsui }, 493e8a9312aStsutsui }, 494e8a9312aStsutsui 495e8a9312aStsutsui /* 9 repressed right - right pressed after released right */ 496e8a9312aStsutsui [ST_REPRESSED_RIGHT] = { 497e8a9312aStsutsui 498e8a9312aStsutsui .buttons[EMU_BUTTONS_NONE] = { 499e8a9312aStsutsui /* nothing (middle release, right release) -> ground */ 500e8a9312aStsutsui .event1 = { ButtonRelease, ButtonMiddle }, 501e8a9312aStsutsui .event2 = { ButtonRelease, ButtonRight }, 502e8a9312aStsutsui .new_state = ST_GROUND, 503e8a9312aStsutsui }, 504e8a9312aStsutsui 505e8a9312aStsutsui .buttons[EMU_BUTTONS_LEFT] = { 506e8a9312aStsutsui /* left (right release) -> released right */ 507e8a9312aStsutsui .event1 = { ButtonRelease, ButtonRight }, 508e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 509e8a9312aStsutsui .new_state = ST_RELEASED_RIGHT, 510e8a9312aStsutsui }, 511e8a9312aStsutsui 512e8a9312aStsutsui .buttons[EMU_BUTTONS_RIGHT] = { 513e8a9312aStsutsui /* right (middle release) -> pressed right */ 514e8a9312aStsutsui .event1 = { ButtonRelease, ButtonMiddle }, 515e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 516e8a9312aStsutsui .new_state = ST_PRESSED_RIGHT, 517e8a9312aStsutsui }, 518e8a9312aStsutsui 519e8a9312aStsutsui .buttons[EMU_BUTTONS_BOTH] = { 520e8a9312aStsutsui /* left & right -> repressed right (no change) */ 521e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 522e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 523e8a9312aStsutsui .new_state = ST_REPRESSED_RIGHT, 524e8a9312aStsutsui }, 525e8a9312aStsutsui 526e8a9312aStsutsui .timeout = { 527e8a9312aStsutsui /* timeout N/A */ 528e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 529e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 530e8a9312aStsutsui .new_state = ST_INVALID, 531e8a9312aStsutsui }, 532e8a9312aStsutsui }, 533e8a9312aStsutsui 534e8a9312aStsutsui /* 10 pressed both - both pressed, not emulating middle */ 535e8a9312aStsutsui [ST_PRESSED_BOTH] = { 536e8a9312aStsutsui 537e8a9312aStsutsui .buttons[EMU_BUTTONS_NONE] = { 538e8a9312aStsutsui /* nothing (left release, right release) -> ground */ 539e8a9312aStsutsui .event1 = { ButtonRelease, ButtonLeft }, 540e8a9312aStsutsui .event2 = { ButtonRelease, ButtonRight }, 541e8a9312aStsutsui .new_state = ST_GROUND, 542e8a9312aStsutsui }, 543e8a9312aStsutsui 544e8a9312aStsutsui .buttons[EMU_BUTTONS_LEFT] = { 545e8a9312aStsutsui /* left (right release) -> pressed left */ 546e8a9312aStsutsui .event1 = { ButtonRelease, ButtonRight }, 547e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 548e8a9312aStsutsui .new_state = ST_PRESSED_LEFT, 549e8a9312aStsutsui }, 550e8a9312aStsutsui 551e8a9312aStsutsui .buttons[EMU_BUTTONS_RIGHT] = { 552e8a9312aStsutsui /* right (left release) -> pressed right */ 553e8a9312aStsutsui .event1 = { ButtonRelease, ButtonLeft }, 554e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 555e8a9312aStsutsui .new_state = ST_PRESSED_RIGHT, 556e8a9312aStsutsui }, 557e8a9312aStsutsui 558e8a9312aStsutsui .buttons[EMU_BUTTONS_BOTH] = { 559e8a9312aStsutsui /* left & right -> pressed both (no change) */ 560e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 561e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 562e8a9312aStsutsui .new_state = ST_PRESSED_BOTH, 563e8a9312aStsutsui }, 564e8a9312aStsutsui 565e8a9312aStsutsui .timeout = { 566e8a9312aStsutsui /* timeout N/A */ 567e8a9312aStsutsui .event1 = { ButtonNone, 0 }, 568e8a9312aStsutsui .event2 = { ButtonNone, 0 }, 569e8a9312aStsutsui .new_state = ST_INVALID, 570e8a9312aStsutsui }, 571e8a9312aStsutsui }, 572e8a9312aStsutsui}; 573e8a9312aStsutsui 574e8a9312aStsutsuistatic CARD32 575e8a9312aStsutsuibuttonTimer(MouseEmu3btnPtr pEmu3btn) 576e8a9312aStsutsui{ 577e8a9312aStsutsui int type, button, flag; 578e8a9312aStsutsui ValuatorMask mask; 579e8a9312aStsutsui const struct button_action *timeout_action; 580e8a9312aStsutsui 5811406604bStsutsui input_lock(); 582e8a9312aStsutsui 583e8a9312aStsutsui pEmu3btn->emulate3Pending = FALSE; 584e8a9312aStsutsui timeout_action = &stateTab[pEmu3btn->emulateState].timeout; 585e8a9312aStsutsui if ((type = timeout_action->event1.type) != ButtonNone) { 586e8a9312aStsutsui button = timeout_action->event1.button; 587e8a9312aStsutsui flag = POINTER_RELATIVE; 588e8a9312aStsutsui valuator_mask_zero(&mask); 589e8a9312aStsutsui QueuePointerEvents(pEmu3btn->device, type, button, flag, &mask); 590e8a9312aStsutsui pEmu3btn->emulateState = timeout_action->new_state; 591e8a9312aStsutsui } else { 592e8a9312aStsutsui LogMessageVerbSigSafe(X_WARNING, -1, 593e8a9312aStsutsui "Got unexpected buttonTimer in state %d\n", pEmu3btn->emulateState); 594e8a9312aStsutsui } 595e8a9312aStsutsui 5961406604bStsutsui input_unlock(); 597e8a9312aStsutsui return 0; 598e8a9312aStsutsui} 599e8a9312aStsutsui 600e8a9312aStsutsuistatic void 601e8a9312aStsutsuiEmulate3ButtonsSetEnabled(MouseEmu3btnPtr pEmu3btn, Bool enable) 602e8a9312aStsutsui{ 603e8a9312aStsutsui 604e8a9312aStsutsui if (pEmu3btn->emulate3Buttons == enable) 605e8a9312aStsutsui return; 606e8a9312aStsutsui 607e8a9312aStsutsui pEmu3btn->emulate3Buttons = enable; 608e8a9312aStsutsui 609e8a9312aStsutsui if (enable) { 610e8a9312aStsutsui pEmu3btn->emulateState = ST_GROUND; 611e8a9312aStsutsui pEmu3btn->emulate3Pending = FALSE; 612e8a9312aStsutsui pEmu3btn->emulate3ButtonsSoft = FALSE; /* specifically requested now */ 613e8a9312aStsutsui 614e8a9312aStsutsui RegisterBlockAndWakeupHandlers(MouseBlockHandler, MouseWakeupHandler, 615e8a9312aStsutsui (void *)pEmu3btn); 616e8a9312aStsutsui } else { 617e8a9312aStsutsui if (pEmu3btn->emulate3Pending) 618e8a9312aStsutsui buttonTimer(pEmu3btn); 619e8a9312aStsutsui 620e8a9312aStsutsui RemoveBlockAndWakeupHandlers(MouseBlockHandler, MouseWakeupHandler, 621e8a9312aStsutsui (void *)pEmu3btn); 622e8a9312aStsutsui } 623e8a9312aStsutsui} 624e8a9312aStsutsui 625e8a9312aStsutsuistatic Bool 626e8a9312aStsutsuiEmulate3ButtonsSoft(MouseEmu3btnPtr pEmu3btn) 627e8a9312aStsutsui{ 628e8a9312aStsutsui 629e8a9312aStsutsui if (!pEmu3btn->emulate3ButtonsSoft) 630e8a9312aStsutsui return TRUE; 631e8a9312aStsutsui 632e8a9312aStsutsui#if defined(__NetBSD__) && defined(WSCONS_SUPPORT) 633e8a9312aStsutsui /* 634e8a9312aStsutsui * On NetBSD a wsmouse is a multiplexed device. Imagine a notebook 635e8a9312aStsutsui * with two-button mousepad, and an external USB mouse plugged in 636e8a9312aStsutsui * temporarily. After using button 3 on the external mouse and 637e8a9312aStsutsui * unplugging it again, the mousepad will still need to emulate 638e8a9312aStsutsui * 3 buttons. 639e8a9312aStsutsui */ 640e8a9312aStsutsui return TRUE; 641e8a9312aStsutsui#else 642e8a9312aStsutsui LogMessageVerbSigSafe(X_INFO, 4, 643e8a9312aStsutsui "mouse: 3rd Button detected: disabling emulate3Button\n"); 644e8a9312aStsutsui 645e8a9312aStsutsui Emulate3ButtonsSetEnabled(pEmu3btn, FALSE); 646e8a9312aStsutsui 647e8a9312aStsutsui return FALSE; 648e8a9312aStsutsui#endif 649e8a9312aStsutsui} 650e8a9312aStsutsui 651e8a9312aStsutsuistatic void 652e8a9312aStsutsuiMouseBlockHandler(void *data, void *waitTime) 653e8a9312aStsutsui{ 654e8a9312aStsutsui MouseEmu3btnPtr pEmu3btn = data; 655e8a9312aStsutsui int ms; 656e8a9312aStsutsui 657e8a9312aStsutsui if (pEmu3btn->emulate3Pending) { 658e8a9312aStsutsui ms = pEmu3btn->emulate3Expires - GetTimeInMillis(); 659e8a9312aStsutsui if (ms <= 0) 660e8a9312aStsutsui ms = 0; 661e8a9312aStsutsui AdjustWaitForDelay(waitTime, ms); 662e8a9312aStsutsui } 663e8a9312aStsutsui} 664e8a9312aStsutsui 665e8a9312aStsutsuistatic void 666e8a9312aStsutsuiMouseWakeupHandler(void *data, int i) 667e8a9312aStsutsui{ 668e8a9312aStsutsui MouseEmu3btnPtr pEmu3btn = data; 669e8a9312aStsutsui int ms; 670e8a9312aStsutsui 671e8a9312aStsutsui if (pEmu3btn->emulate3Pending) { 672e8a9312aStsutsui ms = pEmu3btn->emulate3Expires - GetTimeInMillis(); 673e8a9312aStsutsui if (ms <= 0) 674e8a9312aStsutsui buttonTimer(pEmu3btn); 675e8a9312aStsutsui } 676e8a9312aStsutsui} 677e8a9312aStsutsui 678e8a9312aStsutsui/******************************************************************* 679e8a9312aStsutsui * function "Emulate3ButtonsEnable" 680e8a9312aStsutsui * 681e8a9312aStsutsui * purpose: 682e8a9312aStsutsui * Enable and initialize Emulate3Buttons structures. 683e8a9312aStsutsui * argument: 684e8a9312aStsutsui * (MouseEmu3btnPtr)pEmu3btn : Emu3btn private record 685e8a9312aStsutsui * (DeviceIntPtr)device : pointer device private record 686e8a9312aStsutsui * (int)timeout : timeout to wait another button [ms] 687e8a9312aStsutsui * 688e8a9312aStsutsui *******************************************************************/ 689e8a9312aStsutsuivoid 690e8a9312aStsutsuiEmulate3ButtonsEnable(MouseEmu3btnPtr pEmu3btn, DeviceIntPtr device, int timeout) 691e8a9312aStsutsui{ 692e8a9312aStsutsui 693e8a9312aStsutsui BUG_RETURN_MSG(device == NULL, "Invalid DeviceIntPtr.\n"); 694e8a9312aStsutsui 695e8a9312aStsutsui if (timeout <= 0) { 696e8a9312aStsutsui timeout = EMU3B_DEF_TIMEOUT; 697e8a9312aStsutsui } 698e8a9312aStsutsui pEmu3btn->device = device; 699e8a9312aStsutsui pEmu3btn->emulate3Timeout = timeout; 700e8a9312aStsutsui 701e8a9312aStsutsui Emulate3ButtonsSetEnabled(pEmu3btn, TRUE); 702e8a9312aStsutsui} 703e8a9312aStsutsui 704e8a9312aStsutsui/******************************************************************* 705e8a9312aStsutsui * function "Emulate3ButtonsQueueEvent" 706e8a9312aStsutsui * 707e8a9312aStsutsui * purpose: 708e8a9312aStsutsui * Emulate middle button per left/right button events and post events. 709e8a9312aStsutsui * argument: 710e8a9312aStsutsui * (MouseEmu3btnPtr)pEmu3btn : Emu3btn private record 711e8a9312aStsutsui * (int)type : event (ButtonPress / ButtonRelease) 712e8a9312aStsutsui * (int)buttons : button (Button1 / Button2 / Button3) 713e8a9312aStsutsui * (int)bmask : buttons being pressed (0x1:left / 0x4:right) 714e8a9312aStsutsui * 715e8a9312aStsutsui *******************************************************************/ 716e8a9312aStsutsui 717e8a9312aStsutsuivoid 718e8a9312aStsutsuiEmulate3ButtonsQueueEvent(MouseEmu3btnPtr pEmu3btn, int type, int buttons, int bmask) 719e8a9312aStsutsui{ 720e8a9312aStsutsui DeviceIntPtr device = pEmu3btn->device; 721e8a9312aStsutsui int emulateButtons; 722e8a9312aStsutsui int button, flag; 723e8a9312aStsutsui ValuatorMask mask; 724e8a9312aStsutsui 725e8a9312aStsutsui BUG_RETURN_MSG(buttons != ButtonLeft && buttons != ButtonRight, 726e8a9312aStsutsui "not left or right button event\n"); 727e8a9312aStsutsui 728e8a9312aStsutsui if (pEmu3btn->emulate3ButtonsSoft && pEmu3btn->emulate3Pending) 729e8a9312aStsutsui buttonTimer(pEmu3btn); 730e8a9312aStsutsui 731e8a9312aStsutsui if (pEmu3btn->emulate3Buttons 732e8a9312aStsutsui && ((bmask & BMASK_MIDDLE) == 0 || Emulate3ButtonsSoft(pEmu3btn))) { 733e8a9312aStsutsui const struct button_action *button_action, *timeout_action; 734e8a9312aStsutsui 735e8a9312aStsutsui /* emulate the third button by the other two */ 736e8a9312aStsutsui 737e8a9312aStsutsui emulateButtons = BMASKTOINDEX(bmask); 738e8a9312aStsutsui button_action = 739e8a9312aStsutsui &stateTab[pEmu3btn->emulateState].buttons[emulateButtons]; 740e8a9312aStsutsui 741e8a9312aStsutsui if ((type = button_action->event1.type) != ButtonNone) { 742e8a9312aStsutsui button = button_action->event1.button; 743e8a9312aStsutsui flag = POINTER_RELATIVE; 744e8a9312aStsutsui valuator_mask_zero(&mask); 745e8a9312aStsutsui QueuePointerEvents(device, type, button, flag, &mask); 746e8a9312aStsutsui } 747e8a9312aStsutsui if ((type = button_action->event2.type) != ButtonNone) { 748e8a9312aStsutsui button = button_action->event2.button; 749e8a9312aStsutsui flag = POINTER_RELATIVE; 750e8a9312aStsutsui valuator_mask_zero(&mask); 751e8a9312aStsutsui QueuePointerEvents(device, type, button, flag, &mask); 752e8a9312aStsutsui } 753e8a9312aStsutsui 754e8a9312aStsutsui pEmu3btn->emulateState = button_action->new_state; 755e8a9312aStsutsui 756e8a9312aStsutsui timeout_action = &stateTab[pEmu3btn->emulateState].timeout; 757e8a9312aStsutsui if (timeout_action->event1.type != ButtonNone) { 758e8a9312aStsutsui pEmu3btn->emulate3Expires = 759e8a9312aStsutsui GetTimeInMillis() + pEmu3btn->emulate3Timeout; 760e8a9312aStsutsui pEmu3btn->emulate3Pending = TRUE; 761e8a9312aStsutsui } else { 762e8a9312aStsutsui pEmu3btn->emulate3Pending = FALSE; 763e8a9312aStsutsui } 764e8a9312aStsutsui } else { 765e8a9312aStsutsui /* no emulation; post left or right button event as is */ 766e8a9312aStsutsui flag = POINTER_RELATIVE; 767e8a9312aStsutsui valuator_mask_zero(&mask); 768e8a9312aStsutsui QueuePointerEvents(device, type, buttons, flag, &mask); 769e8a9312aStsutsui } 770e8a9312aStsutsui} 771