Reimplemented some code without using X11.
[wine/multimedia.git] / windows / dinput.c
blob60242a16872f327ca7133271b463c202d0aee0b3
1 /* DirectInput
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
6 */
7 /* Status:
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
18 * an utter mess.)
21 #include "config.h"
22 #include <string.h>
23 #include <unistd.h>
24 #include <assert.h>
25 #include <sys/signal.h>
27 #include "winuser.h"
28 #include "winerror.h"
29 #include "wine/obj_base.h"
30 #include "gdi.h"
31 #include "dinput.h"
32 #include "debug.h"
33 #include "message.h"
34 #include "display.h"
35 #include "mouse.h"
36 #include "sysmetrics.h"
38 extern BYTE InputKeyStateTable[256];
39 extern int min_keycode, max_keycode;
40 extern WORD keyc2vkey[256];
42 static ICOM_VTABLE(IDirectInputA) ddiavt;
43 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt;
44 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt;
46 typedef struct IDirectInputAImpl IDirectInputAImpl;
47 typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
48 typedef struct SysKeyboardAImpl SysKeyboardAImpl;
49 typedef struct SysMouseAImpl SysMouseAImpl;
51 struct IDirectInputDevice2AImpl
53 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
54 DWORD ref;
55 GUID guid;
58 struct SysKeyboardAImpl
60 /* IDirectInputDevice2AImpl */
61 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
62 DWORD ref;
63 GUID guid;
64 /* SysKeyboardAImpl */
65 BYTE keystate[256];
68 struct SysMouseAImpl
70 /* IDirectInputDevice2AImpl */
71 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
72 DWORD ref;
73 GUID guid;
74 /* SysMouseAImpl */
75 BYTE absolute;
76 /* Previous position for relative moves */
77 LONG prevX, prevY;
78 LPMOUSE_EVENT_PROC prev_handler;
79 HWND win;
80 DWORD win_centerX, win_centerY;
81 LPDIDEVICEOBJECTDATA data_queue;
82 int queue_pos, queue_len;
83 int need_warp;
84 int acquired;
88 /* UIDs for Wine "drivers".
89 When enumerating each device supporting DInput, they have two UIDs :
90 - the 'windows' UID
91 - a vendor UID */
92 static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
93 0x9e573ed8,
94 0x7734,
95 0x11d2,
96 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
98 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
99 0x0ab8648a,
100 0x7735,
101 0x11d2,
102 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
105 /* FIXME: This is ugly and not thread safe :/ */
106 static IDirectInputDevice2A* current_lock = NULL;
108 /******************************************************************************
109 * Various debugging tools
111 static void _dump_cooperativelevel(DWORD dwFlags) {
112 int i;
113 const struct {
114 DWORD mask;
115 char *name;
116 } flags[] = {
117 #define FE(x) { x, #x},
118 FE(DISCL_BACKGROUND)
119 FE(DISCL_EXCLUSIVE)
120 FE(DISCL_FOREGROUND)
121 FE(DISCL_NONEXCLUSIVE)
123 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
124 if (flags[i].mask & dwFlags)
125 DUMP("%s ",flags[i].name);
126 DUMP("\n");
129 struct IDirectInputAImpl
131 ICOM_VTABLE(IDirectInputA)* lpvtbl;
132 DWORD ref;
135 /******************************************************************************
136 * DirectInputCreate32A
138 HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
140 IDirectInputAImpl* This;
141 TRACE(dinput, "(0x%08lx,%04lx,%p,%p)\n",
142 (DWORD)hinst,dwVersion,ppDI,punkOuter
144 This = (IDirectInputAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputAImpl));
145 This->ref = 1;
146 This->lpvtbl = &ddiavt;
147 *ppDI=(IDirectInputA*)This;
148 return 0;
150 /******************************************************************************
151 * IDirectInputA_EnumDevices
153 static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
154 LPDIRECTINPUTA iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
155 LPVOID pvRef, DWORD dwFlags
158 ICOM_THIS(IDirectInputAImpl,iface);
159 DIDEVICEINSTANCEA devInstance;
160 int ret;
162 TRACE(dinput, "(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
164 devInstance.dwSize = sizeof(DIDEVICEINSTANCEA);
166 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
167 /* Return keyboard */
168 devInstance.guidInstance = GUID_SysKeyboard; /* DInput's GUID */
169 devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
170 devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
171 strcpy(devInstance.tszInstanceName, "Keyboard");
172 strcpy(devInstance.tszProductName, "Wine Keyboard");
174 ret = lpCallback(&devInstance, pvRef);
175 TRACE(dinput, "Keyboard registered\n");
177 if (ret == DIENUM_STOP)
178 return 0;
181 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
182 /* Return mouse */
183 devInstance.guidInstance = GUID_SysMouse; /* DInput's GUID */
184 devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
185 devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
186 strcpy(devInstance.tszInstanceName, "Mouse");
187 strcpy(devInstance.tszProductName, "Wine Mouse");
189 ret = lpCallback(&devInstance, pvRef);
190 TRACE(dinput, "Mouse registered\n");
193 /* Should also do joystick enumerations.... */
195 return 0;
198 static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUTA iface)
200 ICOM_THIS(IDirectInputAImpl,iface);
201 return ++(This->ref);
204 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
206 ICOM_THIS(IDirectInputAImpl,iface);
207 if (!(--This->ref)) {
208 HeapFree(GetProcessHeap(),0,This);
209 return 0;
211 return This->ref;
214 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
215 LPDIRECTINPUTA iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
216 LPUNKNOWN punk
218 ICOM_THIS(IDirectInputAImpl,iface);
219 char xbuf[50];
221 WINE_StringFromCLSID(rguid,xbuf);
222 FIXME(dinput,"(this=%p,%s,%p,%p): stub\n",This,xbuf,pdev,punk);
223 if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) || /* Generic Keyboard */
224 (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
225 SysKeyboardAImpl* newDevice;
226 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
227 newDevice->ref = 1;
228 newDevice->lpvtbl = &SysKeyboardAvt;
229 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
230 memset(newDevice->keystate,0,256);
231 *pdev=(IDirectInputDeviceA*)newDevice;
232 return DI_OK;
234 if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) || /* Generic Mouse */
235 (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysMouse)))) { /* Wine Mouse */
236 SysKeyboardAImpl* newDevice;
237 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
238 newDevice->ref = 1;
239 newDevice->lpvtbl = &SysMouseAvt;
240 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
241 *pdev=(IDirectInputDeviceA*)newDevice;
242 return DI_OK;
244 return E_FAIL;
247 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
248 LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj
250 ICOM_THIS(IDirectInputAImpl,iface);
251 char xbuf[50];
253 WINE_StringFromCLSID(riid,xbuf);
254 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ppobj);
255 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
256 IDirectInputA_AddRef(iface);
257 *ppobj = This;
258 return 0;
260 if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
261 IDirectInputA_AddRef(iface);
262 *ppobj = This;
263 return 0;
265 return E_FAIL;
268 static HRESULT WINAPI IDirectInputAImpl_Initialize(
269 LPDIRECTINPUTA iface,HINSTANCE hinst,DWORD x
271 return DIERR_ALREADYINITIALIZED;
274 static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
275 REFGUID rguid) {
276 ICOM_THIS(IDirectInputAImpl,iface);
277 char xbuf[50];
279 WINE_StringFromCLSID(rguid,xbuf);
280 FIXME(dinput,"(%p)->(%s): stub\n",This,xbuf);
282 return DI_OK;
285 static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUTA iface,
286 HWND hwndOwner,
287 DWORD dwFlags) {
288 ICOM_THIS(IDirectInputAImpl,iface);
289 FIXME(dinput,"(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
291 return DI_OK;
294 static ICOM_VTABLE(IDirectInputA) ddiavt= {
295 IDirectInputAImpl_QueryInterface,
296 IDirectInputAImpl_AddRef,
297 IDirectInputAImpl_Release,
298 IDirectInputAImpl_CreateDevice,
299 IDirectInputAImpl_EnumDevices,
300 IDirectInputAImpl_GetDeviceStatus,
301 IDirectInputAImpl_RunControlPanel,
302 IDirectInputAImpl_Initialize
305 /******************************************************************************
306 * IDirectInputDeviceA
309 static HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
310 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
313 int i;
314 TRACE(dinput,"(this=%p,%p)\n",This,df);
316 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
317 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
318 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
319 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
320 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
322 for (i=0;i<df->dwNumObjs;i++) {
323 char xbuf[50];
325 if (df->rgodf[i].pguid)
326 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
327 else
328 strcpy(xbuf,"<no guid>");
329 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
330 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
331 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
332 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
335 return 0;
338 static HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
339 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
341 ICOM_THIS(IDirectInputDevice2AImpl,iface);
342 FIXME(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
343 if (TRACE_ON(dinput))
344 _dump_cooperativelevel(dwflags);
345 return 0;
348 static HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
349 LPDIRECTINPUTDEVICE2A iface,HANDLE hnd
351 ICOM_THIS(IDirectInputDevice2AImpl,iface);
352 FIXME(dinput,"(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
353 return 0;
356 static ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE2A iface)
358 ICOM_THIS(IDirectInputDevice2AImpl,iface);
359 This->ref--;
360 if (This->ref)
361 return This->ref;
362 HeapFree(GetProcessHeap(),0,This);
363 return 0;
366 static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
367 LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
370 ICOM_THIS(SysKeyboardAImpl,iface);
371 char xbuf[50];
373 if (HIWORD(rguid))
374 WINE_StringFromCLSID(rguid,xbuf);
375 else
376 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
377 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ph);
378 TRACE(dinput,"(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
379 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
380 if (!HIWORD(rguid)) {
381 switch ((DWORD)rguid) {
382 case DIPROP_BUFFERSIZE: {
383 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
385 TRACE(dinput,"(buffersize=%ld)\n",pd->dwData);
386 break;
388 default:
389 WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
390 break;
393 return 0;
396 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
397 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
400 if (len==256) {
401 int keyc,vkey;
403 memset(ptr,0,256);
404 for (keyc=min_keycode;keyc<max_keycode;keyc++)
406 /* X keycode to virtual key */
407 vkey = keyc2vkey[keyc] & 0xFF;
408 /* The windows scancode is keyc-min_keycode */
409 if (InputKeyStateTable[vkey]&0x80) {
410 ((LPBYTE)ptr)[keyc-min_keycode]=0x80;
411 ((LPBYTE)ptr)[(keyc-min_keycode)|0x80]=0x80;
414 return 0;
416 WARN(dinput,"whoops, SysKeyboardAImpl_GetDeviceState got len %ld?\n",len);
417 return 0;
420 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
421 LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
422 LPDWORD entries,DWORD flags
425 ICOM_THIS(SysKeyboardAImpl,iface);
426 int keyc,n,vkey,xentries;
428 TRACE(dinput,"(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
429 This,dodsize,dod,entries,entries?*entries:0,flags);
430 EVENT_WaitNetEvent(FALSE,TRUE);
431 if (entries)
432 xentries = *entries;
433 else
434 xentries = 1;
436 n = 0;
438 for (keyc=min_keycode;(keyc<max_keycode) && (n<*entries);keyc++)
440 /* X keycode to virtual key */
441 vkey = keyc2vkey[keyc] & 0xFF;
442 if (This->keystate[vkey] == (InputKeyStateTable[vkey]&0x80))
443 continue;
444 if (dod) {
445 /* add an entry */
446 dod[n].dwOfs = keyc-min_keycode; /* scancode */
447 dod[n].dwData = InputKeyStateTable[vkey]&0x80;
448 dod[n].dwTimeStamp = 0; /* umm */
449 dod[n].dwSequence = 0; /* umm */
450 n++;
452 if (!(flags & DIGDD_PEEK))
453 This->keystate[vkey] = InputKeyStateTable[vkey]&0x80;
457 if (n) fprintf(stderr,"%d entries\n",n);
458 *entries = n;
459 return 0;
462 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
464 ICOM_THIS(SysKeyboardAImpl,iface);
465 TRACE(dinput,"(this=%p): stub\n",This);
466 return 0;
469 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
471 ICOM_THIS(SysKeyboardAImpl,iface);
472 TRACE(dinput,"(this=%p): stub\n",This);
473 return 0;
476 static HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
477 LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
480 ICOM_THIS(IDirectInputDevice2AImpl,iface);
481 char xbuf[50];
483 WINE_StringFromCLSID(riid,xbuf);
484 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ppobj);
485 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
486 IDirectInputDevice2_AddRef(iface);
487 *ppobj = This;
488 return 0;
490 if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
491 IDirectInputDevice2_AddRef(iface);
492 *ppobj = This;
493 return 0;
495 if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
496 IDirectInputDevice2_AddRef(iface);
497 *ppobj = This;
498 return 0;
500 return E_FAIL;
503 static ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
504 LPDIRECTINPUTDEVICE2A iface)
506 ICOM_THIS(IDirectInputDevice2AImpl,iface);
507 return ++This->ref;
510 static HRESULT WINAPI IDirectInputDevice2AImpl_GetCapabilities(
511 LPDIRECTINPUTDEVICE2A iface,
512 LPDIDEVCAPS lpDIDevCaps)
514 FIXME(dinput, "stub!\n");
515 return DI_OK;
518 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
519 LPDIRECTINPUTDEVICE2A iface,
520 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
521 LPVOID lpvRef,
522 DWORD dwFlags)
524 FIXME(dinput, "stub!\n");
525 #if 0
526 if (lpCallback)
527 lpCallback(NULL, lpvRef);
528 #endif
529 return DI_OK;
532 static HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
533 LPDIRECTINPUTDEVICE2A iface,
534 REFGUID rguid,
535 LPDIPROPHEADER pdiph)
537 FIXME(dinput, "stub!\n");
538 return DI_OK;
541 static HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
542 LPDIRECTINPUTDEVICE2A iface,
543 LPDIDEVICEOBJECTINSTANCEA pdidoi,
544 DWORD dwObj,
545 DWORD dwHow)
547 FIXME(dinput, "stub!\n");
548 return DI_OK;
551 static HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
552 LPDIRECTINPUTDEVICE2A iface,
553 LPDIDEVICEINSTANCEA pdidi)
555 FIXME(dinput, "stub!\n");
556 return DI_OK;
559 static HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
560 LPDIRECTINPUTDEVICE2A iface,
561 HWND hwndOwner,
562 DWORD dwFlags)
564 FIXME(dinput, "stub!\n");
565 return DI_OK;
568 static HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
569 LPDIRECTINPUTDEVICE2A iface,
570 HINSTANCE hinst,
571 DWORD dwVersion,
572 REFGUID rguid)
574 FIXME(dinput, "stub!\n");
575 return DI_OK;
578 /******************************************************************************
579 * IDirectInputDevice2A
582 static HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
583 LPDIRECTINPUTDEVICE2A iface,
584 REFGUID rguid,
585 LPCDIEFFECT lpeff,
586 LPDIRECTINPUTEFFECT *ppdef,
587 LPUNKNOWN pUnkOuter)
589 FIXME(dinput, "stub!\n");
590 return DI_OK;
593 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
594 LPDIRECTINPUTDEVICE2A iface,
595 LPDIENUMEFFECTSCALLBACKA lpCallback,
596 LPVOID lpvRef,
597 DWORD dwFlags)
599 FIXME(dinput, "stub!\n");
600 if (lpCallback)
601 lpCallback(NULL, lpvRef);
602 return DI_OK;
605 static HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
606 LPDIRECTINPUTDEVICE2A iface,
607 LPDIEFFECTINFOA lpdei,
608 REFGUID rguid)
610 FIXME(dinput, "stub!\n");
611 return DI_OK;
614 static HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
615 LPDIRECTINPUTDEVICE2A iface,
616 LPDWORD pdwOut)
618 FIXME(dinput, "stub!\n");
619 return DI_OK;
622 static HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
623 LPDIRECTINPUTDEVICE2A iface,
624 DWORD dwFlags)
626 FIXME(dinput, "stub!\n");
627 return DI_OK;
630 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
631 LPDIRECTINPUTDEVICE2A iface,
632 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
633 LPVOID lpvRef,
634 DWORD dwFlags)
636 FIXME(dinput, "stub!\n");
637 if (lpCallback)
638 lpCallback(NULL, lpvRef);
639 return DI_OK;
642 static HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
643 LPDIRECTINPUTDEVICE2A iface,
644 LPDIEFFESCAPE lpDIEEsc)
646 FIXME(dinput, "stub!\n");
647 return DI_OK;
650 static HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
651 LPDIRECTINPUTDEVICE2A iface)
653 FIXME(dinput, "stub!\n");
654 return DI_OK;
657 static HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
658 LPDIRECTINPUTDEVICE2A iface,
659 DWORD cbObjectData,
660 LPDIDEVICEOBJECTDATA rgdod,
661 LPDWORD pdwInOut,
662 DWORD dwFlags)
664 FIXME(dinput, "stub!\n");
665 return DI_OK;
668 /******************************************************************************
669 * SysMouseA (DInput Mouse support)
672 /******************************************************************************
673 * Release : release the mouse buffer.
675 static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
677 ICOM_THIS(SysMouseAImpl,iface);
679 This->ref--;
680 if (This->ref)
681 return This->ref;
683 /* Free the data queue */
684 if (This->data_queue != NULL)
685 HeapFree(GetProcessHeap(),0,This->data_queue);
687 /* Install the previous event handler (in case of releasing an aquired
688 mouse device) */
689 if (This->prev_handler != NULL)
690 MOUSE_Enable(This->prev_handler);
692 HeapFree(GetProcessHeap(),0,This);
693 return 0;
697 /******************************************************************************
698 * SetCooperativeLevel : store the window in which we will do our
699 * grabbing.
701 static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
702 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
705 ICOM_THIS(SysMouseAImpl,iface);
707 TRACE(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
709 if (TRACE_ON(dinput))
710 _dump_cooperativelevel(dwflags);
712 /* Store the window which asks for the mouse */
713 This->win = hwnd;
715 return 0;
719 /******************************************************************************
720 * SetDataFormat : the application can choose the format of the data
721 * the device driver sends back with GetDeviceState.
723 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
724 * in absolute and relative mode.
726 static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
727 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
730 ICOM_THIS(SysMouseAImpl,iface);
731 int i;
733 TRACE(dinput,"(this=%p,%p)\n",This,df);
735 TRACE(dinput,"(df.dwSize=%ld)\n",df->dwSize);
736 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
737 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
738 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
739 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
741 for (i=0;i<df->dwNumObjs;i++) {
742 char xbuf[50];
744 if (df->rgodf[i].pguid)
745 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
746 else
747 strcpy(xbuf,"<no guid>");
748 TRACE(dinput,"df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
749 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
750 TRACE(dinput,"dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
751 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
754 /* Check size of data format to prevent crashes if the applications
755 sends a smaller buffer */
756 if (df->dwDataSize != sizeof(struct DIMOUSESTATE)) {
757 FIXME(dinput, "non-standard mouse configuration not supported yet.");
758 return DIERR_INVALIDPARAM;
761 /* For the moment, ignore these fields and return always as if
762 c_dfDIMouse was passed as format... */
764 /* Check if the mouse is in absolute or relative mode */
765 if (df->dwFlags == DIDF_ABSAXIS)
766 This->absolute = 1;
767 else
768 This->absolute = 0;
770 return 0;
773 #define GEN_EVENT(offset,data,time,seq) \
775 if (This->queue_pos < This->queue_len) { \
776 This->data_queue[This->queue_pos].dwOfs = offset; \
777 This->data_queue[This->queue_pos].dwData = data; \
778 This->data_queue[This->queue_pos].dwTimeStamp = time; \
779 This->data_queue[This->queue_pos].dwSequence = seq; \
780 This->queue_pos++; \
784 /* Our private mouse event handler */
785 static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
786 DWORD cButtons, DWORD dwExtraInfo )
788 DWORD posX, posY, keyState, time, extra;
789 SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
791 if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
792 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
793 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
794 keyState = wme->keyState;
795 time = wme->time;
796 extra = (DWORD)wme->hWnd;
798 assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
799 posX = (dx * SYSMETRICS_CXSCREEN) >> 16;
800 posY = (dy * SYSMETRICS_CYSCREEN) >> 16;
801 } else {
802 ERR(dinput, "Mouse event not supported...\n");
803 return ;
806 TRACE(dinput, " %ld %ld ", posX, posY);
808 if ( dwFlags & MOUSEEVENTF_MOVE ) {
809 if (This->absolute) {
810 if (posX != This->prevX)
811 GEN_EVENT(DIMOFS_X, posX, time, 0);
812 if (posY != This->prevY)
813 GEN_EVENT(DIMOFS_Y, posY, time, 0);
814 } else {
815 /* Relative mouse input : the real fun starts here... */
816 if (This->need_warp) {
817 if (posX != This->prevX)
818 GEN_EVENT(DIMOFS_X, posX - This->prevX, time, 0);
819 if (posY != This->prevY)
820 GEN_EVENT(DIMOFS_Y, posY - This->prevY, time, 0);
821 } else {
822 /* This is the first time the event handler has been called after a
823 GetData of GetState. */
824 if (posX != This->win_centerX) {
825 GEN_EVENT(DIMOFS_X, posX - This->win_centerX, time, 0);
826 This->need_warp = 1;
829 if (posY != This->win_centerY) {
830 GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, time, 0);
831 This->need_warp = 1;
836 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
837 if (TRACE_ON(dinput))
838 DUMP(" LD ");
840 GEN_EVENT(DIMOFS_BUTTON0, 0xFF, time, 0);
842 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
843 if (TRACE_ON(dinput))
844 DUMP(" LU ");
846 GEN_EVENT(DIMOFS_BUTTON0, 0x00, time, 0);
848 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
849 if (TRACE_ON(dinput))
850 DUMP(" RD ");
852 GEN_EVENT(DIMOFS_BUTTON1, 0xFF, time, 0);
854 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
855 if (TRACE_ON(dinput))
856 DUMP(" RU ");
858 GEN_EVENT(DIMOFS_BUTTON1, 0x00, time, 0);
860 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
861 if (TRACE_ON(dinput))
862 DUMP(" MD ");
864 GEN_EVENT(DIMOFS_BUTTON2, 0xFF, time, 0);
866 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
867 if (TRACE_ON(dinput))
868 DUMP(" MU ");
870 GEN_EVENT(DIMOFS_BUTTON2, 0x00, time, 0);
872 if (TRACE_ON(dinput))
873 DUMP("\n");
875 This->prevX = posX;
876 This->prevY = posY;
880 /******************************************************************************
881 * Acquire : gets exclusive control of the mouse
883 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
885 ICOM_THIS(SysMouseAImpl,iface);
886 RECT rect;
888 TRACE(dinput,"(this=%p)\n",This);
890 if (This->acquired == 0) {
891 POINT point;
893 /* This stores the current mouse handler.
894 FIXME : need to be fixed for native USER use */
895 This->prev_handler = mouse_event;
897 /* Store (in a global variable) the current lock */
898 current_lock = (IDirectInputDevice2A*)This;
900 /* Install our own mouse event handler */
901 MOUSE_Enable(dinput_mouse_event);
903 /* Get the window dimension and find the center */
904 GetWindowRect(This->win, &rect);
905 This->win_centerX = (rect.right - rect.left) / 2;
906 This->win_centerY = (rect.bottom - rect.top ) / 2;
908 /* Warp the mouse to the center of the window */
909 TRACE(dinput, "Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
910 point.x = This->win_centerX;
911 point.y = This->win_centerY;
912 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
913 DISPLAY_MoveCursor(point.x, point.y);
915 This->acquired = 1;
917 return 0;
920 /******************************************************************************
921 * Unacquire : frees the mouse
923 static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
925 ICOM_THIS(SysMouseAImpl,iface);
927 TRACE(dinput,"(this=%p)\n",This);
929 /* Reinstall previous mouse event handler */
930 MOUSE_Enable(This->prev_handler);
931 This->prev_handler = NULL;
933 /* No more locks */
934 current_lock = NULL;
936 /* Unacquire device */
937 This->acquired = 0;
939 return 0;
942 /******************************************************************************
943 * GetDeviceState : returns the "state" of the mouse.
945 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
946 * supported.
948 static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
949 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
951 ICOM_THIS(SysMouseAImpl,iface);
952 DWORD rx, ry, state;
953 struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
955 TRACE(dinput,"(this=%p,0x%08lx,%p): \n",This,len,ptr);
957 /* Check if the buffer is big enough */
958 if (len < sizeof(struct DIMOUSESTATE)) {
959 FIXME(dinput, "unsupported state structure.");
960 return DIERR_INVALIDPARAM;
963 /* Get the mouse position */
964 EVENT_QueryPointer(&rx, &ry, &state);
965 TRACE(dinput,"(X:%ld - Y:%ld)\n", rx, ry);
967 /* Fill the mouse state structure */
968 if (This->absolute) {
969 mstate->lX = rx;
970 mstate->lY = ry;
971 } else {
972 mstate->lX = rx - This->win_centerX;
973 mstate->lY = ry - This->win_centerY;
975 if ((mstate->lX != 0) || (mstate->lY != 0))
976 This->need_warp = 1;
978 mstate->lZ = 0;
979 mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00);
980 mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00);
981 mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00);
982 mstate->rgbButtons[3] = 0x00;
984 /* Check if we need to do a mouse warping */
985 if (This->need_warp) {
986 POINT point;
988 TRACE(dinput, "Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
989 point.x = This->win_centerX;
990 point.y = This->win_centerY;
991 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
992 DISPLAY_MoveCursor(point.x, point.y);
994 This->need_warp = 0;
997 TRACE(dinput, "(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
998 mstate->lX, mstate->lY,
999 mstate->rgbButtons[0], mstate->rgbButtons[2], mstate->rgbButtons[1]);
1001 return 0;
1004 /******************************************************************************
1005 * GetDeviceState : gets buffered input data.
1007 static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1008 DWORD dodsize,
1009 LPDIDEVICEOBJECTDATA dod,
1010 LPDWORD entries,
1011 DWORD flags
1013 ICOM_THIS(SysMouseAImpl,iface);
1015 TRACE(dinput,"(%p)->(%ld,%p,%p(0x%08lx),0x%08lx)\n",
1016 This,dodsize,dod,entries,*entries,flags);
1018 if (flags & DIGDD_PEEK)
1019 TRACE(dinput, "DIGDD_PEEK\n");
1021 if (dod == NULL) {
1022 *entries = This->queue_pos;
1023 This->queue_pos = 0;
1024 } else {
1025 /* Check for buffer overflow */
1026 if (This->queue_pos > *entries) {
1027 WARN(dinput, "Buffer overflow not handled properly yet...\n");
1028 This->queue_pos = *entries;
1030 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1031 ERR(dinput, "Wrong structure size !\n");
1032 return DIERR_INVALIDPARAM;
1035 TRACE(dinput, "Application retrieving %d event(s).\n", This->queue_pos);
1037 /* Copy the buffered data into the application queue */
1038 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1040 /* Reset the event queue */
1041 This->queue_pos = 0;
1044 /* Check if we need to do a mouse warping */
1045 if (This->need_warp) {
1046 POINT point;
1048 TRACE(dinput, "Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1049 point.x = This->win_centerX;
1050 point.y = This->win_centerY;
1051 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1052 DISPLAY_MoveCursor(point.x, point.y);
1054 This->need_warp = 0;
1057 return 0;
1060 /******************************************************************************
1061 * SetProperty : change input device properties
1063 static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1064 REFGUID rguid,
1065 LPCDIPROPHEADER ph)
1067 ICOM_THIS(SysMouseAImpl,iface);
1068 char xbuf[50];
1070 if (HIWORD(rguid))
1071 WINE_StringFromCLSID(rguid,xbuf);
1072 else
1073 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1075 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ph);
1077 if (!HIWORD(rguid)) {
1078 switch ((DWORD)rguid) {
1079 case DIPROP_BUFFERSIZE: {
1080 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1082 TRACE(dinput,"buffersize = %ld\n",pd->dwData);
1084 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1085 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1086 This->queue_pos = 0;
1087 This->queue_len = pd->dwData;
1088 break;
1090 default:
1091 WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
1092 break;
1096 return 0;
1100 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt={
1101 IDirectInputDevice2AImpl_QueryInterface,
1102 IDirectInputDevice2AImpl_AddRef,
1103 IDirectInputDevice2AImpl_Release,
1104 IDirectInputDevice2AImpl_GetCapabilities,
1105 IDirectInputDevice2AImpl_EnumObjects,
1106 IDirectInputDevice2AImpl_GetProperty,
1107 SysKeyboardAImpl_SetProperty,
1108 SysKeyboardAImpl_Acquire,
1109 SysKeyboardAImpl_Unacquire,
1110 SysKeyboardAImpl_GetDeviceState,
1111 SysKeyboardAImpl_GetDeviceData,
1112 IDirectInputDevice2AImpl_SetDataFormat,
1113 IDirectInputDevice2AImpl_SetEventNotification,
1114 IDirectInputDevice2AImpl_SetCooperativeLevel,
1115 IDirectInputDevice2AImpl_GetObjectInfo,
1116 IDirectInputDevice2AImpl_GetDeviceInfo,
1117 IDirectInputDevice2AImpl_RunControlPanel,
1118 IDirectInputDevice2AImpl_Initialize,
1119 IDirectInputDevice2AImpl_CreateEffect,
1120 IDirectInputDevice2AImpl_EnumEffects,
1121 IDirectInputDevice2AImpl_GetEffectInfo,
1122 IDirectInputDevice2AImpl_GetForceFeedbackState,
1123 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1124 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1125 IDirectInputDevice2AImpl_Escape,
1126 IDirectInputDevice2AImpl_Poll,
1127 IDirectInputDevice2AImpl_SendDeviceData,
1130 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt={
1131 IDirectInputDevice2AImpl_QueryInterface,
1132 IDirectInputDevice2AImpl_AddRef,
1133 SysMouseAImpl_Release,
1134 IDirectInputDevice2AImpl_GetCapabilities,
1135 IDirectInputDevice2AImpl_EnumObjects,
1136 IDirectInputDevice2AImpl_GetProperty,
1137 SysMouseAImpl_SetProperty,
1138 SysMouseAImpl_Acquire,
1139 SysMouseAImpl_Unacquire,
1140 SysMouseAImpl_GetDeviceState,
1141 SysMouseAImpl_GetDeviceData,
1142 SysMouseAImpl_SetDataFormat,
1143 IDirectInputDevice2AImpl_SetEventNotification,
1144 SysMouseAImpl_SetCooperativeLevel,
1145 IDirectInputDevice2AImpl_GetObjectInfo,
1146 IDirectInputDevice2AImpl_GetDeviceInfo,
1147 IDirectInputDevice2AImpl_RunControlPanel,
1148 IDirectInputDevice2AImpl_Initialize,
1149 IDirectInputDevice2AImpl_CreateEffect,
1150 IDirectInputDevice2AImpl_EnumEffects,
1151 IDirectInputDevice2AImpl_GetEffectInfo,
1152 IDirectInputDevice2AImpl_GetForceFeedbackState,
1153 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1154 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1155 IDirectInputDevice2AImpl_Escape,
1156 IDirectInputDevice2AImpl_Poll,
1157 IDirectInputDevice2AImpl_SendDeviceData,