Resolve chained CNAME records
[reactos.git] / reactos / lib / dinput / mouse.c
1 /* DirectInput Mouse device
2 *
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
5 * Copyright 2000-2001 TransGaming Technologies Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdarg.h>
26 #include <string.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "winuser.h"
32 #include "winerror.h"
33 #include "dinput.h"
34
35 #include "dinput_private.h"
36 #include "device_private.h"
37 #include "wine/debug.h"
38 #include "wine/unicode.h"
39
40 #define MOUSE_HACK
41
42 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
43
44 /* Wine mouse driver object instances */
45 #define WINE_MOUSE_X_AXIS_INSTANCE 0
46 #define WINE_MOUSE_Y_AXIS_INSTANCE 1
47 #define WINE_MOUSE_Z_AXIS_INSTANCE 2
48 #define WINE_MOUSE_L_BUTTON_INSTANCE 0
49 #define WINE_MOUSE_R_BUTTON_INSTANCE 1
50 #define WINE_MOUSE_M_BUTTON_INSTANCE 2
51 #define WINE_MOUSE_D_BUTTON_INSTANCE 3
52
53 /* ------------------------------- */
54 /* Wine mouse internal data format */
55 /* ------------------------------- */
56
57 /* Constants used to access the offset array */
58 #define WINE_MOUSE_X_POSITION 0
59 #define WINE_MOUSE_Y_POSITION 1
60 #define WINE_MOUSE_Z_POSITION 2
61 #define WINE_MOUSE_L_POSITION 3
62 #define WINE_MOUSE_R_POSITION 4
63 #define WINE_MOUSE_M_POSITION 5
64
65 typedef struct {
66 LONG lX;
67 LONG lY;
68 LONG lZ;
69 BYTE rgbButtons[4];
70 } Wine_InternalMouseData;
71
72 #define WINE_INTERNALMOUSE_NUM_OBJS 6
73
74 static const DIOBJECTDATAFORMAT Wine_InternalMouseObjectFormat[WINE_INTERNALMOUSE_NUM_OBJS] = {
75 { &GUID_XAxis, FIELD_OFFSET(Wine_InternalMouseData, lX),
76 DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS, 0 },
77 { &GUID_YAxis, FIELD_OFFSET(Wine_InternalMouseData, lY),
78 DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS, 0 },
79 { &GUID_ZAxis, FIELD_OFFSET(Wine_InternalMouseData, lZ),
80 DIDFT_MAKEINSTANCE(WINE_MOUSE_Z_AXIS_INSTANCE) | DIDFT_RELAXIS, 0 },
81 { &GUID_Button, (FIELD_OFFSET(Wine_InternalMouseData, rgbButtons)) + 0,
82 DIDFT_MAKEINSTANCE(WINE_MOUSE_L_BUTTON_INSTANCE) | DIDFT_PSHBUTTON, 0 },
83 { &GUID_Button, (FIELD_OFFSET(Wine_InternalMouseData, rgbButtons)) + 1,
84 DIDFT_MAKEINSTANCE(WINE_MOUSE_R_BUTTON_INSTANCE) | DIDFT_PSHBUTTON, 0 },
85 { &GUID_Button, (FIELD_OFFSET(Wine_InternalMouseData, rgbButtons)) + 2,
86 DIDFT_MAKEINSTANCE(WINE_MOUSE_M_BUTTON_INSTANCE) | DIDFT_PSHBUTTON, 0 }
87 };
88
89 static const DIDATAFORMAT Wine_InternalMouseFormat = {
90 0, /* dwSize - unused */
91 0, /* dwObjsize - unused */
92 0, /* dwFlags - unused */
93 sizeof(Wine_InternalMouseData),
94 WINE_INTERNALMOUSE_NUM_OBJS, /* dwNumObjs */
95 (LPDIOBJECTDATAFORMAT) Wine_InternalMouseObjectFormat
96 };
97
98 static const IDirectInputDevice8AVtbl SysMouseAvt;
99 static const IDirectInputDevice8WVtbl SysMouseWvt;
100
101 typedef struct SysMouseImpl SysMouseImpl;
102
103 typedef enum {
104 WARP_DONE, /* Warping has been done */
105 WARP_NEEDED, /* Warping is needed */
106 WARP_STARTED /* Warping has been done, waiting for the warp event */
107 } WARP_STATUS;
108
109 struct SysMouseImpl
110 {
111 const void *lpVtbl;
112 LONG ref;
113 GUID guid;
114
115 IDirectInputImpl *dinput;
116
117 /* The current data format and the conversion between internal
118 and external data formats */
119 DIDATAFORMAT *df;
120 DataFormat *wine_df;
121 int offset_array[WINE_INTERNALMOUSE_NUM_OBJS];
122
123 /* SysMouseAImpl */
124 BYTE absolute;
125 /* Previous position for relative moves */
126 LONG prevX, prevY;
127 /* These are used in case of relative -> absolute transitions */
128 POINT org_coords;
129 HHOOK hook;
130 HWND win;
131 DWORD dwCoopLevel;
132 POINT mapped_center;
133 DWORD win_centerX, win_centerY;
134 LPDIDEVICEOBJECTDATA data_queue;
135 int queue_head, queue_tail, queue_len;
136 BOOL overflow;
137 /* warping: whether we need to move mouse back to middle once we
138 * reach window borders (for e.g. shooters, "surface movement" games) */
139 WARP_STATUS need_warp;
140 int acquired;
141 HANDLE hEvent;
142 CRITICAL_SECTION crit;
143
144 /* This is for mouse reporting. */
145 Wine_InternalMouseData m_state;
146 };
147
148 /* FIXME: This is ugly and not thread safe :/ */
149 static IDirectInputDevice8A* current_lock = NULL;
150
151 /* FIXME: This is ugly but needed on Windows */
152 static int mouse_set = 0;
153 static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
154 0x9e573ed8,
155 0x7734,
156 0x11d2,
157 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
158 };
159
160 static void fill_mouse_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version) {
161 DWORD dwSize;
162 DIDEVICEINSTANCEA ddi;
163
164 dwSize = lpddi->dwSize;
165
166 TRACE("%ld %p\n", dwSize, lpddi);
167
168 memset(lpddi, 0, dwSize);
169 memset(&ddi, 0, sizeof(ddi));
170
171 ddi.dwSize = dwSize;
172 ddi.guidInstance = GUID_SysMouse;/* DInput's GUID */
173 ddi.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
174 if (version >= 0x0800)
175 ddi.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8);
176 else
177 ddi.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8);
178 strcpy(ddi.tszInstanceName, "Mouse");
179 strcpy(ddi.tszProductName, "Wine Mouse");
180
181 memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
182 }
183
184 static void fill_mouse_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version) {
185 DWORD dwSize;
186 DIDEVICEINSTANCEW ddi;
187
188 dwSize = lpddi->dwSize;
189
190 TRACE("%ld %p\n", dwSize, lpddi);
191
192 memset(lpddi, 0, dwSize);
193 memset(&ddi, 0, sizeof(ddi));
194
195 ddi.dwSize = dwSize;
196 ddi.guidInstance = GUID_SysMouse;/* DInput's GUID */
197 ddi.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
198 if (version >= 0x0800)
199 ddi.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8);
200 else
201 ddi.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8);
202 MultiByteToWideChar(CP_ACP, 0, "Mouse", -1, ddi.tszInstanceName, MAX_PATH);
203 MultiByteToWideChar(CP_ACP, 0, "Wine Mouse", -1, ddi.tszProductName, MAX_PATH);
204
205 memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
206 }
207
208 static BOOL mousedev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
209 {
210 if (id != 0)
211 return FALSE;
212
213 if ((dwDevType == 0) ||
214 ((dwDevType == DIDEVTYPE_MOUSE) && (version < 0x0800)) ||
215 (((dwDevType == DI8DEVCLASS_POINTER) || (dwDevType == DI8DEVTYPE_MOUSE)) && (version >= 0x0800))) {
216 TRACE("Enumerating the mouse device\n");
217
218 fill_mouse_dideviceinstanceA(lpddi, version);
219
220 return TRUE;
221 }
222
223 return FALSE;
224 }
225
226 static BOOL mousedev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
227 {
228 if (id != 0)
229 return FALSE;
230
231 if ((dwDevType == 0) ||
232 ((dwDevType == DIDEVTYPE_MOUSE) && (version < 0x0800)) ||
233 (((dwDevType == DI8DEVCLASS_POINTER) || (dwDevType == DI8DEVTYPE_MOUSE)) && (version >= 0x0800))) {
234 TRACE("Enumerating the mouse device\n");
235
236 fill_mouse_dideviceinstanceW(lpddi, version);
237
238 return TRUE;
239 }
240
241 return FALSE;
242 }
243
244 static SysMouseImpl *alloc_device(REFGUID rguid, const void *mvt, IDirectInputImpl *dinput)
245 {
246 int offset_array[WINE_INTERNALMOUSE_NUM_OBJS] = {
247 FIELD_OFFSET(Wine_InternalMouseData, lX),
248 FIELD_OFFSET(Wine_InternalMouseData, lY),
249 FIELD_OFFSET(Wine_InternalMouseData, lZ),
250 FIELD_OFFSET(Wine_InternalMouseData, rgbButtons) + 0,
251 FIELD_OFFSET(Wine_InternalMouseData, rgbButtons) + 1,
252 FIELD_OFFSET(Wine_InternalMouseData, rgbButtons) + 2
253 };
254 SysMouseImpl* newDevice;
255 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseImpl));
256 newDevice->ref = 1;
257 newDevice->lpVtbl = mvt;
258 InitializeCriticalSection(&(newDevice->crit));
259 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
260
261 /* Per default, Wine uses its internal data format */
262 newDevice->df = (DIDATAFORMAT *) &Wine_InternalMouseFormat;
263 memcpy(newDevice->offset_array, offset_array, WINE_INTERNALMOUSE_NUM_OBJS * sizeof(int));
264 newDevice->wine_df = HeapAlloc(GetProcessHeap(), 0, sizeof(DataFormat));
265 newDevice->wine_df->size = 0;
266 newDevice->wine_df->internal_format_size = Wine_InternalMouseFormat.dwDataSize;
267 newDevice->wine_df->dt = NULL;
268 newDevice->dinput = dinput;
269
270 return newDevice;
271 }
272
273 static HRESULT mousedev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
274 {
275 if ((IsEqualGUID(&GUID_SysMouse,rguid)) || /* Generic Mouse */
276 (IsEqualGUID(&DInput_Wine_Mouse_GUID,rguid))) { /* Wine Mouse */
277 if ((riid == NULL) ||
278 IsEqualGUID(&IID_IDirectInputDeviceA,riid) ||
279 IsEqualGUID(&IID_IDirectInputDevice2A,riid) ||
280 IsEqualGUID(&IID_IDirectInputDevice7A,riid) ||
281 IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
282 *pdev = (IDirectInputDeviceA*) alloc_device(rguid, &SysMouseAvt, dinput);
283 TRACE("Creating a Mouse device (%p)\n", *pdev);
284 return DI_OK;
285 } else
286 return DIERR_NOINTERFACE;
287 }
288
289 return DIERR_DEVICENOTREG;
290 }
291
292 static HRESULT mousedev_create_deviceW(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEW* pdev)
293 {
294 if ((IsEqualGUID(&GUID_SysMouse,rguid)) || /* Generic Mouse */
295 (IsEqualGUID(&DInput_Wine_Mouse_GUID,rguid))) { /* Wine Mouse */
296 if ((riid == NULL) ||
297 IsEqualGUID(&IID_IDirectInputDeviceW,riid) ||
298 IsEqualGUID(&IID_IDirectInputDevice2W,riid) ||
299 IsEqualGUID(&IID_IDirectInputDevice7W,riid) ||
300 IsEqualGUID(&IID_IDirectInputDevice8W,riid)) {
301 *pdev = (IDirectInputDeviceW*) alloc_device(rguid, &SysMouseWvt, dinput);
302 TRACE("Creating a Mouse device (%p)\n", *pdev);
303 return DI_OK;
304 } else
305 return DIERR_NOINTERFACE;
306 }
307
308 return DIERR_DEVICENOTREG;
309 }
310
311 const struct dinput_device mouse_device = {
312 "Wine mouse driver",
313 mousedev_enum_deviceA,
314 mousedev_enum_deviceW,
315 mousedev_create_deviceA,
316 mousedev_create_deviceW
317 };
318
319 /******************************************************************************
320 * SysMouseA (DInput Mouse support)
321 */
322
323 /******************************************************************************
324 * Release : release the mouse buffer.
325 */
326 static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE8A iface)
327 {
328 SysMouseImpl *This = (SysMouseImpl *)iface;
329 ULONG ref;
330
331 ref = InterlockedDecrement(&(This->ref));
332 if (ref)
333 return ref;
334
335 /* Free the data queue */
336 HeapFree(GetProcessHeap(),0,This->data_queue);
337
338 if (This->hook) {
339 UnhookWindowsHookEx( This->hook );
340 if (This->dwCoopLevel & DISCL_EXCLUSIVE)
341 ShowCursor(TRUE); /* show cursor */
342 }
343 DeleteCriticalSection(&(This->crit));
344
345 /* Free the DataFormat */
346 if (This->df != &(Wine_InternalMouseFormat)) {
347 HeapFree(GetProcessHeap(), 0, This->df->rgodf);
348 HeapFree(GetProcessHeap(), 0, This->df);
349 }
350
351 HeapFree(GetProcessHeap(),0,This);
352 return 0;
353 }
354
355
356 /******************************************************************************
357 * SetCooperativeLevel : store the window in which we will do our
358 * grabbing.
359 */
360 static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
361 LPDIRECTINPUTDEVICE8A iface,HWND hwnd,DWORD dwflags
362 )
363 {
364 SysMouseImpl *This = (SysMouseImpl *)iface;
365
366 TRACE("(this=%p,%p,0x%08lx)\n",This,hwnd,dwflags);
367
368 if (TRACE_ON(dinput)) {
369 TRACE(" cooperative level : ");
370 _dump_cooperativelevel_DI(dwflags);
371 }
372
373 /* Store the window which asks for the mouse */
374 if (!hwnd)
375 hwnd = GetDesktopWindow();
376 This->win = hwnd;
377 This->dwCoopLevel = dwflags;
378
379 return DI_OK;
380 }
381
382
383 /******************************************************************************
384 * SetDataFormat : the application can choose the format of the data
385 * the device driver sends back with GetDeviceState.
386 *
387 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
388 * in absolute and relative mode.
389 */
390 static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
391 LPDIRECTINPUTDEVICE8A iface,LPCDIDATAFORMAT df
392 )
393 {
394 SysMouseImpl *This = (SysMouseImpl *)iface;
395
396 TRACE("(this=%p,%p)\n",This,df);
397
398 _dump_DIDATAFORMAT(df);
399
400 /* Tests under windows show that a call to SetDataFormat always sets the mouse
401 in relative mode whatever the dwFlags value (DIDF_ABSAXIS/DIDF_RELAXIS).
402 To switch in absolute mode, SetProperty must be used. */
403 This->absolute = 0;
404
405 /* Store the new data format */
406 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize);
407 memcpy(This->df, df, df->dwSize);
408 This->df->rgodf = HeapAlloc(GetProcessHeap(),0,df->dwNumObjs*df->dwObjSize);
409 memcpy(This->df->rgodf,df->rgodf,df->dwNumObjs*df->dwObjSize);
410
411 /* Prepare all the data-conversion filters */
412 This->wine_df = create_DataFormat(&(Wine_InternalMouseFormat), df, This->offset_array);
413
414 return DI_OK;
415 }
416
417 /* low-level mouse hook */
418 static LRESULT CALLBACK dinput_mouse_hook( int code, WPARAM wparam, LPARAM lparam )
419 {
420 LRESULT ret;
421 MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam;
422 SysMouseImpl* This = (SysMouseImpl*) current_lock;
423 DWORD dwCoop;
424 static long last_event = 0;
425 int wdata;
426
427 if (code != HC_ACTION) return CallNextHookEx( This->hook, code, wparam, lparam );
428
429 EnterCriticalSection(&(This->crit));
430 dwCoop = This->dwCoopLevel;
431
432 /* Only allow mouse events every 10 ms.
433 * This is to allow the cursor to start acceleration before
434 * the warps happen. But if it involves a mouse button event we
435 * allow it since we don't want to lose the clicks.
436 */
437 if (((GetCurrentTime() - last_event) < 10)
438 && wparam == WM_MOUSEMOVE)
439 goto end;
440 else last_event = GetCurrentTime();
441
442 /* Mouse moved -> send event if asked */
443 if (This->hEvent)
444 SetEvent(This->hEvent);
445
446 if (wparam == WM_MOUSEMOVE) {
447 if (This->absolute) {
448 if (hook->pt.x != This->prevX)
449 GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], hook->pt.x, hook->time, 0);
450 if (hook->pt.y != This->prevY)
451 GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], hook->pt.y, hook->time, 0);
452 } else {
453 /* Now, warp handling */
454 if ((This->need_warp == WARP_STARTED) &&
455 (hook->pt.x == This->mapped_center.x) && (hook->pt.y == This->mapped_center.y)) {
456 /* Warp has been done... */
457 This->need_warp = WARP_DONE;
458 goto end;
459 }
460
461 /* Relative mouse input with absolute mouse event : the real fun starts here... */
462 if ((This->need_warp == WARP_NEEDED) ||
463 (This->need_warp == WARP_STARTED)) {
464 if (hook->pt.x != This->prevX)
465 GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], hook->pt.x - This->prevX,
466 hook->time, (This->dinput->evsequence)++);
467 if (hook->pt.y != This->prevY)
468 GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], hook->pt.y - This->prevY,
469 hook->time, (This->dinput->evsequence)++);
470 } else {
471 /* This is the first time the event handler has been called after a
472 GetDeviceData or GetDeviceState. */
473 if (hook->pt.x != This->mapped_center.x) {
474 GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], hook->pt.x - This->mapped_center.x,
475 hook->time, (This->dinput->evsequence)++);
476 This->need_warp = WARP_NEEDED;
477 }
478
479 if (hook->pt.y != This->mapped_center.y) {
480 GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], hook->pt.y - This->mapped_center.y,
481 hook->time, (This->dinput->evsequence)++);
482 This->need_warp = WARP_NEEDED;
483 }
484 }
485 }
486
487 This->prevX = hook->pt.x;
488 This->prevY = hook->pt.y;
489
490 if (This->absolute) {
491 This->m_state.lX = hook->pt.x;
492 This->m_state.lY = hook->pt.y;
493 } else {
494 This->m_state.lX = hook->pt.x - This->mapped_center.x;
495 This->m_state.lY = hook->pt.y - This->mapped_center.y;
496 }
497 }
498
499 TRACE(" msg %x pt %ld %ld (W=%d)\n",
500 wparam, hook->pt.x, hook->pt.y, (!This->absolute) && This->need_warp );
501
502 switch(wparam) {
503 case WM_LBUTTONDOWN:
504 GEN_EVENT(This->offset_array[WINE_MOUSE_L_POSITION], 0x80,
505 hook->time, This->dinput->evsequence++);
506 This->m_state.rgbButtons[0] = 0x80;
507 break;
508 case WM_LBUTTONUP:
509 GEN_EVENT(This->offset_array[WINE_MOUSE_L_POSITION], 0x00,
510 hook->time, This->dinput->evsequence++);
511 This->m_state.rgbButtons[0] = 0x00;
512 break;
513 case WM_RBUTTONDOWN:
514 GEN_EVENT(This->offset_array[WINE_MOUSE_R_POSITION], 0x80,
515 hook->time, This->dinput->evsequence++);
516 This->m_state.rgbButtons[1] = 0x80;
517 break;
518 case WM_RBUTTONUP:
519 GEN_EVENT(This->offset_array[WINE_MOUSE_R_POSITION], 0x00,
520 hook->time, This->dinput->evsequence++);
521 This->m_state.rgbButtons[1] = 0x00;
522 break;
523 case WM_MBUTTONDOWN:
524 GEN_EVENT(This->offset_array[WINE_MOUSE_M_POSITION], 0x80,
525 hook->time, This->dinput->evsequence++);
526 This->m_state.rgbButtons[2] = 0x80;
527 break;
528 case WM_MBUTTONUP:
529 GEN_EVENT(This->offset_array[WINE_MOUSE_M_POSITION], 0x00,
530 hook->time, This->dinput->evsequence++);
531 This->m_state.rgbButtons[2] = 0x00;
532 break;
533 case WM_MOUSEWHEEL:
534 wdata = (short)HIWORD(hook->mouseData);
535 GEN_EVENT(This->offset_array[WINE_MOUSE_Z_POSITION], wdata,
536 hook->time, This->dinput->evsequence++);
537 This->m_state.lZ += wdata;
538 break;
539 }
540
541 TRACE("(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
542 This->m_state.lX, This->m_state.lY,
543 This->m_state.rgbButtons[0], This->m_state.rgbButtons[2], This->m_state.rgbButtons[1]);
544
545 end:
546 LeaveCriticalSection(&(This->crit));
547
548 if (dwCoop & DISCL_NONEXCLUSIVE) {
549 /* Pass the events down to previous handlers (e.g. win32 input) */
550 ret = CallNextHookEx( This->hook, code, wparam, lparam );
551 } else {
552 /* Ignore message */
553 ret = 1;
554 }
555 return ret;
556 }
557
558
559 static void dinput_window_check(SysMouseImpl* This) {
560 RECT rect;
561 DWORD centerX, centerY;
562
563 /* make sure the window hasn't moved */
564 GetWindowRect(This->win, &rect);
565 centerX = (rect.right - rect.left) / 2;
566 centerY = (rect.bottom - rect.top ) / 2;
567 if (This->win_centerX != centerX || This->win_centerY != centerY) {
568 This->win_centerX = centerX;
569 This->win_centerY = centerY;
570 }
571 This->mapped_center.x = This->win_centerX;
572 This->mapped_center.y = This->win_centerY;
573 MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1);
574 }
575
576
577 /******************************************************************************
578 * Acquire : gets exclusive control of the mouse
579 */
580 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
581 {
582 SysMouseImpl *This = (SysMouseImpl *)iface;
583 RECT rect;
584 POINT point;
585
586 TRACE("(this=%p)\n",This);
587
588 if (This->acquired)
589 return S_FALSE;
590
591 This->acquired = 1;
592
593 /* Store (in a global variable) the current lock */
594 current_lock = (IDirectInputDevice8A*)This;
595
596 /* Init the mouse state */
597 GetCursorPos( &point );
598 if (This->absolute) {
599 This->m_state.lX = point.x;
600 This->m_state.lY = point.y;
601 This->prevX = point.x;
602 This->prevY = point.y;
603 } else {
604 This->m_state.lX = 0;
605 This->m_state.lY = 0;
606 This->org_coords = point;
607 }
608 This->m_state.lZ = 0;
609 This->m_state.rgbButtons[0] = GetKeyState(VK_LBUTTON) & 0x80;
610 This->m_state.rgbButtons[1] = GetKeyState(VK_RBUTTON) & 0x80;
611 This->m_state.rgbButtons[2] = GetKeyState(VK_MBUTTON) & 0x80;
612
613 /* Install our mouse hook */
614 if (This->dwCoopLevel & DISCL_EXCLUSIVE)
615 ShowCursor(FALSE); /* hide cursor */
616 This->hook = SetWindowsHookExA( WH_MOUSE_LL, dinput_mouse_hook, DINPUT_instance, 0 );
617
618 /* Get the window dimension and find the center */
619 GetWindowRect(This->win, &rect);
620 This->win_centerX = (rect.right - rect.left) / 2;
621 This->win_centerY = (rect.bottom - rect.top ) / 2;
622
623 /* Warp the mouse to the center of the window */
624 if (This->absolute == 0) {
625 This->mapped_center.x = This->win_centerX;
626 This->mapped_center.y = This->win_centerY;
627 MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1);
628 TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y);
629 SetCursorPos( This->mapped_center.x, This->mapped_center.y );
630 #ifdef MOUSE_HACK
631 This->need_warp = WARP_DONE;
632 #else
633 This->need_warp = WARP_STARTED;
634 #endif
635 }
636
637 return DI_OK;
638 }
639
640 /******************************************************************************
641 * Unacquire : frees the mouse
642 */
643 static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
644 {
645 SysMouseImpl *This = (SysMouseImpl *)iface;
646
647 TRACE("(this=%p)\n",This);
648
649 if (0 == This->acquired) {
650 return DI_NOEFFECT;
651 }
652
653 /* Reinstall previous mouse event handler */
654 if (This->hook) {
655 UnhookWindowsHookEx( This->hook );
656 This->hook = 0;
657
658 if (This->dwCoopLevel & DISCL_EXCLUSIVE)
659 ShowCursor(TRUE); /* show cursor */
660 }
661
662 /* No more locks */
663 if (current_lock == (IDirectInputDevice8A*) This)
664 current_lock = NULL;
665 else
666 ERR("this(%p) != current_lock(%p)\n", This, current_lock);
667
668 /* Unacquire device */
669 This->acquired = 0;
670
671 /* And put the mouse cursor back where it was at acquire time */
672 if (This->absolute == 0) {
673 TRACE(" warping mouse back to (%ld , %ld)\n", This->org_coords.x, This->org_coords.y);
674 SetCursorPos(This->org_coords.x, This->org_coords.y);
675 }
676
677 return DI_OK;
678 }
679
680 // if you call poll then to getdevicestate
681 // it did not send back right value in windows
682 int poll_mouse=0;
683
684
685 static HRESULT WINAPI SysMouseAImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
686 {
687 int retValue = DI_OK;
688
689 if (poll_mouse==0) {
690 retValue=SysMouseAImpl_Acquire(iface);
691 poll_mouse=1;
692 if (retValue!=DI_OK) retValue=DIERR_NOTACQUIRED;
693 else retValue = DI_OK;
694 }
695
696 return retValue;
697 }
698
699
700 /******************************************************************************
701 * GetDeviceState : returns the "state" of the mouse.
702 *
703 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
704 * supported.
705 */
706 static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
707 LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr
708 ) {
709 SysMouseImpl *This = (SysMouseImpl *)iface;
710
711 if(This->acquired == 0) return DIERR_NOTACQUIRED;
712
713 EnterCriticalSection(&(This->crit));
714 TRACE("(this=%p,0x%08lx,%p):\n", This, len, ptr);
715 TRACE("(X: %ld - Y: %ld - Z: %ld L: %02x M: %02x R: %02x)\n",
716 This->m_state.lX, This->m_state.lY, This->m_state.lZ,
717 This->m_state.rgbButtons[0], This->m_state.rgbButtons[2], This->m_state.rgbButtons[1]);
718
719 /* Copy the current mouse state */
720 fill_DataFormat(ptr, &(This->m_state), This->wine_df);
721
722 #ifdef __REACTOS__
723 // this fix windows bugs when
724 // some program calling on mouse poll
725 if (poll_mouse==1) poll_mouse=0;
726 else {
727 if (This->absolute == 0) {
728 This->m_state.lX = 0;
729 This->m_state.lY = 0;
730 This->m_state.lZ = 0;
731 }
732 }
733 #endif
734
735 /* Check if we need to do a mouse warping */
736 if (This->need_warp == WARP_NEEDED) {
737 dinput_window_check(This);
738 TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y);
739 if (mouse_set==0){
740 SetCursorPos( This->mapped_center.x, This->mapped_center.y );
741 mouse_set++;
742 }
743
744 #ifdef MOUSE_HACK
745 This->need_warp = WARP_DONE;
746 #else
747 This->need_warp = WARP_STARTED;
748 #endif
749 }
750
751 LeaveCriticalSection(&(This->crit));
752
753 return DI_OK;
754 }
755
756 /******************************************************************************
757 * GetDeviceData : gets buffered input data.
758 */
759 static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface,
760 DWORD dodsize,
761 LPDIDEVICEOBJECTDATA dod,
762 LPDWORD entries,
763 DWORD flags
764 ) {
765 SysMouseImpl *This = (SysMouseImpl *)iface;
766 DWORD len;
767 int nqtail = 0;
768
769 TRACE("(%p)->(dods=%ld,dod=%p,entries=%p (%ld)%s,fl=0x%08lx%s)\n",This,dodsize,dod,
770 entries, *entries,*entries == INFINITE ? " (INFINITE)" : "",
771 flags, (flags & DIGDD_PEEK) ? " (DIGDD_PEEK)": "" );
772
773 if (This->acquired == 0) {
774 WARN(" application tries to get data from an unacquired device !\n");
775 //return DIERR_NOTACQUIRED;
776
777 // windows does not get any data if
778 // we do not call manual to mouse Acquire
779 // this is only need if some apps calling on getdevice data direcly
780 // in windows GetdeviceData does always update first the data
781 // then return it.
782 SysMouseAImpl_Acquire(iface);
783 }
784
785 EnterCriticalSection(&(This->crit));
786
787 len = ((This->queue_head < This->queue_tail) ? This->queue_len : 0)
788 + (This->queue_head - This->queue_tail);
789 if ((*entries != INFINITE) && (len > *entries)) len = *entries;
790
791 if (dod == NULL) {
792 *entries = len;
793
794 if (!(flags & DIGDD_PEEK)) {
795 if (len)
796 TRACE("Application discarding %ld event(s).\n", len);
797
798 nqtail = This->queue_tail + len;
799 while (nqtail >= This->queue_len) nqtail -= This->queue_len;
800 } else {
801 TRACE("Telling application that %ld event(s) are in the queue.\n", len);
802 }
803 } else {
804 if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3)) {
805 ERR("Wrong structure size !\n");
806 LeaveCriticalSection(&(This->crit));
807 return DIERR_INVALIDPARAM;
808 }
809
810 if (len)
811 TRACE("Application retrieving %ld event(s):\n", len);
812
813 *entries = 0;
814 nqtail = This->queue_tail;
815 while (len) {
816 /* Copy the buffered data into the application queue */
817 TRACE(" - queuing Offs:%2ld Data:%5ld TS:%8ld Seq:%8ld at address %p from queue tail %4d\n",
818 (This->data_queue)->dwOfs,
819 (This->data_queue)->dwData,
820 (This->data_queue)->dwTimeStamp,
821 (This->data_queue)->dwSequence,
822 (char *)dod + *entries * dodsize,
823 nqtail);
824 memcpy((char *)dod + *entries * dodsize, This->data_queue + nqtail, dodsize);
825 /* Advance position */
826 nqtail++;
827 if (nqtail >= This->queue_len)
828 nqtail -= This->queue_len;
829 (*entries)++;
830 len--;
831 }
832 }
833 if (!(flags & DIGDD_PEEK))
834 This->queue_tail = nqtail;
835
836 LeaveCriticalSection(&(This->crit));
837
838 /* Check if we need to do a mouse warping */
839 if (This->need_warp == WARP_NEEDED) {
840 dinput_window_check(This);
841 TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y);
842 if (mouse_set==0){
843 SetCursorPos( This->mapped_center.x, This->mapped_center.y );
844 mouse_set++;
845 }
846
847 #ifdef MOUSE_HACK
848 This->need_warp = WARP_DONE;
849 #else
850 This->need_warp = WARP_STARTED;
851 #endif
852 }
853 return DI_OK;
854 }
855
856 /******************************************************************************
857 * SetProperty : change input device properties
858 */
859 static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface,
860 REFGUID rguid,
861 LPCDIPROPHEADER ph)
862 {
863 SysMouseImpl *This = (SysMouseImpl *)iface;
864
865 TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
866
867 if (!HIWORD(rguid)) {
868 switch (LOWORD(rguid)) {
869 case (DWORD) DIPROP_BUFFERSIZE: {
870 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
871
872 TRACE("buffersize = %ld\n",pd->dwData);
873
874 This->data_queue = HeapAlloc(GetProcessHeap(),0, pd->dwData * sizeof(DIDEVICEOBJECTDATA));
875 This->queue_head = 0;
876 This->queue_tail = 0;
877 This->queue_len = pd->dwData;
878 break;
879 }
880 case (DWORD) DIPROP_AXISMODE: {
881 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
882 This->absolute = !(pd->dwData);
883 TRACE("Using %s coordinates mode now\n", This->absolute ? "absolute" : "relative");
884 break;
885 }
886 default:
887 FIXME("Unknown type %p (%s)\n",rguid,debugstr_guid(rguid));
888 break;
889 }
890 }
891
892 return DI_OK;
893 }
894
895 /******************************************************************************
896 * GetProperty : get input device properties
897 */
898 static HRESULT WINAPI SysMouseAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface,
899 REFGUID rguid,
900 LPDIPROPHEADER pdiph)
901 {
902 SysMouseImpl *This = (SysMouseImpl *)iface;
903
904 TRACE("(this=%p,%s,%p)\n",
905 iface, debugstr_guid(rguid), pdiph);
906
907 if (TRACE_ON(dinput))
908 _dump_DIPROPHEADER(pdiph);
909
910 if (!HIWORD(rguid)) {
911 switch (LOWORD(rguid)) {
912 case (DWORD) DIPROP_BUFFERSIZE: {
913 LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
914
915 TRACE(" return buffersize = %d\n",This->queue_len);
916 pd->dwData = This->queue_len;
917 break;
918 }
919
920 case (DWORD) DIPROP_GRANULARITY: {
921 LPDIPROPDWORD pr = (LPDIPROPDWORD) pdiph;
922
923 /* We'll just assume that the app asks about the Z axis */
924 pr->dwData = WHEEL_DELTA;
925
926 break;
927 }
928
929 case (DWORD) DIPROP_RANGE: {
930 LPDIPROPRANGE pr = (LPDIPROPRANGE) pdiph;
931
932 if ((pdiph->dwHow == DIPH_BYID) &&
933 ((pdiph->dwObj == (DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS)) ||
934 (pdiph->dwObj == (DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS)))) {
935 /* Querying the range of either the X or the Y axis. As I do
936 not know the range, do as if the range were
937 unrestricted...*/
938 pr->lMin = DIPROPRANGE_NOMIN;
939 pr->lMax = DIPROPRANGE_NOMAX;
940 }
941
942 break;
943 }
944
945 default:
946 FIXME("Unknown type %p (%s)\n",rguid,debugstr_guid(rguid));
947 break;
948 }
949 }
950
951 return DI_OK;
952 }
953
954
955
956 /******************************************************************************
957 * SetEventNotification : specifies event to be sent on state change
958 */
959 static HRESULT WINAPI SysMouseAImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface,
960 HANDLE hnd) {
961 SysMouseImpl *This = (SysMouseImpl *)iface;
962
963 TRACE("(this=%p,%p)\n",This,hnd);
964
965 This->hEvent = hnd;
966
967 return DI_OK;
968 }
969
970 /******************************************************************************
971 * GetCapabilities : get the device capablitites
972 */
973 static HRESULT WINAPI SysMouseAImpl_GetCapabilities(
974 LPDIRECTINPUTDEVICE8A iface,
975 LPDIDEVCAPS lpDIDevCaps)
976 {
977 SysMouseImpl *This = (SysMouseImpl *)iface;
978 DIDEVCAPS devcaps;
979
980 TRACE("(this=%p,%p)\n",This,lpDIDevCaps);
981
982 if ((lpDIDevCaps->dwSize != sizeof(DIDEVCAPS)) && (lpDIDevCaps->dwSize != sizeof(DIDEVCAPS_DX3))) {
983 WARN("invalid parameter\n");
984 return DIERR_INVALIDPARAM;
985 }
986
987 devcaps.dwSize = lpDIDevCaps->dwSize;
988 devcaps.dwFlags = DIDC_ATTACHED;
989 if (This->dinput->dwVersion >= 0x0800)
990 devcaps.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8);
991 else
992 devcaps.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8);
993 devcaps.dwAxes = 3;
994 devcaps.dwButtons = 3;
995 devcaps.dwPOVs = 0;
996 devcaps.dwFFSamplePeriod = 0;
997 devcaps.dwFFMinTimeResolution = 0;
998 devcaps.dwFirmwareRevision = 100;
999 devcaps.dwHardwareRevision = 100;
1000 devcaps.dwFFDriverVersion = 0;
1001
1002 memcpy(lpDIDevCaps, &devcaps, lpDIDevCaps->dwSize);
1003
1004 return DI_OK;
1005 }
1006
1007
1008 /******************************************************************************
1009 * EnumObjects : enumerate the different buttons and axis...
1010 */
1011 static HRESULT WINAPI SysMouseAImpl_EnumObjects(
1012 LPDIRECTINPUTDEVICE8A iface,
1013 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
1014 LPVOID lpvRef,
1015 DWORD dwFlags)
1016 {
1017 SysMouseImpl *This = (SysMouseImpl *)iface;
1018 DIDEVICEOBJECTINSTANCEA ddoi;
1019
1020 TRACE("(this=%p,%p,%p,%08lx)\n", This, lpCallback, lpvRef, dwFlags);
1021 if (TRACE_ON(dinput)) {
1022 TRACE(" - flags = ");
1023 _dump_EnumObjects_flags(dwFlags);
1024 TRACE("\n");
1025 }
1026
1027 /* Only the fields till dwFFMaxForce are relevant */
1028 memset(&ddoi, 0, sizeof(ddoi));
1029 ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);
1030
1031 /* In a mouse, we have : two relative axis and three buttons */
1032 if ((dwFlags == DIDFT_ALL) ||
1033 (dwFlags & DIDFT_AXIS)) {
1034 /* X axis */
1035 ddoi.guidType = GUID_XAxis;
1036 ddoi.dwOfs = This->offset_array[WINE_MOUSE_X_POSITION];
1037 ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS;
1038 strcpy(ddoi.tszName, "X-Axis");
1039 _dump_OBJECTINSTANCEA(&ddoi);
1040 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1041
1042 /* Y axis */
1043 ddoi.guidType = GUID_YAxis;
1044 ddoi.dwOfs = This->offset_array[WINE_MOUSE_Y_POSITION];
1045 ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS;
1046 strcpy(ddoi.tszName, "Y-Axis");
1047 _dump_OBJECTINSTANCEA(&ddoi);
1048 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1049
1050 /* Z axis */
1051 ddoi.guidType = GUID_ZAxis;
1052 ddoi.dwOfs = This->offset_array[WINE_MOUSE_Z_POSITION];
1053 ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_Z_AXIS_INSTANCE) | DIDFT_RELAXIS;
1054 strcpy(ddoi.tszName, "Z-Axis");
1055 _dump_OBJECTINSTANCEA(&ddoi);
1056 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1057 }
1058
1059 if ((dwFlags == DIDFT_ALL) ||
1060 (dwFlags & DIDFT_BUTTON)) {
1061 ddoi.guidType = GUID_Button;
1062
1063 /* Left button */
1064 ddoi.dwOfs = This->offset_array[WINE_MOUSE_L_POSITION];
1065 ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_L_BUTTON_INSTANCE) | DIDFT_PSHBUTTON;
1066 strcpy(ddoi.tszName, "Left-Button");
1067 _dump_OBJECTINSTANCEA(&ddoi);
1068 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1069
1070 /* Right button */
1071 ddoi.dwOfs = This->offset_array[WINE_MOUSE_R_POSITION];
1072 ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_R_BUTTON_INSTANCE) | DIDFT_PSHBUTTON;
1073 strcpy(ddoi.tszName, "Right-Button");
1074 _dump_OBJECTINSTANCEA(&ddoi);
1075 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1076
1077 /* Middle button */
1078 ddoi.dwOfs = This->offset_array[WINE_MOUSE_M_POSITION];
1079 ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_M_BUTTON_INSTANCE) | DIDFT_PSHBUTTON;
1080 strcpy(ddoi.tszName, "Middle-Button");
1081 _dump_OBJECTINSTANCEA(&ddoi);
1082 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1083 }
1084
1085 return DI_OK;
1086 }
1087
1088 static HRESULT WINAPI SysMouseWImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface, LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID lpvRef,DWORD dwFlags)
1089 {
1090 SysMouseImpl *This = (SysMouseImpl *)iface;
1091
1092 device_enumobjects_AtoWcb_data data;
1093
1094 data.lpCallBack = lpCallback;
1095 data.lpvRef = lpvRef;
1096
1097 return SysMouseAImpl_EnumObjects((LPDIRECTINPUTDEVICE8A) This, (LPDIENUMDEVICEOBJECTSCALLBACKA) DIEnumDevicesCallbackAtoW, (LPVOID) &data, dwFlags);
1098 }
1099
1100 /******************************************************************************
1101 * GetDeviceInfo : get information about a device's identity
1102 */
1103 static HRESULT WINAPI SysMouseAImpl_GetDeviceInfo(
1104 LPDIRECTINPUTDEVICE8A iface,
1105 LPDIDEVICEINSTANCEA pdidi)
1106 {
1107 SysMouseImpl *This = (SysMouseImpl *)iface;
1108 TRACE("(this=%p,%p)\n", This, pdidi);
1109
1110 if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) {
1111 WARN(" dinput3 not supporte yet...\n");
1112 return DI_OK;
1113 }
1114
1115 fill_mouse_dideviceinstanceA(pdidi, This->dinput->dwVersion);
1116
1117 return DI_OK;
1118 }
1119
1120 static HRESULT WINAPI SysMouseWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW pdidi)
1121 {
1122 SysMouseImpl *This = (SysMouseImpl *)iface;
1123 TRACE("(this=%p,%p)\n", This, pdidi);
1124
1125 if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) {
1126 WARN(" dinput3 not supporte yet...\n");
1127 return DI_OK;
1128 }
1129
1130 fill_mouse_dideviceinstanceW(pdidi, This->dinput->dwVersion);
1131
1132 return DI_OK;
1133 }
1134
1135
1136 static const IDirectInputDevice8AVtbl SysMouseAvt =
1137 {
1138 IDirectInputDevice2AImpl_QueryInterface,
1139 IDirectInputDevice2AImpl_AddRef,
1140 SysMouseAImpl_Release,
1141 SysMouseAImpl_GetCapabilities,
1142 SysMouseAImpl_EnumObjects,
1143 SysMouseAImpl_GetProperty,
1144 SysMouseAImpl_SetProperty,
1145 SysMouseAImpl_Acquire,
1146 SysMouseAImpl_Unacquire,
1147 SysMouseAImpl_GetDeviceState,
1148 SysMouseAImpl_GetDeviceData,
1149 SysMouseAImpl_SetDataFormat,
1150 SysMouseAImpl_SetEventNotification,
1151 SysMouseAImpl_SetCooperativeLevel,
1152 IDirectInputDevice2AImpl_GetObjectInfo,
1153 SysMouseAImpl_GetDeviceInfo,
1154 IDirectInputDevice2AImpl_RunControlPanel,
1155 IDirectInputDevice2AImpl_Initialize,
1156 IDirectInputDevice2AImpl_CreateEffect,
1157 IDirectInputDevice2AImpl_EnumEffects,
1158 IDirectInputDevice2AImpl_GetEffectInfo,
1159 IDirectInputDevice2AImpl_GetForceFeedbackState,
1160 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1161 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1162 IDirectInputDevice2AImpl_Escape,
1163 SysMouseAImpl_Poll,
1164 IDirectInputDevice2AImpl_SendDeviceData,
1165 IDirectInputDevice7AImpl_EnumEffectsInFile,
1166 IDirectInputDevice7AImpl_WriteEffectToFile,
1167 IDirectInputDevice8AImpl_BuildActionMap,
1168 IDirectInputDevice8AImpl_SetActionMap,
1169 IDirectInputDevice8AImpl_GetImageInfo
1170 };
1171
1172 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1173 # define XCAST(fun) (typeof(SysMouseWvt.fun))
1174 #else
1175 # define XCAST(fun) (void*)
1176 #endif
1177
1178 static const IDirectInputDevice8WVtbl SysMouseWvt =
1179 {
1180 IDirectInputDevice2WImpl_QueryInterface,
1181 XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
1182 XCAST(Release)SysMouseAImpl_Release,
1183 XCAST(GetCapabilities)SysMouseAImpl_GetCapabilities,
1184 SysMouseWImpl_EnumObjects,
1185 XCAST(GetProperty)SysMouseAImpl_GetProperty,
1186 XCAST(SetProperty)SysMouseAImpl_SetProperty,
1187 XCAST(Acquire)SysMouseAImpl_Acquire,
1188 XCAST(Unacquire)SysMouseAImpl_Unacquire,
1189 XCAST(GetDeviceState)SysMouseAImpl_GetDeviceState,
1190 XCAST(GetDeviceData)SysMouseAImpl_GetDeviceData,
1191 XCAST(SetDataFormat)SysMouseAImpl_SetDataFormat,
1192 XCAST(SetEventNotification)SysMouseAImpl_SetEventNotification,
1193 XCAST(SetCooperativeLevel)SysMouseAImpl_SetCooperativeLevel,
1194 IDirectInputDevice2WImpl_GetObjectInfo,
1195 SysMouseWImpl_GetDeviceInfo,
1196 XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel,
1197 XCAST(Initialize)IDirectInputDevice2AImpl_Initialize,
1198 XCAST(CreateEffect)IDirectInputDevice2AImpl_CreateEffect,
1199 IDirectInputDevice2WImpl_EnumEffects,
1200 IDirectInputDevice2WImpl_GetEffectInfo,
1201 XCAST(GetForceFeedbackState)IDirectInputDevice2AImpl_GetForceFeedbackState,
1202 XCAST(SendForceFeedbackCommand)IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1203 XCAST(EnumCreatedEffectObjects)IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1204 XCAST(Escape)IDirectInputDevice2AImpl_Escape,
1205 XCAST(Poll)SysMouseAImpl_Poll,
1206 XCAST(SendDeviceData)IDirectInputDevice2AImpl_SendDeviceData,
1207 IDirectInputDevice7WImpl_EnumEffectsInFile,
1208 IDirectInputDevice7WImpl_WriteEffectToFile,
1209 IDirectInputDevice8WImpl_BuildActionMap,
1210 IDirectInputDevice8WImpl_SetActionMap,
1211 IDirectInputDevice8WImpl_GetImageInfo
1212 };
1213 #undef XCAST