1 /* DirectInput Mouse device
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
10 #ifdef HAVE_SYS_ERRNO_H
11 # include <sys/errno.h>
14 #include "debugtools.h"
25 #include "dinput_private.h"
26 #include "device_private.h"
30 DEFAULT_DEBUG_CHANNEL(dinput
);
32 /* Wine mouse driver object instances */
33 #define WINE_MOUSE_X_AXIS_INSTANCE 0x0001
34 #define WINE_MOUSE_Y_AXIS_INSTANCE 0x0002
35 #define WINE_MOUSE_L_BUTTON_INSTANCE 0x0004
36 #define WINE_MOUSE_R_BUTTON_INSTANCE 0x0008
37 #define WINE_MOUSE_M_BUTTON_INSTANCE 0x0010
39 /* ------------------------------- */
40 /* Wine mouse internal data format */
41 /* ------------------------------- */
43 /* Constants used to access the offset array */
44 #define WINE_MOUSE_X_POSITION 0
45 #define WINE_MOUSE_Y_POSITION 1
46 #define WINE_MOUSE_L_POSITION 2
47 #define WINE_MOUSE_R_POSITION 3
48 #define WINE_MOUSE_M_POSITION 4
54 } Wine_InternalMouseData
;
56 #define WINE_INTERNALMOUSE_NUM_OBJS 5
58 static DIOBJECTDATAFORMAT Wine_InternalMouseObjectFormat
[WINE_INTERNALMOUSE_NUM_OBJS
] = {
59 { &GUID_XAxis
, FIELD_OFFSET(Wine_InternalMouseData
, lX
),
60 DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE
) | DIDFT_RELAXIS
, 0 },
61 { &GUID_YAxis
, FIELD_OFFSET(Wine_InternalMouseData
, lY
),
62 DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE
) | DIDFT_RELAXIS
, 0 },
63 { &GUID_Button
, (FIELD_OFFSET(Wine_InternalMouseData
, rgbButtons
)) + 0,
64 DIDFT_MAKEINSTANCE(WINE_MOUSE_L_BUTTON_INSTANCE
) | DIDFT_PSHBUTTON
, 0 },
65 { &GUID_Button
, (FIELD_OFFSET(Wine_InternalMouseData
, rgbButtons
)) + 1,
66 DIDFT_MAKEINSTANCE(WINE_MOUSE_R_BUTTON_INSTANCE
) | DIDFT_PSHBUTTON
, 0 },
67 { &GUID_Button
, (FIELD_OFFSET(Wine_InternalMouseData
, rgbButtons
)) + 2,
68 DIDFT_MAKEINSTANCE(WINE_MOUSE_M_BUTTON_INSTANCE
) | DIDFT_PSHBUTTON
, 0 }
71 static DIDATAFORMAT Wine_InternalMouseFormat
= {
72 0, /* dwSize - unused */
73 0, /* dwObjsize - unused */
74 0, /* dwFlags - unused */
75 sizeof(Wine_InternalMouseData
),
76 WINE_INTERNALMOUSE_NUM_OBJS
, /* dwNumObjs */
77 Wine_InternalMouseObjectFormat
80 static ICOM_VTABLE(IDirectInputDevice2A
) SysMouseAvt
;
81 static ICOM_VTABLE(IDirectInputDevice7A
) SysMouse7Avt
;
82 typedef struct SysMouseAImpl SysMouseAImpl
;
85 WARP_NEEDED
, /* Warping is needed */
86 WARP_STARTED
, /* Warping has been done, waiting for the warp event */
87 WARP_DONE
/* Warping has been done */
92 /* IDirectInputDevice2AImpl */
93 ICOM_VFIELD(IDirectInputDevice2A
);
97 IDirectInputAImpl
*dinput
;
99 /* The current data format and the conversion between internal
100 and external data formats */
107 /* Previous position for relative moves */
109 LPMOUSE_EVENT_PROC prev_handler
;
111 DWORD win_centerX
, win_centerY
;
112 LPDIDEVICEOBJECTDATA data_queue
;
113 int queue_pos
, queue_len
;
114 WARP_STATUS need_warp
;
117 CRITICAL_SECTION crit
;
119 /* This is for mouse reporting. */
120 Wine_InternalMouseData m_state
;
123 static GUID DInput_Wine_Mouse_GUID
= { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
127 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
130 /* FIXME: This is ugly and not thread safe :/ */
131 static IDirectInputDevice2A
* current_lock
= NULL
;
134 static BOOL
mousedev_enum_device(DWORD dwDevType
, DWORD dwFlags
, LPCDIDEVICEINSTANCEA lpddi
)
136 if ((dwDevType
== 0) || (dwDevType
== DIDEVTYPE_MOUSE
)) {
137 TRACE("Enumerating the Mouse device\n");
140 lpddi
->guidInstance
= GUID_SysMouse
;/* DInput's GUID */
141 lpddi
->guidProduct
= DInput_Wine_Mouse_GUID
; /* Vendor's GUID */
142 lpddi
->dwDevType
= DIDEVTYPE_MOUSE
| (DIDEVTYPEMOUSE_UNKNOWN
<< 8);
143 strcpy(lpddi
->tszInstanceName
, "Mouse");
144 strcpy(lpddi
->tszProductName
, "Wine Mouse");
152 static SysMouseAImpl
*alloc_device(REFGUID rguid
, ICOM_VTABLE(IDirectInputDevice2A
) *mvt
, IDirectInputAImpl
*dinput
)
154 int offset_array
[5] = {
155 FIELD_OFFSET(Wine_InternalMouseData
, lX
),
156 FIELD_OFFSET(Wine_InternalMouseData
, lY
),
157 FIELD_OFFSET(Wine_InternalMouseData
, rgbButtons
) + 0,
158 FIELD_OFFSET(Wine_InternalMouseData
, rgbButtons
) + 1,
159 FIELD_OFFSET(Wine_InternalMouseData
, rgbButtons
) + 2
161 SysMouseAImpl
* newDevice
;
162 newDevice
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(SysMouseAImpl
));
164 ICOM_VTBL(newDevice
) = mvt
;
165 InitializeCriticalSection(&(newDevice
->crit
));
166 memcpy(&(newDevice
->guid
),rguid
,sizeof(*rguid
));
168 /* Per default, Wine uses its internal data format */
169 newDevice
->df
= &Wine_InternalMouseFormat
;
170 memcpy(newDevice
->offset_array
, offset_array
, 5 * sizeof(int));
171 newDevice
->wine_df
= (DataFormat
*) HeapAlloc(GetProcessHeap(), 0, sizeof(DataFormat
));
172 newDevice
->wine_df
->size
= 0;
173 newDevice
->wine_df
->internal_format_size
= Wine_InternalMouseFormat
.dwDataSize
;
174 newDevice
->wine_df
->dt
= NULL
;
175 newDevice
->dinput
= dinput
;
180 static HRESULT
mousedev_create_device(IDirectInputAImpl
*dinput
, REFGUID rguid
, REFIID riid
, LPDIRECTINPUTDEVICEA
* pdev
)
182 if ((IsEqualGUID(&GUID_SysMouse
,rguid
)) || /* Generic Mouse */
183 (IsEqualGUID(&DInput_Wine_Mouse_GUID
,rguid
))) { /* Wine Mouse */
184 if ((riid
== NULL
) || (IsEqualGUID(&IID_IDirectInputDevice2A
,riid
)) || (IsEqualGUID(&IID_IDirectInputDevice2A
,riid
))) {
185 *pdev
=(IDirectInputDeviceA
*) alloc_device(rguid
, &SysMouseAvt
, dinput
);
187 TRACE("Creating a Mouse device (%p)\n", *pdev
);
189 }else if (IsEqualGUID(&IID_IDirectInputDevice7A
,riid
)) {
190 *pdev
=(IDirectInputDeviceA
*) alloc_device(rguid
, (ICOM_VTABLE(IDirectInputDevice2A
) *) &SysMouse7Avt
, dinput
);
192 TRACE("Creating a Mouse DInput7A device (%p)\n", *pdev
);
195 return DIERR_NOINTERFACE
;
198 return DIERR_DEVICENOTREG
;
201 static dinput_device mousedev
= {
202 mousedev_enum_device
,
203 mousedev_create_device
206 DECL_GLOBAL_CONSTRUCTOR(mousedev_register
) { dinput_register_device(&mousedev
); }
208 /******************************************************************************
209 * SysMouseA (DInput Mouse support)
212 /******************************************************************************
213 * Release : release the mouse buffer.
215 static ULONG WINAPI
SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface
)
217 ICOM_THIS(SysMouseAImpl
,iface
);
223 /* Free the data queue */
224 if (This
->data_queue
!= NULL
)
225 HeapFree(GetProcessHeap(),0,This
->data_queue
);
227 /* Install the previous event handler (in case of releasing an acquired
229 if (This
->prev_handler
!= NULL
)
230 MOUSE_Enable(This
->prev_handler
);
231 DeleteCriticalSection(&(This
->crit
));
233 /* Free the DataFormat */
234 if (This
->df
!= &(Wine_InternalMouseFormat
)) {
235 HeapFree(GetProcessHeap(), 0, This
->df
->rgodf
);
236 HeapFree(GetProcessHeap(), 0, This
->df
);
239 HeapFree(GetProcessHeap(),0,This
);
244 /******************************************************************************
245 * SetCooperativeLevel : store the window in which we will do our
248 static HRESULT WINAPI
SysMouseAImpl_SetCooperativeLevel(
249 LPDIRECTINPUTDEVICE2A iface
,HWND hwnd
,DWORD dwflags
252 ICOM_THIS(SysMouseAImpl
,iface
);
254 TRACE("(this=%p,0x%08lx,0x%08lx)\n",This
,(DWORD
)hwnd
,dwflags
);
256 if (TRACE_ON(dinput
))
257 _dump_cooperativelevel_DI(dwflags
);
259 /* Store the window which asks for the mouse */
266 /******************************************************************************
267 * SetDataFormat : the application can choose the format of the data
268 * the device driver sends back with GetDeviceState.
270 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
271 * in absolute and relative mode.
273 static HRESULT WINAPI
SysMouseAImpl_SetDataFormat(
274 LPDIRECTINPUTDEVICE2A iface
,LPCDIDATAFORMAT df
277 ICOM_THIS(SysMouseAImpl
,iface
);
280 TRACE("(this=%p,%p)\n",This
,df
);
282 TRACE("(df.dwSize=%ld)\n",df
->dwSize
);
283 TRACE("(df.dwObjsize=%ld)\n",df
->dwObjSize
);
284 TRACE("(df.dwFlags=0x%08lx)\n",df
->dwFlags
);
285 TRACE("(df.dwDataSize=%ld)\n",df
->dwDataSize
);
286 TRACE("(df.dwNumObjs=%ld)\n",df
->dwNumObjs
);
288 for (i
=0;i
<df
->dwNumObjs
;i
++) {
290 TRACE("df.rgodf[%d].guid %s (%p)\n",i
, debugstr_guid(df
->rgodf
[i
].pguid
), df
->rgodf
[i
].pguid
);
291 TRACE("df.rgodf[%d].dwOfs %ld\n",i
,df
->rgodf
[i
].dwOfs
);
292 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df
->rgodf
[i
].dwType
),DIDFT_GETINSTANCE(df
->rgodf
[i
].dwType
));
293 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i
,df
->rgodf
[i
].dwFlags
);
296 /* Check if the mouse is in absolute or relative mode */
297 if (df
->dwFlags
== DIDF_ABSAXIS
)
299 else if (df
->dwFlags
== DIDF_RELAXIS
)
302 ERR("Neither absolute nor relative flag set.");
304 /* Store the new data format */
305 This
->df
= HeapAlloc(GetProcessHeap(),0,df
->dwSize
);
306 memcpy(This
->df
, df
, df
->dwSize
);
307 This
->df
->rgodf
= HeapAlloc(GetProcessHeap(),0,df
->dwNumObjs
*df
->dwObjSize
);
308 memcpy(This
->df
->rgodf
,df
->rgodf
,df
->dwNumObjs
*df
->dwObjSize
);
310 /* Prepare all the data-conversion filters */
311 This
->wine_df
= create_DataFormat(&(Wine_InternalMouseFormat
), df
, This
->offset_array
);
316 /* Our private mouse event handler */
317 static void WINAPI
dinput_mouse_event( DWORD dwFlags
, DWORD dx
, DWORD dy
,
318 DWORD cButtons
, DWORD dwExtraInfo
)
320 long posX
= -1, posY
= -1;
321 DWORD keyState
, xtime
, extra
;
322 SysMouseAImpl
* This
= (SysMouseAImpl
*) current_lock
;
324 EnterCriticalSection(&(This
->crit
));
325 /* Mouse moved -> send event if asked */
327 SetEvent(This
->hEvent
);
329 if ( !IsBadReadPtr( (LPVOID
)dwExtraInfo
, sizeof(WINE_MOUSEEVENT
) )
330 && ((WINE_MOUSEEVENT
*)dwExtraInfo
)->magic
== WINE_MOUSEEVENT_MAGIC
) {
331 WINE_MOUSEEVENT
*wme
= (WINE_MOUSEEVENT
*)dwExtraInfo
;
332 keyState
= wme
->keyState
;
334 extra
= (DWORD
)wme
->hWnd
;
336 if (dwFlags
& MOUSEEVENTF_MOVE
) {
337 if (dwFlags
& MOUSEEVENTF_ABSOLUTE
) {
338 posX
= (dx
* GetSystemMetrics(SM_CXSCREEN
)) >> 16;
339 posY
= (dy
* GetSystemMetrics(SM_CYSCREEN
)) >> 16;
341 if (This
->absolute
) {
342 if (posX
!= This
->prevX
)
343 GEN_EVENT(This
->offset_array
[WINE_MOUSE_X_POSITION
], posX
, xtime
, 0);
344 if (posY
!= This
->prevY
)
345 GEN_EVENT(This
->offset_array
[WINE_MOUSE_Y_POSITION
], posY
, xtime
, 0);
347 /* Now, warp handling */
348 if ((This
->need_warp
== WARP_STARTED
) &&
349 (posX
== This
->win_centerX
) && (posX
== This
->win_centerX
)) {
350 /* Warp has been done... */
351 This
->need_warp
= WARP_DONE
;
352 LeaveCriticalSection(&(This
->crit
));
356 /* Relative mouse input with absolute mouse event : the real fun starts here... */
357 if ((This
->need_warp
== WARP_NEEDED
) ||
358 (This
->need_warp
== WARP_STARTED
)) {
359 if (posX
!= This
->prevX
)
360 GEN_EVENT(This
->offset_array
[WINE_MOUSE_X_POSITION
], posX
- This
->prevX
, xtime
, (This
->dinput
->evsequence
)++);
361 if (posY
!= This
->prevY
)
362 GEN_EVENT(This
->offset_array
[WINE_MOUSE_Y_POSITION
], posY
- This
->prevY
, xtime
, (This
->dinput
->evsequence
)++);
364 /* This is the first time the event handler has been called after a
365 GetData of GetState. */
366 if (posX
!= This
->win_centerX
) {
367 GEN_EVENT(This
->offset_array
[WINE_MOUSE_X_POSITION
], posX
- This
->win_centerX
, xtime
, (This
->dinput
->evsequence
)++);
368 This
->need_warp
= WARP_NEEDED
;
371 if (posY
!= This
->win_centerY
) {
372 GEN_EVENT(This
->offset_array
[WINE_MOUSE_Y_POSITION
], posY
- This
->win_centerY
, xtime
, (This
->dinput
->evsequence
)++);
373 This
->need_warp
= WARP_NEEDED
;
381 if (This
->absolute
) {
382 This
->m_state
.lX
= posX
;
383 This
->m_state
.lY
= posY
;
385 This
->m_state
.lX
= posX
- This
->win_centerX
;
386 This
->m_state
.lY
= posY
- This
->win_centerY
;
389 /* Mouse reporting is in relative mode */
393 if (This
->absolute
) {
396 aposX
= This
->m_state
.lX
+ posX
;
399 if (aposX
>= GetSystemMetrics(SM_CXSCREEN
))
400 aposX
= GetSystemMetrics(SM_CXSCREEN
);
402 aposY
= This
->m_state
.lY
+ posY
;
405 if (aposY
>= GetSystemMetrics(SM_CYSCREEN
))
406 aposY
= GetSystemMetrics(SM_CYSCREEN
);
409 GEN_EVENT(This
->offset_array
[WINE_MOUSE_X_POSITION
], aposX
, xtime
, (This
->dinput
->evsequence
)++);
411 GEN_EVENT(This
->offset_array
[WINE_MOUSE_Y_POSITION
], aposY
, xtime
, (This
->dinput
->evsequence
)++);
413 This
->m_state
.lX
= aposX
;
414 This
->m_state
.lY
= aposY
;
417 GEN_EVENT(This
->offset_array
[WINE_MOUSE_X_POSITION
], posX
, xtime
, (This
->dinput
->evsequence
)++);
419 GEN_EVENT(This
->offset_array
[WINE_MOUSE_Y_POSITION
], posY
, xtime
, (This
->dinput
->evsequence
)++);
421 This
->m_state
.lX
= posX
;
422 This
->m_state
.lY
= posY
;
427 ERR("Mouse event not supported...\n");
428 LeaveCriticalSection(&(This
->crit
));
432 if (TRACE_ON(dinput
)) {
433 if (dwFlags
& MOUSEEVENTF_MOVE
)
434 TRACE(" %ld %ld (%s)", posX
, posY
,
435 (dwFlags
& MOUSEEVENTF_ABSOLUTE
? "abs" : "rel"));
437 if ( dwFlags
& MOUSEEVENTF_LEFTDOWN
) DPRINTF(" LD ");
438 if ( dwFlags
& MOUSEEVENTF_LEFTUP
) DPRINTF(" LU ");
440 if ( dwFlags
& MOUSEEVENTF_RIGHTDOWN
) DPRINTF(" RD ");
441 if ( dwFlags
& MOUSEEVENTF_RIGHTUP
) DPRINTF(" RU ");
443 if ( dwFlags
& MOUSEEVENTF_MIDDLEDOWN
) DPRINTF(" MD ");
444 if ( dwFlags
& MOUSEEVENTF_MIDDLEUP
) DPRINTF(" MU ");
446 if (!(This
->absolute
)) DPRINTF(" W=%d ", This
->need_warp
);
452 if ( dwFlags
& MOUSEEVENTF_LEFTDOWN
) {
453 GEN_EVENT(This
->offset_array
[WINE_MOUSE_L_POSITION
], 0xFF, xtime
, (This
->dinput
->evsequence
)++);
454 This
->m_state
.rgbButtons
[0] = 0xFF;
456 if ( dwFlags
& MOUSEEVENTF_LEFTUP
) {
457 GEN_EVENT(This
->offset_array
[WINE_MOUSE_L_POSITION
], 0x00, xtime
, (This
->dinput
->evsequence
)++);
458 This
->m_state
.rgbButtons
[0] = 0x00;
460 if ( dwFlags
& MOUSEEVENTF_RIGHTDOWN
) {
461 GEN_EVENT(This
->offset_array
[WINE_MOUSE_R_POSITION
], 0xFF, xtime
, (This
->dinput
->evsequence
)++);
462 This
->m_state
.rgbButtons
[1] = 0xFF;
464 if ( dwFlags
& MOUSEEVENTF_RIGHTUP
) {
465 GEN_EVENT(This
->offset_array
[WINE_MOUSE_R_POSITION
], 0x00, xtime
, (This
->dinput
->evsequence
)++);
466 This
->m_state
.rgbButtons
[1] = 0x00;
468 if ( dwFlags
& MOUSEEVENTF_MIDDLEDOWN
) {
469 GEN_EVENT(This
->offset_array
[WINE_MOUSE_M_POSITION
], 0xFF, xtime
, (This
->dinput
->evsequence
)++);
470 This
->m_state
.rgbButtons
[2] = 0xFF;
472 if ( dwFlags
& MOUSEEVENTF_MIDDLEUP
) {
473 GEN_EVENT(This
->offset_array
[WINE_MOUSE_M_POSITION
], 0x00, xtime
, (This
->dinput
->evsequence
)++);
474 This
->m_state
.rgbButtons
[2] = 0x00;
477 TRACE("(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
478 This
->m_state
.lX
, This
->m_state
.lY
,
479 This
->m_state
.rgbButtons
[0], This
->m_state
.rgbButtons
[2], This
->m_state
.rgbButtons
[1]);
481 LeaveCriticalSection(&(This
->crit
));
485 /******************************************************************************
486 * Acquire : gets exclusive control of the mouse
488 static HRESULT WINAPI
SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface
)
490 ICOM_THIS(SysMouseAImpl
,iface
);
493 TRACE("(this=%p)\n",This
);
495 if (This
->acquired
== 0) {
498 /* This stores the current mouse handler. */
499 This
->prev_handler
= mouse_event
;
501 /* Store (in a global variable) the current lock */
502 current_lock
= (IDirectInputDevice2A
*)This
;
504 /* Init the mouse state */
505 if (This
->absolute
) {
506 This
->m_state
.lX
= PosX
;
507 This
->m_state
.lY
= PosY
;
512 This
->m_state
.lX
= 0;
513 This
->m_state
.lY
= 0;
515 This
->m_state
.rgbButtons
[0] = (MouseButtonsStates
[0] ? 0xFF : 0x00);
516 This
->m_state
.rgbButtons
[1] = (MouseButtonsStates
[1] ? 0xFF : 0x00);
517 This
->m_state
.rgbButtons
[2] = (MouseButtonsStates
[2] ? 0xFF : 0x00);
519 /* Install our own mouse event handler */
520 MOUSE_Enable(dinput_mouse_event
);
522 /* Get the window dimension and find the center */
523 GetWindowRect(This
->win
, &rect
);
524 This
->win_centerX
= (rect
.right
- rect
.left
) / 2;
525 This
->win_centerY
= (rect
.bottom
- rect
.top
) / 2;
527 /* Warp the mouse to the center of the window */
528 if (This
->absolute
== 0) {
529 TRACE("Warping mouse to %ld - %ld\n", This
->win_centerX
, This
->win_centerY
);
530 point
.x
= This
->win_centerX
;
531 point
.y
= This
->win_centerY
;
532 MapWindowPoints(This
->win
, HWND_DESKTOP
, &point
, 1);
533 USER_Driver
.pMoveCursor( point
.x
, point
.y
);
535 This
->need_warp
= WARP_DONE
;
537 This
->need_warp
= WARP_STARTED
;
546 /******************************************************************************
547 * Unacquire : frees the mouse
549 static HRESULT WINAPI
SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface
)
551 ICOM_THIS(SysMouseAImpl
,iface
);
553 TRACE("(this=%p)\n",This
);
557 /* Reinstall previous mouse event handler */
558 MOUSE_Enable(This
->prev_handler
);
559 This
->prev_handler
= NULL
;
564 /* Unacquire device */
568 ERR("Unacquiring a not-acquired device !!!\n");
573 /******************************************************************************
574 * GetDeviceState : returns the "state" of the mouse.
576 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
579 static HRESULT WINAPI
SysMouseAImpl_GetDeviceState(
580 LPDIRECTINPUTDEVICE2A iface
,DWORD len
,LPVOID ptr
582 ICOM_THIS(SysMouseAImpl
,iface
);
584 EnterCriticalSection(&(This
->crit
));
585 TRACE("(this=%p,0x%08lx,%p): \n",This
,len
,ptr
);
587 /* Copy the current mouse state */
588 fill_DataFormat(ptr
, &(This
->m_state
), This
->wine_df
);
590 /* Initialize the buffer when in relative mode */
591 if (This
->absolute
== 0) {
592 This
->m_state
.lX
= 0;
593 This
->m_state
.lY
= 0;
596 /* Check if we need to do a mouse warping */
597 if (This
->need_warp
== WARP_NEEDED
) {
600 TRACE("Warping mouse to %ld - %ld\n", This
->win_centerX
, This
->win_centerY
);
601 point
.x
= This
->win_centerX
;
602 point
.y
= This
->win_centerY
;
603 MapWindowPoints(This
->win
, HWND_DESKTOP
, &point
, 1);
604 USER_Driver
.pMoveCursor( point
.x
, point
.y
);
607 This
->need_warp
= WARP_DONE
;
609 This
->need_warp
= WARP_STARTED
;
613 LeaveCriticalSection(&(This
->crit
));
615 TRACE("(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
616 This
->m_state
.lX
, This
->m_state
.lY
,
617 This
->m_state
.rgbButtons
[0], This
->m_state
.rgbButtons
[2], This
->m_state
.rgbButtons
[1]);
622 /******************************************************************************
623 * GetDeviceState : gets buffered input data.
625 static HRESULT WINAPI
SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface
,
627 LPDIDEVICEOBJECTDATA dod
,
631 ICOM_THIS(SysMouseAImpl
,iface
);
633 EnterCriticalSection(&(This
->crit
));
634 TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This
,dodsize
,*entries
,flags
);
636 if (flags
& DIGDD_PEEK
)
637 FIXME("DIGDD_PEEK\n");
640 *entries
= This
->queue_pos
;
643 /* Check for buffer overflow */
644 if (This
->queue_pos
> *entries
) {
645 WARN("Buffer overflow not handled properly yet...\n");
646 This
->queue_pos
= *entries
;
648 if (dodsize
!= sizeof(DIDEVICEOBJECTDATA
)) {
649 ERR("Wrong structure size !\n");
650 LeaveCriticalSection(&(This
->crit
));
651 return DIERR_INVALIDPARAM
;
655 TRACE("Application retrieving %d event(s).\n", This
->queue_pos
);
657 /* Copy the buffered data into the application queue */
658 memcpy(dod
, This
->data_queue
, This
->queue_pos
* dodsize
);
659 *entries
= This
->queue_pos
;
661 /* Reset the event queue */
664 LeaveCriticalSection(&(This
->crit
));
666 /* Check if we need to do a mouse warping */
667 if (This
->need_warp
== WARP_NEEDED
) {
670 TRACE("Warping mouse to %ld - %ld\n", This
->win_centerX
, This
->win_centerY
);
671 point
.x
= This
->win_centerX
;
672 point
.y
= This
->win_centerY
;
673 MapWindowPoints(This
->win
, HWND_DESKTOP
, &point
, 1);
675 USER_Driver
.pMoveCursor( point
.x
, point
.y
);
678 This
->need_warp
= WARP_DONE
;
680 This
->need_warp
= WARP_STARTED
;
686 /******************************************************************************
687 * SetProperty : change input device properties
689 static HRESULT WINAPI
SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface
,
693 ICOM_THIS(SysMouseAImpl
,iface
);
695 TRACE("(this=%p,%s,%p)\n",This
,debugstr_guid(rguid
),ph
);
697 if (!HIWORD(rguid
)) {
698 switch ((DWORD
)rguid
) {
699 case (DWORD
) DIPROP_BUFFERSIZE
: {
700 LPCDIPROPDWORD pd
= (LPCDIPROPDWORD
)ph
;
702 TRACE("buffersize = %ld\n",pd
->dwData
);
704 This
->data_queue
= (LPDIDEVICEOBJECTDATA
)HeapAlloc(GetProcessHeap(),0,
705 pd
->dwData
* sizeof(DIDEVICEOBJECTDATA
));
707 This
->queue_len
= pd
->dwData
;
710 case (DWORD
) DIPROP_AXISMODE
: {
711 LPCDIPROPDWORD pd
= (LPCDIPROPDWORD
)ph
;
712 This
->absolute
= !(pd
->dwData
);
713 TRACE("absolute mode: %d\n", This
->absolute
);
717 FIXME("Unknown type %ld (%s)\n",(DWORD
)rguid
,debugstr_guid(rguid
));
725 /******************************************************************************
726 * GetProperty : get input device properties
728 static HRESULT WINAPI
SysMouseAImpl_GetProperty(LPDIRECTINPUTDEVICE2A iface
,
730 LPDIPROPHEADER pdiph
)
732 ICOM_THIS(SysMouseAImpl
,iface
);
734 TRACE("(this=%p,%s,%p): stub!\n",
735 iface
, debugstr_guid(rguid
), pdiph
);
737 if (TRACE_ON(dinput
))
738 _dump_DIPROPHEADER(pdiph
);
740 if (!HIWORD(rguid
)) {
741 switch ((DWORD
)rguid
) {
742 case (DWORD
) DIPROP_BUFFERSIZE
: {
743 LPDIPROPDWORD pd
= (LPDIPROPDWORD
)pdiph
;
745 TRACE(" return buffersize = %d\n",This
->queue_len
);
746 pd
->dwData
= This
->queue_len
;
750 case (DWORD
) DIPROP_RANGE
: {
751 LPDIPROPRANGE pr
= (LPDIPROPRANGE
) pdiph
;
753 if ((pdiph
->dwHow
== DIPH_BYID
) &&
754 ((pdiph
->dwObj
== (DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE
) | DIDFT_RELAXIS
)) ||
755 (pdiph
->dwObj
== (DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE
) | DIDFT_RELAXIS
)))) {
756 /* Querying the range of either the X or the Y axis. As I do
757 not know the range, do as if the range where
759 pr
->lMin
= DIPROPRANGE_NOMIN
;
760 pr
->lMax
= DIPROPRANGE_NOMAX
;
767 FIXME("Unknown type %ld (%s)\n",(DWORD
)rguid
,debugstr_guid(rguid
));
778 /******************************************************************************
779 * SetEventNotification : specifies event to be sent on state change
781 static HRESULT WINAPI
SysMouseAImpl_SetEventNotification(LPDIRECTINPUTDEVICE2A iface
,
783 ICOM_THIS(SysMouseAImpl
,iface
);
785 TRACE("(this=%p,0x%08lx)\n",This
,(DWORD
)hnd
);
792 /******************************************************************************
793 * GetCapabilities : get the device capablitites
795 static HRESULT WINAPI
SysMouseAImpl_GetCapabilities(
796 LPDIRECTINPUTDEVICE2A iface
,
797 LPDIDEVCAPS lpDIDevCaps
)
799 ICOM_THIS(SysMouseAImpl
,iface
);
801 TRACE("(this=%p,%p)\n",This
,lpDIDevCaps
);
803 if (lpDIDevCaps
->dwSize
== sizeof(DIDEVCAPS
)) {
804 lpDIDevCaps
->dwFlags
= DIDC_ATTACHED
;
805 lpDIDevCaps
->dwDevType
= DIDEVTYPE_MOUSE
;
806 lpDIDevCaps
->dwAxes
= 2;
807 lpDIDevCaps
->dwButtons
= 3;
808 lpDIDevCaps
->dwPOVs
= 0;
809 lpDIDevCaps
->dwFFSamplePeriod
= 0;
810 lpDIDevCaps
->dwFFMinTimeResolution
= 0;
811 lpDIDevCaps
->dwFirmwareRevision
= 100;
812 lpDIDevCaps
->dwHardwareRevision
= 100;
813 lpDIDevCaps
->dwFFDriverVersion
= 0;
816 FIXME("DirectX 3.0 not supported....\n");
823 /******************************************************************************
824 * EnumObjects : enumerate the different buttons and axis...
826 static HRESULT WINAPI
SysMouseAImpl_EnumObjects(
827 LPDIRECTINPUTDEVICE2A iface
,
828 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback
,
832 ICOM_THIS(SysMouseAImpl
,iface
);
833 DIDEVICEOBJECTINSTANCEA ddoi
;
835 TRACE("(this=%p,%p,%p,%08lx)\n", This
, lpCallback
, lpvRef
, dwFlags
);
836 if (TRACE_ON(dinput
)) {
837 DPRINTF(" - flags = ");
838 _dump_EnumObjects_flags(dwFlags
);
842 /* Only the fields till dwFFMaxForce are relevant */
843 ddoi
.dwSize
= FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA
, dwFFMaxForce
);
845 /* In a mouse, we have : two relative axis and three buttons */
846 if ((dwFlags
== DIDFT_ALL
) ||
847 (dwFlags
& DIDFT_AXIS
)) {
849 ddoi
.guidType
= GUID_XAxis
;
850 ddoi
.dwOfs
= This
->offset_array
[WINE_MOUSE_X_POSITION
];
851 ddoi
.dwType
= DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE
) | DIDFT_RELAXIS
;
852 strcpy(ddoi
.tszName
, "X-Axis");
853 _dump_OBJECTINSTANCEA(&ddoi
);
854 if (lpCallback(&ddoi
, lpvRef
) != DIENUM_CONTINUE
) return DI_OK
;
857 ddoi
.guidType
= GUID_YAxis
;
858 ddoi
.dwOfs
= This
->offset_array
[WINE_MOUSE_Y_POSITION
];
859 ddoi
.dwType
= DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE
) | DIDFT_RELAXIS
;
860 strcpy(ddoi
.tszName
, "Y-Axis");
861 _dump_OBJECTINSTANCEA(&ddoi
);
862 if (lpCallback(&ddoi
, lpvRef
) != DIENUM_CONTINUE
) return DI_OK
;
865 if ((dwFlags
== DIDFT_ALL
) ||
866 (dwFlags
& DIDFT_BUTTON
)) {
867 ddoi
.guidType
= GUID_Button
;
870 ddoi
.dwOfs
= This
->offset_array
[WINE_MOUSE_L_POSITION
];
871 ddoi
.dwType
= DIDFT_MAKEINSTANCE(WINE_MOUSE_L_BUTTON_INSTANCE
) | DIDFT_PSHBUTTON
;
872 strcpy(ddoi
.tszName
, "Left-Button");
873 _dump_OBJECTINSTANCEA(&ddoi
);
874 if (lpCallback(&ddoi
, lpvRef
) != DIENUM_CONTINUE
) return DI_OK
;
877 ddoi
.dwOfs
= This
->offset_array
[WINE_MOUSE_R_POSITION
];
878 ddoi
.dwType
= DIDFT_MAKEINSTANCE(WINE_MOUSE_R_BUTTON_INSTANCE
) | DIDFT_PSHBUTTON
;
879 strcpy(ddoi
.tszName
, "Right-Button");
880 _dump_OBJECTINSTANCEA(&ddoi
);
881 if (lpCallback(&ddoi
, lpvRef
) != DIENUM_CONTINUE
) return DI_OK
;
884 ddoi
.dwOfs
= This
->offset_array
[WINE_MOUSE_M_POSITION
];
885 ddoi
.dwType
= DIDFT_MAKEINSTANCE(WINE_MOUSE_M_BUTTON_INSTANCE
) | DIDFT_PSHBUTTON
;
886 strcpy(ddoi
.tszName
, "Middle-Button");
887 _dump_OBJECTINSTANCEA(&ddoi
);
888 if (lpCallback(&ddoi
, lpvRef
) != DIENUM_CONTINUE
) return DI_OK
;
895 static ICOM_VTABLE(IDirectInputDevice2A
) SysMouseAvt
=
897 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
898 IDirectInputDevice2AImpl_QueryInterface
,
899 IDirectInputDevice2AImpl_AddRef
,
900 SysMouseAImpl_Release
,
901 SysMouseAImpl_GetCapabilities
,
902 SysMouseAImpl_EnumObjects
,
903 SysMouseAImpl_GetProperty
,
904 SysMouseAImpl_SetProperty
,
905 SysMouseAImpl_Acquire
,
906 SysMouseAImpl_Unacquire
,
907 SysMouseAImpl_GetDeviceState
,
908 SysMouseAImpl_GetDeviceData
,
909 SysMouseAImpl_SetDataFormat
,
910 SysMouseAImpl_SetEventNotification
,
911 SysMouseAImpl_SetCooperativeLevel
,
912 IDirectInputDevice2AImpl_GetObjectInfo
,
913 IDirectInputDevice2AImpl_GetDeviceInfo
,
914 IDirectInputDevice2AImpl_RunControlPanel
,
915 IDirectInputDevice2AImpl_Initialize
,
916 IDirectInputDevice2AImpl_CreateEffect
,
917 IDirectInputDevice2AImpl_EnumEffects
,
918 IDirectInputDevice2AImpl_GetEffectInfo
,
919 IDirectInputDevice2AImpl_GetForceFeedbackState
,
920 IDirectInputDevice2AImpl_SendForceFeedbackCommand
,
921 IDirectInputDevice2AImpl_EnumCreatedEffectObjects
,
922 IDirectInputDevice2AImpl_Escape
,
923 IDirectInputDevice2AImpl_Poll
,
924 IDirectInputDevice2AImpl_SendDeviceData
,
927 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
928 # define XCAST(fun) (typeof(SysMouse7Avt.fn##fun))
930 # define XCAST(fun) (void*)
933 static ICOM_VTABLE(IDirectInputDevice7A
) SysMouse7Avt
=
935 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
936 XCAST(QueryInterface
)IDirectInputDevice2AImpl_QueryInterface
,
937 XCAST(AddRef
)IDirectInputDevice2AImpl_AddRef
,
938 XCAST(Release
)SysMouseAImpl_Release
,
939 XCAST(GetCapabilities
)SysMouseAImpl_GetCapabilities
,
940 XCAST(EnumObjects
)SysMouseAImpl_EnumObjects
,
941 XCAST(GetProperty
)SysMouseAImpl_GetProperty
,
942 XCAST(SetProperty
)SysMouseAImpl_SetProperty
,
943 XCAST(Acquire
)SysMouseAImpl_Acquire
,
944 XCAST(Unacquire
)SysMouseAImpl_Unacquire
,
945 XCAST(GetDeviceState
)SysMouseAImpl_GetDeviceState
,
946 XCAST(GetDeviceData
)SysMouseAImpl_GetDeviceData
,
947 XCAST(SetDataFormat
)SysMouseAImpl_SetDataFormat
,
948 XCAST(SetEventNotification
)SysMouseAImpl_SetEventNotification
,
949 XCAST(SetCooperativeLevel
)SysMouseAImpl_SetCooperativeLevel
,
950 XCAST(GetObjectInfo
)IDirectInputDevice2AImpl_GetObjectInfo
,
951 XCAST(GetDeviceInfo
)IDirectInputDevice2AImpl_GetDeviceInfo
,
952 XCAST(RunControlPanel
)IDirectInputDevice2AImpl_RunControlPanel
,
953 XCAST(Initialize
)IDirectInputDevice2AImpl_Initialize
,
954 XCAST(CreateEffect
)IDirectInputDevice2AImpl_CreateEffect
,
955 XCAST(EnumEffects
)IDirectInputDevice2AImpl_EnumEffects
,
956 XCAST(GetEffectInfo
)IDirectInputDevice2AImpl_GetEffectInfo
,
957 XCAST(GetForceFeedbackState
)IDirectInputDevice2AImpl_GetForceFeedbackState
,
958 XCAST(SendForceFeedbackCommand
)IDirectInputDevice2AImpl_SendForceFeedbackCommand
,
959 XCAST(EnumCreatedEffectObjects
)IDirectInputDevice2AImpl_EnumCreatedEffectObjects
,
960 XCAST(Escape
)IDirectInputDevice2AImpl_Escape
,
961 XCAST(Poll
)IDirectInputDevice2AImpl_Poll
,
962 XCAST(SendDeviceData
)IDirectInputDevice2AImpl_SendDeviceData
,
963 IDirectInputDevice7AImpl_EnumEffectsInFile
,
964 IDirectInputDevice7AImpl_WriteEffectToFile