Initial commit
[xorg_rtime.git] / xorg-server-1.4 / hw / xwin / winmouse.c
blob1507dd34f815697d0486c0833658498302974aed
1 /*
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
29 * Suhaib M Siddiqi
30 * Peter Busch
31 * Harold L Hunt II
34 #ifdef HAVE_XWIN_CONFIG_H
35 #include <xwin-config.h>
36 #endif
37 #include "win.h"
39 #if defined(XFree86Server) && defined(XINPUT)
40 #include "inputstr.h"
42 /* Peek the internal button mapping */
43 static CARD8 const *g_winMouseButtonMap = NULL;
44 #endif
48 * Local prototypes
51 static void
52 winMouseCtrl (DeviceIntPtr pDevice, PtrCtrl *pCtrl);
55 static void
56 winMouseCtrl (DeviceIntPtr pDevice, PtrCtrl *pCtrl)
62 * See Porting Layer Definition - p. 18
63 * This is known as a DeviceProc
66 int
67 winMouseProc (DeviceIntPtr pDeviceInt, int iState)
69 int lngMouseButtons, i;
70 int lngWheelEvents = 2;
71 CARD8 *map;
72 DevicePtr pDevice = (DevicePtr) pDeviceInt;
74 switch (iState)
76 case DEVICE_INIT:
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)
88 lngMouseButtons = 3;
89 winMsg(X_PROBED, "%d mouse buttons found\n", lngMouseButtons);
91 /* allocate memory:
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 */
97 map[0] = 0;
98 for (i=1; i <= lngMouseButtons + lngWheelEvents; i++)
99 map[i] = i;
100 InitPointerDeviceStruct (pDevice,
101 map,
102 lngMouseButtons + lngWheelEvents,
103 GetMotionHistory,
104 winMouseCtrl,
105 GetMotionHistorySize(),
107 free(map);
109 #if defined(XFree86Server) && defined(XINPUT)
110 g_winMouseButtonMap = pDeviceInt->button->map;
111 #endif
112 break;
114 case DEVICE_ON:
115 pDevice->on = TRUE;
116 break;
118 case DEVICE_CLOSE:
119 #if defined(XFree86Server) && defined(XINPUT)
120 g_winMouseButtonMap = NULL;
121 #endif
122 case DEVICE_OFF:
123 pDevice->on = FALSE;
124 break;
126 return Success;
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
142 && iDeltaZ > 0)
143 || (pScreenPriv->iDeltaZ < 0
144 && iDeltaZ < 0))
146 /* Previous delta and of same sign as current delta */
147 iDeltaZ += pScreenPriv->iDeltaZ;
148 pScreenPriv->iDeltaZ = 0;
150 else
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
163 * WHEEL_DELTA
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;
172 else
175 * Wheel has not moved past WHEEL_DELTA threshold;
176 * we will store the wheel delta until the threshold
177 * has been reached.
179 pScreenPriv->iDeltaZ = iDeltaZ;
180 return 0;
183 /* Set the button to indicate up or down wheel delta */
184 if (iDeltaZ > 0)
186 button = Button4;
188 else
190 button = Button5;
194 * Flip iDeltaZ to positive, if negative,
195 * because always need to generate a *positive* number of
196 * button clicks for the Z axis.
198 if (iDeltaZ < 0)
200 iDeltaZ *= -1;
203 /* Generate X input messages for each wheel delta we have seen */
204 while (iDeltaZ--)
206 /* Push the wheel button */
207 winMouseButtonsSendEvent (ButtonPress, button);
209 /* Release the wheel button */
210 winMouseButtonsSendEvent (ButtonRelease, button);
213 return 0;
218 * Enqueue a mouse button event
221 void
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];
231 else
232 #endif
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,
247 WPARAM wParam)
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);
257 return 0;
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,
278 WIN_E3B_TIMER_ID,
279 pScreenInfo->iE3BTimeout,
280 NULL);
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);
340 return 0;