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)
41 #include "exevents.h" /* for button/axes labels */
42 #include "xserver-properties.h"
44 /* Peek the internal button mapping */
45 static CARD8 const *g_winMouseButtonMap = NULL;
54 winMouseCtrl (DeviceIntPtr pDevice, PtrCtrl *pCtrl);
58 winMouseCtrl (DeviceIntPtr pDevice, PtrCtrl *pCtrl)
64 * See Porting Layer Definition - p. 18
65 * This is known as a DeviceProc
69 winMouseProc (DeviceIntPtr pDeviceInt, int iState)
71 int lngMouseButtons, i;
72 int lngWheelEvents = 2;
74 DevicePtr pDevice = (DevicePtr) pDeviceInt;
81 /* Get number of mouse buttons */
82 lngMouseButtons = GetSystemMetrics(SM_CMOUSEBUTTONS);
84 /* Mapping of windows events to X events:
85 * LEFT:1 MIDDLE:2 RIGHT:3
86 * SCROLL_UP:4 SCROLL_DOWN:5
87 * XBUTTON 1:6 XBUTTON 2:7 ...
89 * To map scroll wheel correctly we need at least the 3 normal buttons
91 if (lngMouseButtons < 3)
93 winMsg(X_PROBED, "%d mouse buttons found\n", lngMouseButtons);
96 * number of buttons + 2x mouse wheel event + 1 extra (offset for map)
98 map = malloc(sizeof(CARD8) * (lngMouseButtons + lngWheelEvents + 1));
100 /* initalize button map */
102 for (i=1; i <= lngMouseButtons + lngWheelEvents; i++)
105 btn_labels = calloc((lngMouseButtons + lngWheelEvents), sizeof(Atom));
106 btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
107 btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
108 btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
109 btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
110 btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
112 axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
113 axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
115 InitPointerDeviceStruct (pDevice,
117 lngMouseButtons + lngWheelEvents,
120 GetMotionHistorySize(),
126 #if defined(XFree86Server)
127 g_winMouseButtonMap = pDeviceInt->button->map;
136 #if defined(XFree86Server)
137 g_winMouseButtonMap = NULL;
147 /* Handle the mouse wheel */
149 winMouseWheel (ScreenPtr pScreen, int iDeltaZ)
151 winScreenPriv(pScreen);
152 int button; /* Button4 or Button5 */
154 /* Button4 = WheelUp */
155 /* Button5 = WheelDown */
157 /* Do we have any previous delta stored? */
158 if ((pScreenPriv->iDeltaZ > 0
160 || (pScreenPriv->iDeltaZ < 0
163 /* Previous delta and of same sign as current delta */
164 iDeltaZ += pScreenPriv->iDeltaZ;
165 pScreenPriv->iDeltaZ = 0;
170 * Previous delta of different sign, or zero.
171 * We will set it to zero for either case,
172 * as blindly setting takes just as much time
173 * as checking, then setting if necessary :)
175 pScreenPriv->iDeltaZ = 0;
179 * Only process this message if the wheel has moved further than
182 if (iDeltaZ >= WHEEL_DELTA || (-1 * iDeltaZ) >= WHEEL_DELTA)
184 pScreenPriv->iDeltaZ = 0;
186 /* Figure out how many whole deltas of the wheel we have */
187 iDeltaZ /= WHEEL_DELTA;
192 * Wheel has not moved past WHEEL_DELTA threshold;
193 * we will store the wheel delta until the threshold
196 pScreenPriv->iDeltaZ = iDeltaZ;
200 /* Set the button to indicate up or down wheel delta */
211 * Flip iDeltaZ to positive, if negative,
212 * because always need to generate a *positive* number of
213 * button clicks for the Z axis.
220 /* Generate X input messages for each wheel delta we have seen */
223 /* Push the wheel button */
224 winMouseButtonsSendEvent (ButtonPress, button);
226 /* Release the wheel button */
227 winMouseButtonsSendEvent (ButtonRelease, button);
235 * Enqueue a mouse button event
239 winMouseButtonsSendEvent (int iEventType, int iButton)
244 #if defined(XFree86Server)
245 if (g_winMouseButtonMap)
246 iButton = g_winMouseButtonMap[iButton];
249 GetEventList(&events);
250 nevents = GetPointerEvents(events, g_pwinPointer, iEventType, iButton,
251 POINTER_RELATIVE, 0, 0, NULL);
253 for (i = 0; i < nevents; i++)
254 mieqEnqueue(g_pwinPointer, events[i].event);
257 ErrorF("winMouseButtonsSendEvent: iEventType: %d, iButton: %d, nEvents %d\n",
258 iEventType, iButton, nevents);
264 * Decide what to do with a Windows mouse message
268 winMouseButtonsHandle (ScreenPtr pScreen,
269 int iEventType, int iButton,
272 winScreenPriv(pScreen);
273 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
275 /* Send button events right away if emulate 3 buttons is off */
276 if (pScreenInfo->iE3BTimeout == WIN_E3B_OFF)
278 /* Emulate 3 buttons is off, send the button event */
279 winMouseButtonsSendEvent (iEventType, iButton);
283 /* Emulate 3 buttons is on, let the fun begin */
284 if (iEventType == ButtonPress
285 && pScreenPriv->iE3BCachedPress == 0
286 && !pScreenPriv->fE3BFakeButton2Sent)
289 * Button was pressed, no press is cached,
290 * and there is no fake button 2 release pending.
293 /* Store button press type */
294 pScreenPriv->iE3BCachedPress = iButton;
297 * Set a timer to send this button press if the other button
298 * is not pressed within the timeout time.
300 SetTimer (pScreenPriv->hwndScreen,
302 pScreenInfo->iE3BTimeout,
305 else if (iEventType == ButtonPress
306 && pScreenPriv->iE3BCachedPress != 0
307 && pScreenPriv->iE3BCachedPress != iButton
308 && !pScreenPriv->fE3BFakeButton2Sent)
311 * Button press is cached, other button was pressed,
312 * and there is no fake button 2 release pending.
315 /* Mouse button was cached and other button was pressed */
316 KillTimer (pScreenPriv->hwndScreen, WIN_E3B_TIMER_ID);
317 pScreenPriv->iE3BCachedPress = 0;
319 /* Send fake middle button */
320 winMouseButtonsSendEvent (ButtonPress, Button2);
322 /* Indicate that a fake middle button event was sent */
323 pScreenPriv->fE3BFakeButton2Sent = TRUE;
325 else if (iEventType == ButtonRelease
326 && pScreenPriv->iE3BCachedPress == iButton)
329 * Cached button was released before timer ran out,
330 * and before the other mouse button was pressed.
332 KillTimer (pScreenPriv->hwndScreen, WIN_E3B_TIMER_ID);
333 pScreenPriv->iE3BCachedPress = 0;
335 /* Send cached press, then send release */
336 winMouseButtonsSendEvent (ButtonPress, iButton);
337 winMouseButtonsSendEvent (ButtonRelease, iButton);
339 else if (iEventType == ButtonRelease
340 && pScreenPriv->fE3BFakeButton2Sent
341 && !(wParam & MK_LBUTTON)
342 && !(wParam & MK_RBUTTON))
345 * Fake button 2 was sent and both mouse buttons have now been released
347 pScreenPriv->fE3BFakeButton2Sent = FALSE;
349 /* Send middle mouse button release */
350 winMouseButtonsSendEvent (ButtonRelease, Button2);
352 else if (iEventType == ButtonRelease
353 && pScreenPriv->iE3BCachedPress == 0
354 && !pScreenPriv->fE3BFakeButton2Sent)
357 * Button was release, no button is cached,
358 * and there is no fake button 2 release is pending.
360 winMouseButtonsSendEvent (ButtonRelease, iButton);
367 * Enqueue a motion event.
369 * XXX: miPointerMove does exactly this, but is static :-( (and uses a static buffer)
372 void winEnqueueMotion(int x, int y)
378 miPointerSetPosition(g_pwinPointer, &x, &y);
382 GetEventList(&events);
383 nevents = GetPointerEvents(events, g_pwinPointer, MotionNotify, 0,
384 POINTER_ABSOLUTE | POINTER_SCREEN, 0, 2, valuators);
386 for (i = 0; i < nevents; i++)
387 mieqEnqueue(g_pwinPointer, events[i].event);