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>
40 #include "exevents.h" /* for button/axes labels */
41 #include "xserver-properties.h"
42 #include "inpututils.h"
44 /* Peek the internal button mapping */
45 static CARD8
const *g_winMouseButtonMap
= NULL
;
52 winMouseCtrl(DeviceIntPtr pDevice
, PtrCtrl
* pCtrl
);
55 winMouseCtrl(DeviceIntPtr pDevice
, PtrCtrl
* pCtrl
)
60 * See Porting Layer Definition - p. 18
61 * This is known as a DeviceProc
65 winMouseProc(DeviceIntPtr pDeviceInt
, int iState
)
67 int lngMouseButtons
, i
;
68 int lngWheelEvents
= 4;
70 DevicePtr pDevice
= (DevicePtr
) pDeviceInt
;
76 /* Get number of mouse buttons */
77 lngMouseButtons
= GetSystemMetrics(SM_CMOUSEBUTTONS
);
78 winMsg(X_PROBED
, "%d mouse buttons found\n", lngMouseButtons
);
80 /* Mapping of windows events to X events:
81 * LEFT:1 MIDDLE:2 RIGHT:3
82 * SCROLL_UP:4 SCROLL_DOWN:5
83 * TILT_LEFT:6 TILT_RIGHT:7
84 * XBUTTON 1:8 XBUTTON 2:9 (most commonly 'back' and 'forward')
87 * The current Windows API only defines 2 extra buttons, so we don't
88 * expect more than 5 buttons to be reported, but more than that
89 * should be handled correctly
93 * To map scroll wheel correctly we need at least the 3 normal buttons
95 if (lngMouseButtons
< 3)
99 * number of buttons + 4 x mouse wheel event + 1 extra (offset for map)
101 map
= malloc(sizeof(CARD8
) * (lngMouseButtons
+ lngWheelEvents
+ 1));
103 /* initalize button map */
105 for (i
= 1; i
<= lngMouseButtons
+ lngWheelEvents
; i
++)
108 btn_labels
[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT
);
109 btn_labels
[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE
);
110 btn_labels
[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT
);
111 btn_labels
[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP
);
112 btn_labels
[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN
);
113 btn_labels
[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT
);
114 btn_labels
[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT
);
115 btn_labels
[7] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_BACK
);
116 btn_labels
[8] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_FORWARD
);
118 axes_labels
[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X
);
119 axes_labels
[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y
);
121 InitPointerDeviceStruct(pDevice
,
123 lngMouseButtons
+ lngWheelEvents
,
126 GetMotionHistorySize(), 2, axes_labels
);
129 g_winMouseButtonMap
= pDeviceInt
->button
->map
;
137 g_winMouseButtonMap
= NULL
;
146 /* Handle the mouse wheel */
148 winMouseWheel(int *iTotalDeltaZ
, int iDeltaZ
, int iButtonUp
, int iButtonDown
)
152 /* Do we have any previous delta stored? */
153 if ((*iTotalDeltaZ
> 0 && iDeltaZ
> 0)
154 || (*iTotalDeltaZ
< 0 && iDeltaZ
< 0)) {
155 /* Previous delta and of same sign as current delta */
156 iDeltaZ
+= *iTotalDeltaZ
;
161 * Previous delta of different sign, or zero.
162 * We will set it to zero for either case,
163 * as blindly setting takes just as much time
164 * as checking, then setting if necessary :)
170 * Only process this message if the wheel has moved further than
173 if (iDeltaZ
>= WHEEL_DELTA
|| (-1 * iDeltaZ
) >= WHEEL_DELTA
) {
176 /* Figure out how many whole deltas of the wheel we have */
177 iDeltaZ
/= WHEEL_DELTA
;
181 * Wheel has not moved past WHEEL_DELTA threshold;
182 * we will store the wheel delta until the threshold
185 *iTotalDeltaZ
= iDeltaZ
;
189 /* Set the button to indicate up or down wheel delta */
194 button
= iButtonDown
;
198 * Flip iDeltaZ to positive, if negative,
199 * because always need to generate a *positive* number of
200 * button clicks for the Z axis.
206 /* Generate X input messages for each wheel delta we have seen */
208 /* Push the wheel button */
209 winMouseButtonsSendEvent(ButtonPress
, button
);
211 /* Release the wheel button */
212 winMouseButtonsSendEvent(ButtonRelease
, button
);
219 * Enqueue a mouse button event
223 winMouseButtonsSendEvent(int iEventType
, int iButton
)
227 if (g_winMouseButtonMap
)
228 iButton
= g_winMouseButtonMap
[iButton
];
230 valuator_mask_zero(&mask
);
231 QueuePointerEvents(g_pwinPointer
, iEventType
, iButton
,
232 POINTER_RELATIVE
, &mask
);
235 ErrorF("winMouseButtonsSendEvent: iEventType: %d, iButton: %d\n",
236 iEventType
, iButton
);
241 * Decide what to do with a Windows mouse message
245 winMouseButtonsHandle(ScreenPtr pScreen
,
246 int iEventType
, int iButton
, WPARAM wParam
)
248 winScreenPriv(pScreen
);
249 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
251 /* Send button events right away if emulate 3 buttons is off */
252 if (pScreenInfo
->iE3BTimeout
== WIN_E3B_OFF
) {
253 /* Emulate 3 buttons is off, send the button event */
254 winMouseButtonsSendEvent(iEventType
, iButton
);
258 /* Emulate 3 buttons is on, let the fun begin */
259 if (iEventType
== ButtonPress
260 && pScreenPriv
->iE3BCachedPress
== 0
261 && !pScreenPriv
->fE3BFakeButton2Sent
) {
263 * Button was pressed, no press is cached,
264 * and there is no fake button 2 release pending.
267 /* Store button press type */
268 pScreenPriv
->iE3BCachedPress
= iButton
;
271 * Set a timer to send this button press if the other button
272 * is not pressed within the timeout time.
274 SetTimer(pScreenPriv
->hwndScreen
,
275 WIN_E3B_TIMER_ID
, pScreenInfo
->iE3BTimeout
, NULL
);
277 else if (iEventType
== ButtonPress
278 && pScreenPriv
->iE3BCachedPress
!= 0
279 && pScreenPriv
->iE3BCachedPress
!= iButton
280 && !pScreenPriv
->fE3BFakeButton2Sent
) {
282 * Button press is cached, other button was pressed,
283 * and there is no fake button 2 release pending.
286 /* Mouse button was cached and other button was pressed */
287 KillTimer(pScreenPriv
->hwndScreen
, WIN_E3B_TIMER_ID
);
288 pScreenPriv
->iE3BCachedPress
= 0;
290 /* Send fake middle button */
291 winMouseButtonsSendEvent(ButtonPress
, Button2
);
293 /* Indicate that a fake middle button event was sent */
294 pScreenPriv
->fE3BFakeButton2Sent
= TRUE
;
296 else if (iEventType
== ButtonRelease
297 && pScreenPriv
->iE3BCachedPress
== iButton
) {
299 * Cached button was released before timer ran out,
300 * and before the other mouse button was pressed.
302 KillTimer(pScreenPriv
->hwndScreen
, WIN_E3B_TIMER_ID
);
303 pScreenPriv
->iE3BCachedPress
= 0;
305 /* Send cached press, then send release */
306 winMouseButtonsSendEvent(ButtonPress
, iButton
);
307 winMouseButtonsSendEvent(ButtonRelease
, iButton
);
309 else if (iEventType
== ButtonRelease
310 && pScreenPriv
->fE3BFakeButton2Sent
&& !(wParam
& MK_LBUTTON
)
311 && !(wParam
& MK_RBUTTON
)) {
313 * Fake button 2 was sent and both mouse buttons have now been released
315 pScreenPriv
->fE3BFakeButton2Sent
= FALSE
;
317 /* Send middle mouse button release */
318 winMouseButtonsSendEvent(ButtonRelease
, Button2
);
320 else if (iEventType
== ButtonRelease
321 && pScreenPriv
->iE3BCachedPress
== 0
322 && !pScreenPriv
->fE3BFakeButton2Sent
) {
324 * Button was release, no button is cached,
325 * and there is no fake button 2 release is pending.
327 winMouseButtonsSendEvent(ButtonRelease
, iButton
);
334 * Enqueue a motion event.
338 winEnqueueMotion(int x
, int y
)
346 valuator_mask_set_range(&mask
, 0, 2, valuators
);
347 QueuePointerEvents(g_pwinPointer
, MotionNotify
, 0,
348 POINTER_ABSOLUTE
| POINTER_SCREEN
, &mask
);