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