3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
9 * - Tomb Raider 2 Demo:
10 * Playable using keyboard only.
11 * - WingCommander Prophecy Demo:
12 * Doesn't get Input Focus.
14 * - Fallout : works great in X and DGA mode
16 * FIXME: The keyboard handling needs to (and will) be merged into keyboard.c
17 * (The current implementation is currently only a proof of concept and
26 #ifdef HAVE_SYS_SIGNAL_H
27 #include <sys/signal.h>
30 #include "wine/obj_base.h"
31 #include "debugtools.h"
37 #include "sysmetrics.h"
42 DEFAULT_DEBUG_CHANNEL(dinput)
44 extern BYTE InputKeyStateTable[256];
45 extern int min_keycode, max_keycode;
46 extern WORD keyc2vkey[256];
48 static ICOM_VTABLE(IDirectInputA) ddiavt;
49 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt;
50 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt;
52 typedef struct IDirectInputAImpl IDirectInputAImpl;
53 typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
54 typedef struct SysKeyboardAImpl SysKeyboardAImpl;
55 typedef struct SysMouseAImpl SysMouseAImpl;
57 struct IDirectInputDevice2AImpl
59 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
64 struct SysKeyboardAImpl
66 /* IDirectInputDevice2AImpl */
67 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
70 /* SysKeyboardAImpl */
76 /* IDirectInputDevice2AImpl */
77 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
84 /* Previous position for relative moves */
86 LPMOUSE_EVENT_PROC prev_handler;
88 DWORD win_centerX, win_centerY;
89 LPDIDEVICEOBJECTDATA data_queue;
90 int queue_pos, queue_len;
94 CRITICAL_SECTION crit;
97 static int evsequence=0;
100 /* UIDs for Wine "drivers".
101 When enumerating each device supporting DInput, they have two UIDs :
104 static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
108 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
110 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
114 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
117 /* FIXME: This is ugly and not thread safe :/ */
118 static IDirectInputDevice2A* current_lock = NULL;
120 /******************************************************************************
121 * Various debugging tools
123 static void _dump_cooperativelevel(DWORD dwFlags) {
129 #define FE(x) { x, #x},
133 FE(DISCL_NONEXCLUSIVE)
135 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
136 if (flags[i].mask & dwFlags)
137 DPRINTF("%s ",flags[i].name);
141 struct IDirectInputAImpl
143 ICOM_VTABLE(IDirectInputA)* lpvtbl;
147 /******************************************************************************
148 * DirectInputCreate32A
150 HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
152 IDirectInputAImpl* This;
153 TRACE("(0x%08lx,%04lx,%p,%p)\n",
154 (DWORD)hinst,dwVersion,ppDI,punkOuter
156 This = (IDirectInputAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputAImpl));
158 This->lpvtbl = &ddiavt;
159 *ppDI=(IDirectInputA*)This;
162 /******************************************************************************
163 * IDirectInputA_EnumDevices
165 static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
166 LPDIRECTINPUTA iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
167 LPVOID pvRef, DWORD dwFlags
170 ICOM_THIS(IDirectInputAImpl,iface);
171 DIDEVICEINSTANCEA devInstance;
174 TRACE("(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
176 devInstance.dwSize = sizeof(DIDEVICEINSTANCEA);
177 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
178 /* Return keyboard */
179 devInstance.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
180 devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
181 devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
182 strcpy(devInstance.tszInstanceName, "Keyboard");
183 strcpy(devInstance.tszProductName, "Wine Keyboard");
185 ret = lpCallback(&devInstance, pvRef);
186 TRACE("Keyboard registered\n");
187 if (ret == DIENUM_STOP)
191 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_MOUSE)) {
193 devInstance.guidInstance = GUID_SysMouse;/* DInput's GUID */
194 devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
195 devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
196 strcpy(devInstance.tszInstanceName, "Mouse");
197 strcpy(devInstance.tszProductName, "Wine Mouse");
199 ret = lpCallback(&devInstance, pvRef);
200 TRACE("Mouse registered\n");
202 /* Should also do joystick enumerations.... */
206 static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUTA iface)
208 ICOM_THIS(IDirectInputAImpl,iface);
209 return ++(This->ref);
212 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
214 ICOM_THIS(IDirectInputAImpl,iface);
215 if (!(--This->ref)) {
216 HeapFree(GetProcessHeap(),0,This);
222 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
223 LPDIRECTINPUTA iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
226 ICOM_THIS(IDirectInputAImpl,iface);
229 WINE_StringFromCLSID(rguid,xbuf);
230 FIXME("(this=%p,%s,%p,%p): stub\n",This,xbuf,pdev,punk);
231 if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) || /* Generic Keyboard */
232 (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
233 SysKeyboardAImpl* newDevice;
234 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
236 newDevice->lpvtbl = &SysKeyboardAvt;
237 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
238 memset(newDevice->keystate,0,256);
239 *pdev=(IDirectInputDeviceA*)newDevice;
242 if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) || /* Generic Mouse */
243 (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysMouse)))) { /* Wine Mouse */
244 SysMouseAImpl* newDevice;
245 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
247 newDevice->lpvtbl = &SysMouseAvt;
248 InitializeCriticalSection(&(newDevice->crit));
249 MakeCriticalSectionGlobal(&(newDevice->crit));
250 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
251 *pdev=(IDirectInputDeviceA*)newDevice;
257 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
258 LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj
260 ICOM_THIS(IDirectInputAImpl,iface);
263 WINE_StringFromCLSID(riid,xbuf);
264 TRACE("(this=%p,%s,%p)\n",This,xbuf,ppobj);
265 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
266 IDirectInputA_AddRef(iface);
270 if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
271 IDirectInputA_AddRef(iface);
278 static HRESULT WINAPI IDirectInputAImpl_Initialize(
279 LPDIRECTINPUTA iface,HINSTANCE hinst,DWORD x
281 return DIERR_ALREADYINITIALIZED;
284 static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
286 ICOM_THIS(IDirectInputAImpl,iface);
289 WINE_StringFromCLSID(rguid,xbuf);
290 FIXME("(%p)->(%s): stub\n",This,xbuf);
295 static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUTA iface,
298 ICOM_THIS(IDirectInputAImpl,iface);
299 FIXME("(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
304 static ICOM_VTABLE(IDirectInputA) ddiavt =
306 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
307 IDirectInputAImpl_QueryInterface,
308 IDirectInputAImpl_AddRef,
309 IDirectInputAImpl_Release,
310 IDirectInputAImpl_CreateDevice,
311 IDirectInputAImpl_EnumDevices,
312 IDirectInputAImpl_GetDeviceStatus,
313 IDirectInputAImpl_RunControlPanel,
314 IDirectInputAImpl_Initialize
317 /******************************************************************************
318 * IDirectInputDeviceA
321 static HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
322 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
326 TRACE(dinput,"(this=%p,%p)\n",This,df);
328 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
329 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
330 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
331 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
332 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
334 for (i=0;i<df->dwNumObjs;i++) {
337 if (df->rgodf[i].pguid)
338 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
340 strcpy(xbuf,"<no guid>");
341 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
342 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
343 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
344 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
350 static HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
351 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
353 ICOM_THIS(IDirectInputDevice2AImpl,iface);
354 FIXME("(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
355 if (TRACE_ON(dinput))
356 _dump_cooperativelevel(dwflags);
360 static HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
361 LPDIRECTINPUTDEVICE2A iface,HANDLE hnd
363 ICOM_THIS(IDirectInputDevice2AImpl,iface);
364 FIXME("(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
368 static ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE2A iface)
370 ICOM_THIS(IDirectInputDevice2AImpl,iface);
374 HeapFree(GetProcessHeap(),0,This);
378 static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
379 LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
382 ICOM_THIS(SysKeyboardAImpl,iface);
386 WINE_StringFromCLSID(rguid,xbuf);
388 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
389 TRACE("(this=%p,%s,%p)\n",This,xbuf,ph);
390 TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
391 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
392 if (!HIWORD(rguid)) {
393 switch ((DWORD)rguid) {
394 case (DWORD) DIPROP_BUFFERSIZE: {
395 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
397 TRACE("(buffersize=%ld)\n",pd->dwData);
401 WARN("Unknown type %ld\n",(DWORD)rguid);
408 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
409 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
412 return KEYBOARD_Driver->pGetDIState(len, ptr)?DI_OK:E_FAIL;
415 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
416 LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
417 LPDWORD entries,DWORD flags
420 ICOM_THIS(SysKeyboardAImpl,iface);
424 TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
425 This,dodsize,dod,entries,entries?*entries:0,flags);
427 ret=KEYBOARD_Driver->pGetDIData(
428 This->keystate, dodsize, dod, entries, flags)?DI_OK:E_FAIL;
429 for (i=0;i<*entries;i++) {
430 dod[i].dwTimeStamp = time(NULL);
431 dod[i].dwSequence = evsequence++;
436 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
438 ICOM_THIS(SysKeyboardAImpl,iface);
439 TRACE("(this=%p): stub\n",This);
443 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
445 ICOM_THIS(SysKeyboardAImpl,iface);
446 TRACE("(this=%p): stub\n",This);
450 static HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
451 LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
454 ICOM_THIS(IDirectInputDevice2AImpl,iface);
457 WINE_StringFromCLSID(riid,xbuf);
458 TRACE("(this=%p,%s,%p)\n",This,xbuf,ppobj);
459 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
460 IDirectInputDevice2_AddRef(iface);
464 if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
465 IDirectInputDevice2_AddRef(iface);
469 if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
470 IDirectInputDevice2_AddRef(iface);
477 static ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
478 LPDIRECTINPUTDEVICE2A iface)
480 ICOM_THIS(IDirectInputDevice2AImpl,iface);
484 static HRESULT WINAPI IDirectInputDevice2AImpl_GetCapabilities(
485 LPDIRECTINPUTDEVICE2A iface,
486 LPDIDEVCAPS lpDIDevCaps)
488 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
493 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
494 LPDIRECTINPUTDEVICE2A iface,
495 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
502 lpCallback(NULL, lpvRef);
507 static HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
508 LPDIRECTINPUTDEVICE2A iface,
510 LPDIPROPHEADER pdiph)
516 static HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
517 LPDIRECTINPUTDEVICE2A iface,
518 LPDIDEVICEOBJECTINSTANCEA pdidoi,
526 static HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
527 LPDIRECTINPUTDEVICE2A iface,
528 LPDIDEVICEINSTANCEA pdidi)
534 static HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
535 LPDIRECTINPUTDEVICE2A iface,
543 static HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
544 LPDIRECTINPUTDEVICE2A iface,
553 /******************************************************************************
554 * IDirectInputDevice2A
557 static HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
558 LPDIRECTINPUTDEVICE2A iface,
561 LPDIRECTINPUTEFFECT *ppdef,
568 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
569 LPDIRECTINPUTDEVICE2A iface,
570 LPDIENUMEFFECTSCALLBACKA lpCallback,
576 lpCallback(NULL, lpvRef);
580 static HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
581 LPDIRECTINPUTDEVICE2A iface,
582 LPDIEFFECTINFOA lpdei,
589 static HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
590 LPDIRECTINPUTDEVICE2A iface,
597 static HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
598 LPDIRECTINPUTDEVICE2A iface,
605 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
606 LPDIRECTINPUTDEVICE2A iface,
607 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
613 lpCallback(NULL, lpvRef);
617 static HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
618 LPDIRECTINPUTDEVICE2A iface,
619 LPDIEFFESCAPE lpDIEEsc)
625 static HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
626 LPDIRECTINPUTDEVICE2A iface)
632 static HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
633 LPDIRECTINPUTDEVICE2A iface,
635 LPDIDEVICEOBJECTDATA rgdod,
643 /******************************************************************************
644 * SysMouseA (DInput Mouse support)
647 /******************************************************************************
648 * Release : release the mouse buffer.
650 static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
652 ICOM_THIS(SysMouseAImpl,iface);
658 /* Free the data queue */
659 if (This->data_queue != NULL)
660 HeapFree(GetProcessHeap(),0,This->data_queue);
662 /* Install the previous event handler (in case of releasing an aquired
664 if (This->prev_handler != NULL)
665 MOUSE_Enable(This->prev_handler);
666 DeleteCriticalSection(&(This->crit));
668 HeapFree(GetProcessHeap(),0,This);
673 /******************************************************************************
674 * SetCooperativeLevel : store the window in which we will do our
677 static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
678 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
681 ICOM_THIS(SysMouseAImpl,iface);
683 TRACE("(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
685 if (TRACE_ON(dinput))
686 _dump_cooperativelevel(dwflags);
688 /* Store the window which asks for the mouse */
695 /******************************************************************************
696 * SetDataFormat : the application can choose the format of the data
697 * the device driver sends back with GetDeviceState.
699 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
700 * in absolute and relative mode.
702 static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
703 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
706 ICOM_THIS(SysMouseAImpl,iface);
709 TRACE("(this=%p,%p)\n",This,df);
711 TRACE("(df.dwSize=%ld)\n",df->dwSize);
712 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
713 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
714 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
715 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
717 for (i=0;i<df->dwNumObjs;i++) {
720 if (df->rgodf[i].pguid)
721 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
723 strcpy(xbuf,"<no guid>");
724 TRACE("df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
725 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
726 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
727 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
730 /* Check size of data format to prevent crashes if the applications
731 sends a smaller buffer */
732 if (df->dwDataSize != sizeof(struct DIMOUSESTATE)) {
733 FIXME("non-standard mouse configuration not supported yet.");
734 return DIERR_INVALIDPARAM;
737 /* For the moment, ignore these fields and return always as if
738 c_dfDIMouse was passed as format... */
740 /* Check if the mouse is in absolute or relative mode */
741 if (df->dwFlags == DIDF_ABSAXIS)
743 else if (df->dwFlags == DIDF_RELAXIS)
746 ERR("Neither absolute nor relative flag set.");
748 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
749 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
753 #define GEN_EVENT(offset,data,xtime,seq) \
755 if (This->queue_pos < This->queue_len) { \
756 This->data_queue[This->queue_pos].dwOfs = offset; \
757 This->data_queue[This->queue_pos].dwData = data; \
758 This->data_queue[This->queue_pos].dwTimeStamp = xtime; \
759 This->data_queue[This->queue_pos].dwSequence = seq; \
765 /* Our private mouse event handler */
766 static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
767 DWORD cButtons, DWORD dwExtraInfo )
769 DWORD posX, posY, keyState, xtime, extra;
770 SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
772 EnterCriticalSection(&(This->crit));
773 /* Mouse moved -> send event if asked */
775 SetEvent(This->hEvent);
777 if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
778 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
779 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
780 keyState = wme->keyState;
782 extra = (DWORD)wme->hWnd;
784 assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
785 posX = (dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
786 posY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
788 ERR("Mouse event not supported...\n");
789 LeaveCriticalSection(&(This->crit));
793 TRACE(" %ld %ld ", posX, posY);
795 if ( dwFlags & MOUSEEVENTF_MOVE ) {
796 if (This->absolute) {
797 if (posX != This->prevX)
798 GEN_EVENT(DIMOFS_X, posX, xtime, 0);
799 if (posY != This->prevY)
800 GEN_EVENT(DIMOFS_Y, posY, xtime, 0);
802 /* Relative mouse input : the real fun starts here... */
803 if (This->need_warp) {
804 if (posX != This->prevX)
805 GEN_EVENT(DIMOFS_X, posX - This->prevX, xtime, evsequence++);
806 if (posY != This->prevY)
807 GEN_EVENT(DIMOFS_Y, posY - This->prevY, xtime, evsequence++);
809 /* This is the first time the event handler has been called after a
810 GetData of GetState. */
811 if (posX != This->win_centerX) {
812 GEN_EVENT(DIMOFS_X, posX - This->win_centerX, xtime, evsequence++);
816 if (posY != This->win_centerY) {
817 GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, xtime, evsequence++);
823 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
824 if (TRACE_ON(dinput))
827 GEN_EVENT(DIMOFS_BUTTON0, 0xFF, xtime, evsequence++);
829 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
830 if (TRACE_ON(dinput))
833 GEN_EVENT(DIMOFS_BUTTON0, 0x00, xtime, evsequence++);
835 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
836 if (TRACE_ON(dinput))
839 GEN_EVENT(DIMOFS_BUTTON1, 0xFF, xtime, evsequence++);
841 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
842 if (TRACE_ON(dinput))
845 GEN_EVENT(DIMOFS_BUTTON1, 0x00, xtime, evsequence++);
847 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
848 if (TRACE_ON(dinput))
851 GEN_EVENT(DIMOFS_BUTTON2, 0xFF, xtime, evsequence++);
853 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
854 if (TRACE_ON(dinput))
857 GEN_EVENT(DIMOFS_BUTTON2, 0x00, xtime, evsequence++);
859 if (TRACE_ON(dinput))
864 LeaveCriticalSection(&(This->crit));
868 /******************************************************************************
869 * Acquire : gets exclusive control of the mouse
871 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
873 ICOM_THIS(SysMouseAImpl,iface);
876 TRACE("(this=%p)\n",This);
878 if (This->acquired == 0) {
881 /* This stores the current mouse handler. */
882 This->prev_handler = mouse_event;
884 /* Store (in a global variable) the current lock */
885 current_lock = (IDirectInputDevice2A*)This;
887 /* Install our own mouse event handler */
888 MOUSE_Enable(dinput_mouse_event);
890 /* Get the window dimension and find the center */
891 GetWindowRect(This->win, &rect);
892 This->win_centerX = (rect.right - rect.left) / 2;
893 This->win_centerY = (rect.bottom - rect.top ) / 2;
895 /* Warp the mouse to the center of the window */
896 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
897 point.x = This->win_centerX;
898 point.y = This->win_centerY;
899 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
900 DISPLAY_MoveCursor(point.x, point.y);
907 /******************************************************************************
908 * Unacquire : frees the mouse
910 static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
912 ICOM_THIS(SysMouseAImpl,iface);
914 TRACE("(this=%p)\n",This);
916 /* Reinstall previous mouse event handler */
917 MOUSE_Enable(This->prev_handler);
918 This->prev_handler = NULL;
923 /* Unacquire device */
929 /******************************************************************************
930 * GetDeviceState : returns the "state" of the mouse.
932 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
935 static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
936 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
938 ICOM_THIS(SysMouseAImpl,iface);
940 struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
942 TRACE("(this=%p,0x%08lx,%p): \n",This,len,ptr);
944 /* Check if the buffer is big enough */
945 if (len < sizeof(struct DIMOUSESTATE)) {
946 FIXME("unsupported state structure.");
947 return DIERR_INVALIDPARAM;
950 /* Get the mouse position */
951 EVENT_QueryPointer(&rx, &ry, &state);
952 TRACE("(X:%ld - Y:%ld)\n", rx, ry);
954 /* Fill the mouse state structure */
955 if (This->absolute) {
959 mstate->lX = rx - This->win_centerX;
960 mstate->lY = ry - This->win_centerY;
962 if ((mstate->lX != 0) || (mstate->lY != 0))
966 mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00);
967 mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00);
968 mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00);
969 mstate->rgbButtons[3] = 0x00;
971 /* Check if we need to do a mouse warping */
972 if (This->need_warp) {
975 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
976 point.x = This->win_centerX;
977 point.y = This->win_centerY;
978 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
979 DISPLAY_MoveCursor(point.x, point.y);
984 TRACE("(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
985 mstate->lX, mstate->lY,
986 mstate->rgbButtons[0], mstate->rgbButtons[2], mstate->rgbButtons[1]);
991 /******************************************************************************
992 * GetDeviceState : gets buffered input data.
994 static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
996 LPDIDEVICEOBJECTDATA dod,
1000 ICOM_THIS(SysMouseAImpl,iface);
1002 EnterCriticalSection(&(This->crit));
1003 TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
1005 if (flags & DIGDD_PEEK)
1006 FIXME("DIGDD_PEEK\n");
1009 *entries = This->queue_pos;
1010 This->queue_pos = 0;
1012 /* Check for buffer overflow */
1013 if (This->queue_pos > *entries) {
1014 WARN("Buffer overflow not handled properly yet...\n");
1015 This->queue_pos = *entries;
1017 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1018 ERR("Wrong structure size !\n");
1019 LeaveCriticalSection(&(This->crit));
1020 return DIERR_INVALIDPARAM;
1023 if (This->queue_pos)
1024 TRACE("Application retrieving %d event(s).\n", This->queue_pos);
1026 /* Copy the buffered data into the application queue */
1027 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1028 *entries = This->queue_pos;
1030 /* Reset the event queue */
1031 This->queue_pos = 0;
1033 LeaveCriticalSection(&(This->crit));
1035 #if 0 /* FIXME: seems to create motion events, which fire back at us. */
1036 /* Check if we need to do a mouse warping */
1037 if (This->need_warp) {
1040 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1041 point.x = This->win_centerX;
1042 point.y = This->win_centerY;
1043 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1045 DISPLAY_MoveCursor(point.x, point.y);
1047 This->need_warp = 0;
1053 /******************************************************************************
1054 * SetProperty : change input device properties
1056 static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1060 ICOM_THIS(SysMouseAImpl,iface);
1064 WINE_StringFromCLSID(rguid,xbuf);
1066 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1068 TRACE("(this=%p,%s,%p)\n",This,xbuf,ph);
1070 if (!HIWORD(rguid)) {
1071 switch ((DWORD)rguid) {
1072 case (DWORD) DIPROP_BUFFERSIZE: {
1073 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1075 TRACE("buffersize = %ld\n",pd->dwData);
1077 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1078 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1079 This->queue_pos = 0;
1080 This->queue_len = pd->dwData;
1084 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1092 /******************************************************************************
1093 * SetEventNotification : specifies event to be sent on state change
1095 static HRESULT WINAPI SysMouseAImpl_SetEventNotification(LPDIRECTINPUTDEVICE2A iface,
1097 ICOM_THIS(SysMouseAImpl,iface);
1099 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1108 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt =
1110 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1111 IDirectInputDevice2AImpl_QueryInterface,
1112 IDirectInputDevice2AImpl_AddRef,
1113 IDirectInputDevice2AImpl_Release,
1114 IDirectInputDevice2AImpl_GetCapabilities,
1115 IDirectInputDevice2AImpl_EnumObjects,
1116 IDirectInputDevice2AImpl_GetProperty,
1117 SysKeyboardAImpl_SetProperty,
1118 SysKeyboardAImpl_Acquire,
1119 SysKeyboardAImpl_Unacquire,
1120 SysKeyboardAImpl_GetDeviceState,
1121 SysKeyboardAImpl_GetDeviceData,
1122 IDirectInputDevice2AImpl_SetDataFormat,
1123 IDirectInputDevice2AImpl_SetEventNotification,
1124 IDirectInputDevice2AImpl_SetCooperativeLevel,
1125 IDirectInputDevice2AImpl_GetObjectInfo,
1126 IDirectInputDevice2AImpl_GetDeviceInfo,
1127 IDirectInputDevice2AImpl_RunControlPanel,
1128 IDirectInputDevice2AImpl_Initialize,
1129 IDirectInputDevice2AImpl_CreateEffect,
1130 IDirectInputDevice2AImpl_EnumEffects,
1131 IDirectInputDevice2AImpl_GetEffectInfo,
1132 IDirectInputDevice2AImpl_GetForceFeedbackState,
1133 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1134 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1135 IDirectInputDevice2AImpl_Escape,
1136 IDirectInputDevice2AImpl_Poll,
1137 IDirectInputDevice2AImpl_SendDeviceData,
1140 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt =
1142 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1143 IDirectInputDevice2AImpl_QueryInterface,
1144 IDirectInputDevice2AImpl_AddRef,
1145 SysMouseAImpl_Release,
1146 IDirectInputDevice2AImpl_GetCapabilities,
1147 IDirectInputDevice2AImpl_EnumObjects,
1148 IDirectInputDevice2AImpl_GetProperty,
1149 SysMouseAImpl_SetProperty,
1150 SysMouseAImpl_Acquire,
1151 SysMouseAImpl_Unacquire,
1152 SysMouseAImpl_GetDeviceState,
1153 SysMouseAImpl_GetDeviceData,
1154 SysMouseAImpl_SetDataFormat,
1155 SysMouseAImpl_SetEventNotification,
1156 SysMouseAImpl_SetCooperativeLevel,
1157 IDirectInputDevice2AImpl_GetObjectInfo,
1158 IDirectInputDevice2AImpl_GetDeviceInfo,
1159 IDirectInputDevice2AImpl_RunControlPanel,
1160 IDirectInputDevice2AImpl_Initialize,
1161 IDirectInputDevice2AImpl_CreateEffect,
1162 IDirectInputDevice2AImpl_EnumEffects,
1163 IDirectInputDevice2AImpl_GetEffectInfo,
1164 IDirectInputDevice2AImpl_GetForceFeedbackState,
1165 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1166 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1167 IDirectInputDevice2AImpl_Escape,
1168 IDirectInputDevice2AImpl_Poll,
1169 IDirectInputDevice2AImpl_SendDeviceData,