2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
4 *Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 *"Software"), to deal in the Software without restriction, including
7 *without limitation the rights to use, copy, modify, merge, publish,
8 *distribute, sublicense, and/or sell copies of the Software, and to
9 *permit persons to whom the Software is furnished to do so, subject to
10 *the following conditions:
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *Except as contained in this notice, the name of the XFree86 Project
24 *shall not be used in advertising or otherwise to promote the sale, use
25 *or other dealings in this Software without prior written authorization
26 *from the XFree86 Project.
28 * Authors: Dakshinamurthy Karra
34 #ifdef HAVE_XWIN_CONFIG_H
35 #include <xwin-config.h>
39 #if defined(XFree86Server) && defined(XINPUT)
42 /* Peek the internal button mapping */
43 static CARD8
const *g_winMouseButtonMap
= NULL
;
52 winMouseCtrl (DeviceIntPtr pDevice
, PtrCtrl
*pCtrl
);
56 winMouseCtrl (DeviceIntPtr pDevice
, PtrCtrl
*pCtrl
)
62 * See Porting Layer Definition - p. 18
63 * This is known as a DeviceProc
67 winMouseProc (DeviceIntPtr pDeviceInt
, int iState
)
69 int lngMouseButtons
, i
;
70 int lngWheelEvents
= 2;
72 DevicePtr pDevice
= (DevicePtr
) pDeviceInt
;
77 /* Get number of mouse buttons */
78 lngMouseButtons
= GetSystemMetrics(SM_CMOUSEBUTTONS
);
80 /* Mapping of windows events to X events:
81 * LEFT:1 MIDDLE:2 RIGHT:3
82 * SCROLL_UP:4 SCROLL_DOWN:5
83 * XBUTTON 1:6 XBUTTON 2:7 ...
85 * To map scroll wheel correctly we need at least the 3 normal buttons
87 if (lngMouseButtons
< 3)
89 winMsg(X_PROBED
, "%d mouse buttons found\n", lngMouseButtons
);
92 * number of buttons + 2x mouse wheel event + 1 extra (offset for map)
94 map
= malloc(sizeof(CARD8
) * (lngMouseButtons
+ lngWheelEvents
+ 1));
96 /* initalize button map */
98 for (i
=1; i
<= lngMouseButtons
+ lngWheelEvents
; i
++)
100 InitPointerDeviceStruct (pDevice
,
102 lngMouseButtons
+ lngWheelEvents
,
105 GetMotionHistorySize(),
109 #if defined(XFree86Server) && defined(XINPUT)
110 g_winMouseButtonMap
= pDeviceInt
->button
->map
;
119 #if defined(XFree86Server) && defined(XINPUT)
120 g_winMouseButtonMap
= NULL
;
130 /* Handle the mouse wheel */
132 winMouseWheel (ScreenPtr pScreen
, int iDeltaZ
)
134 winScreenPriv(pScreen
);
135 int button
; /* Button4 or Button5 */
137 /* Button4 = WheelUp */
138 /* Button5 = WheelDown */
140 /* Do we have any previous delta stored? */
141 if ((pScreenPriv
->iDeltaZ
> 0
143 || (pScreenPriv
->iDeltaZ
< 0
146 /* Previous delta and of same sign as current delta */
147 iDeltaZ
+= pScreenPriv
->iDeltaZ
;
148 pScreenPriv
->iDeltaZ
= 0;
153 * Previous delta of different sign, or zero.
154 * We will set it to zero for either case,
155 * as blindly setting takes just as much time
156 * as checking, then setting if necessary :)
158 pScreenPriv
->iDeltaZ
= 0;
162 * Only process this message if the wheel has moved further than
165 if (iDeltaZ
>= WHEEL_DELTA
|| (-1 * iDeltaZ
) >= WHEEL_DELTA
)
167 pScreenPriv
->iDeltaZ
= 0;
169 /* Figure out how many whole deltas of the wheel we have */
170 iDeltaZ
/= WHEEL_DELTA
;
175 * Wheel has not moved past WHEEL_DELTA threshold;
176 * we will store the wheel delta until the threshold
179 pScreenPriv
->iDeltaZ
= iDeltaZ
;
183 /* Set the button to indicate up or down wheel delta */
194 * Flip iDeltaZ to positive, if negative,
195 * because always need to generate a *positive* number of
196 * button clicks for the Z axis.
203 /* Generate X input messages for each wheel delta we have seen */
206 /* Push the wheel button */
207 winMouseButtonsSendEvent (ButtonPress
, button
);
209 /* Release the wheel button */
210 winMouseButtonsSendEvent (ButtonRelease
, button
);
218 * Enqueue a mouse button event
222 winMouseButtonsSendEvent (int iEventType
, int iButton
)
224 xEvent xCurrentEvent
;
226 /* Load an xEvent and enqueue the event */
227 xCurrentEvent
.u
.u
.type
= iEventType
;
228 #if defined(XFree86Server) && defined(XINPUT)
229 if (g_winMouseButtonMap
)
230 xCurrentEvent
.u
.u
.detail
= g_winMouseButtonMap
[iButton
];
233 xCurrentEvent
.u
.u
.detail
= iButton
;
234 xCurrentEvent
.u
.keyButtonPointer
.time
235 = g_c32LastInputEventTime
= GetTickCount ();
236 mieqEnqueue (&xCurrentEvent
);
241 * Decide what to do with a Windows mouse message
245 winMouseButtonsHandle (ScreenPtr pScreen
,
246 int iEventType
, int iButton
,
249 winScreenPriv(pScreen
);
250 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
252 /* Send button events right away if emulate 3 buttons is off */
253 if (pScreenInfo
->iE3BTimeout
== WIN_E3B_OFF
)
255 /* Emulate 3 buttons is off, send the button event */
256 winMouseButtonsSendEvent (iEventType
, iButton
);
260 /* Emulate 3 buttons is on, let the fun begin */
261 if (iEventType
== ButtonPress
262 && pScreenPriv
->iE3BCachedPress
== 0
263 && !pScreenPriv
->fE3BFakeButton2Sent
)
266 * Button was pressed, no press is cached,
267 * and there is no fake button 2 release pending.
270 /* Store button press type */
271 pScreenPriv
->iE3BCachedPress
= iButton
;
274 * Set a timer to send this button press if the other button
275 * is not pressed within the timeout time.
277 SetTimer (pScreenPriv
->hwndScreen
,
279 pScreenInfo
->iE3BTimeout
,
282 else if (iEventType
== ButtonPress
283 && pScreenPriv
->iE3BCachedPress
!= 0
284 && pScreenPriv
->iE3BCachedPress
!= iButton
285 && !pScreenPriv
->fE3BFakeButton2Sent
)
288 * Button press is cached, other button was pressed,
289 * and there is no fake button 2 release pending.
292 /* Mouse button was cached and other button was pressed */
293 KillTimer (pScreenPriv
->hwndScreen
, WIN_E3B_TIMER_ID
);
294 pScreenPriv
->iE3BCachedPress
= 0;
296 /* Send fake middle button */
297 winMouseButtonsSendEvent (ButtonPress
, Button2
);
299 /* Indicate that a fake middle button event was sent */
300 pScreenPriv
->fE3BFakeButton2Sent
= TRUE
;
302 else if (iEventType
== ButtonRelease
303 && pScreenPriv
->iE3BCachedPress
== iButton
)
306 * Cached button was released before timer ran out,
307 * and before the other mouse button was pressed.
309 KillTimer (pScreenPriv
->hwndScreen
, WIN_E3B_TIMER_ID
);
310 pScreenPriv
->iE3BCachedPress
= 0;
312 /* Send cached press, then send release */
313 winMouseButtonsSendEvent (ButtonPress
, iButton
);
314 winMouseButtonsSendEvent (ButtonRelease
, iButton
);
316 else if (iEventType
== ButtonRelease
317 && pScreenPriv
->fE3BFakeButton2Sent
318 && !(wParam
& MK_LBUTTON
)
319 && !(wParam
& MK_RBUTTON
))
322 * Fake button 2 was sent and both mouse buttons have now been released
324 pScreenPriv
->fE3BFakeButton2Sent
= FALSE
;
326 /* Send middle mouse button release */
327 winMouseButtonsSendEvent (ButtonRelease
, Button2
);
329 else if (iEventType
== ButtonRelease
330 && pScreenPriv
->iE3BCachedPress
== 0
331 && !pScreenPriv
->fE3BFakeButton2Sent
)
334 * Button was release, no button is cached,
335 * and there is no fake button 2 release is pending.
337 winMouseButtonsSendEvent (ButtonRelease
, iButton
);