One small error corrected and the 102th key...
[wine/wine-kai.git] / windows / dinput.c
blob800e489882a0cf659c3fec94035adcc1414de642
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 "dinput.h"
31 #include "debug.h"
32 #include "message.h"
33 #include "display.h"
34 #include "mouse.h"
35 #include "sysmetrics.h"
37 extern BYTE InputKeyStateTable[256];
38 extern int min_keycode, max_keycode;
39 extern WORD keyc2vkey[256];
41 static ICOM_VTABLE(IDirectInputA) ddiavt;
42 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt;
43 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt;
45 typedef struct IDirectInputAImpl IDirectInputAImpl;
46 typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
47 typedef struct SysKeyboardAImpl SysKeyboardAImpl;
48 typedef struct SysMouseAImpl SysMouseAImpl;
50 struct IDirectInputDevice2AImpl
52 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
53 DWORD ref;
54 GUID guid;
57 struct SysKeyboardAImpl
59 /* IDirectInputDevice2AImpl */
60 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
61 DWORD ref;
62 GUID guid;
63 /* SysKeyboardAImpl */
64 BYTE keystate[256];
67 struct SysMouseAImpl
69 /* IDirectInputDevice2AImpl */
70 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
71 DWORD ref;
72 GUID guid;
73 /* SysMouseAImpl */
74 BYTE absolute;
75 /* Previous position for relative moves */
76 LONG prevX, prevY;
77 LPMOUSE_EVENT_PROC prev_handler;
78 HWND win;
79 DWORD win_centerX, win_centerY;
80 LPDIDEVICEOBJECTDATA data_queue;
81 int queue_pos, queue_len;
82 int need_warp;
83 int acquired;
87 /* UIDs for Wine "drivers".
88 When enumerating each device supporting DInput, they have two UIDs :
89 - the 'windows' UID
90 - a vendor UID */
91 static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
92 0x9e573ed8,
93 0x7734,
94 0x11d2,
95 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
97 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
98 0x0ab8648a,
99 0x7735,
100 0x11d2,
101 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
104 /* FIXME: This is ugly and not thread safe :/ */
105 static IDirectInputDevice2A* current_lock = NULL;
107 /******************************************************************************
108 * Various debugging tools
110 static void _dump_cooperativelevel(DWORD dwFlags) {
111 int i;
112 const struct {
113 DWORD mask;
114 char *name;
115 } flags[] = {
116 #define FE(x) { x, #x},
117 FE(DISCL_BACKGROUND)
118 FE(DISCL_EXCLUSIVE)
119 FE(DISCL_FOREGROUND)
120 FE(DISCL_NONEXCLUSIVE)
122 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
123 if (flags[i].mask & dwFlags)
124 DUMP("%s ",flags[i].name);
125 DUMP("\n");
128 struct IDirectInputAImpl
130 ICOM_VTABLE(IDirectInputA)* lpvtbl;
131 DWORD ref;
134 /******************************************************************************
135 * DirectInputCreate32A
137 HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
139 IDirectInputAImpl* This;
140 TRACE(dinput, "(0x%08lx,%04lx,%p,%p)\n",
141 (DWORD)hinst,dwVersion,ppDI,punkOuter
143 This = (IDirectInputAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputAImpl));
144 This->ref = 1;
145 This->lpvtbl = &ddiavt;
146 *ppDI=(IDirectInputA*)This;
147 return 0;
149 /******************************************************************************
150 * IDirectInputA_EnumDevices
152 static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
153 LPDIRECTINPUTA iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
154 LPVOID pvRef, DWORD dwFlags
157 ICOM_THIS(IDirectInputAImpl,iface);
158 DIDEVICEINSTANCEA devInstance;
159 int ret;
161 TRACE(dinput, "(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
163 devInstance.dwSize = sizeof(DIDEVICEINSTANCEA);
165 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
166 /* Return keyboard */
167 devInstance.guidInstance = GUID_SysKeyboard; /* DInput's GUID */
168 devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
169 devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
170 strcpy(devInstance.tszInstanceName, "Keyboard");
171 strcpy(devInstance.tszProductName, "Wine Keyboard");
173 ret = lpCallback(&devInstance, pvRef);
174 TRACE(dinput, "Keyboard registered\n");
176 if (ret == DIENUM_STOP)
177 return 0;
180 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
181 /* Return mouse */
182 devInstance.guidInstance = GUID_SysMouse; /* DInput's GUID */
183 devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
184 devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
185 strcpy(devInstance.tszInstanceName, "Mouse");
186 strcpy(devInstance.tszProductName, "Wine Mouse");
188 ret = lpCallback(&devInstance, pvRef);
189 TRACE(dinput, "Mouse registered\n");
192 /* Should also do joystick enumerations.... */
194 return 0;
197 static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUTA iface)
199 ICOM_THIS(IDirectInputAImpl,iface);
200 return ++(This->ref);
203 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
205 ICOM_THIS(IDirectInputAImpl,iface);
206 if (!(--This->ref)) {
207 HeapFree(GetProcessHeap(),0,This);
208 return 0;
210 return This->ref;
213 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
214 LPDIRECTINPUTA iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
215 LPUNKNOWN punk
217 ICOM_THIS(IDirectInputAImpl,iface);
218 char xbuf[50];
220 WINE_StringFromCLSID(rguid,xbuf);
221 FIXME(dinput,"(this=%p,%s,%p,%p): stub\n",This,xbuf,pdev,punk);
222 if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) || /* Generic Keyboard */
223 (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
224 SysKeyboardAImpl* newDevice;
225 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
226 newDevice->ref = 1;
227 newDevice->lpvtbl = &SysKeyboardAvt;
228 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
229 memset(newDevice->keystate,0,256);
230 *pdev=(IDirectInputDeviceA*)newDevice;
231 return DI_OK;
233 if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) || /* Generic Mouse */
234 (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysMouse)))) { /* Wine Mouse */
235 SysKeyboardAImpl* newDevice;
236 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
237 newDevice->ref = 1;
238 newDevice->lpvtbl = &SysMouseAvt;
239 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
240 *pdev=(IDirectInputDeviceA*)newDevice;
241 return DI_OK;
243 return E_FAIL;
246 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
247 LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj
249 ICOM_THIS(IDirectInputAImpl,iface);
250 char xbuf[50];
252 WINE_StringFromCLSID(riid,xbuf);
253 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ppobj);
254 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
255 IDirectInputA_AddRef(iface);
256 *ppobj = This;
257 return 0;
259 if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
260 IDirectInputA_AddRef(iface);
261 *ppobj = This;
262 return 0;
264 return E_FAIL;
267 static HRESULT WINAPI IDirectInputAImpl_Initialize(
268 LPDIRECTINPUTA iface,HINSTANCE hinst,DWORD x
270 return DIERR_ALREADYINITIALIZED;
273 static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
274 REFGUID rguid) {
275 ICOM_THIS(IDirectInputAImpl,iface);
276 char xbuf[50];
278 WINE_StringFromCLSID(rguid,xbuf);
279 FIXME(dinput,"(%p)->(%s): stub\n",This,xbuf);
281 return DI_OK;
284 static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUTA iface,
285 HWND hwndOwner,
286 DWORD dwFlags) {
287 ICOM_THIS(IDirectInputAImpl,iface);
288 FIXME(dinput,"(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
290 return DI_OK;
293 static ICOM_VTABLE(IDirectInputA) ddiavt= {
294 IDirectInputAImpl_QueryInterface,
295 IDirectInputAImpl_AddRef,
296 IDirectInputAImpl_Release,
297 IDirectInputAImpl_CreateDevice,
298 IDirectInputAImpl_EnumDevices,
299 IDirectInputAImpl_GetDeviceStatus,
300 IDirectInputAImpl_RunControlPanel,
301 IDirectInputAImpl_Initialize
304 /******************************************************************************
305 * IDirectInputDeviceA
308 static HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
309 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
312 int i;
313 TRACE(dinput,"(this=%p,%p)\n",This,df);
315 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
316 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
317 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
318 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
319 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
321 for (i=0;i<df->dwNumObjs;i++) {
322 char xbuf[50];
324 if (df->rgodf[i].pguid)
325 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
326 else
327 strcpy(xbuf,"<no guid>");
328 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
329 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
330 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
331 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
334 return 0;
337 static HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
338 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
340 ICOM_THIS(IDirectInputDevice2AImpl,iface);
341 FIXME(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
342 if (TRACE_ON(dinput))
343 _dump_cooperativelevel(dwflags);
344 return 0;
347 static HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
348 LPDIRECTINPUTDEVICE2A iface,HANDLE hnd
350 ICOM_THIS(IDirectInputDevice2AImpl,iface);
351 FIXME(dinput,"(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
352 return 0;
355 static ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE2A iface)
357 ICOM_THIS(IDirectInputDevice2AImpl,iface);
358 This->ref--;
359 if (This->ref)
360 return This->ref;
361 HeapFree(GetProcessHeap(),0,This);
362 return 0;
365 static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
366 LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
369 ICOM_THIS(SysKeyboardAImpl,iface);
370 char xbuf[50];
372 if (HIWORD(rguid))
373 WINE_StringFromCLSID(rguid,xbuf);
374 else
375 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
376 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ph);
377 TRACE(dinput,"(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
378 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
379 if (!HIWORD(rguid)) {
380 switch ((DWORD)rguid) {
381 case DIPROP_BUFFERSIZE: {
382 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
384 TRACE(dinput,"(buffersize=%ld)\n",pd->dwData);
385 break;
387 default:
388 WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
389 break;
392 return 0;
395 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
396 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
399 if (len==256) {
400 int keyc,vkey;
402 memset(ptr,0,256);
403 for (keyc=min_keycode;keyc<max_keycode;keyc++)
405 /* X keycode to virtual key */
406 vkey = keyc2vkey[keyc] & 0xFF;
407 /* The windows scancode is keyc-min_keycode */
408 if (InputKeyStateTable[vkey]&0x80) {
409 ((LPBYTE)ptr)[keyc-min_keycode]=0x80;
410 ((LPBYTE)ptr)[(keyc-min_keycode)|0x80]=0x80;
413 return 0;
415 WARN(dinput,"whoops, SysKeyboardAImpl_GetDeviceState got len %ld?\n",len);
416 return 0;
419 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
420 LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
421 LPDWORD entries,DWORD flags
424 ICOM_THIS(SysKeyboardAImpl,iface);
425 int keyc,n,vkey,xentries;
427 TRACE(dinput,"(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
428 This,dodsize,dod,entries,entries?*entries:0,flags);
429 EVENT_WaitNetEvent(FALSE,TRUE);
430 if (entries)
431 xentries = *entries;
432 else
433 xentries = 1;
435 n = 0;
437 for (keyc=min_keycode;(keyc<max_keycode) && (n<*entries);keyc++)
439 /* X keycode to virtual key */
440 vkey = keyc2vkey[keyc] & 0xFF;
441 if (This->keystate[vkey] == (InputKeyStateTable[vkey]&0x80))
442 continue;
443 if (dod) {
444 /* add an entry */
445 dod[n].dwOfs = keyc-min_keycode; /* scancode */
446 dod[n].dwData = InputKeyStateTable[vkey]&0x80;
447 dod[n].dwTimeStamp = 0; /* umm */
448 dod[n].dwSequence = 0; /* umm */
449 n++;
451 if (!(flags & DIGDD_PEEK))
452 This->keystate[vkey] = InputKeyStateTable[vkey]&0x80;
456 if (n) fprintf(stderr,"%d entries\n",n);
457 *entries = n;
458 return 0;
461 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
463 ICOM_THIS(SysKeyboardAImpl,iface);
464 TRACE(dinput,"(this=%p): stub\n",This);
465 return 0;
468 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
470 ICOM_THIS(SysKeyboardAImpl,iface);
471 TRACE(dinput,"(this=%p): stub\n",This);
472 return 0;
475 static HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
476 LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
479 ICOM_THIS(IDirectInputDevice2AImpl,iface);
480 char xbuf[50];
482 WINE_StringFromCLSID(riid,xbuf);
483 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ppobj);
484 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
485 IDirectInputDevice2_AddRef(iface);
486 *ppobj = This;
487 return 0;
489 if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
490 IDirectInputDevice2_AddRef(iface);
491 *ppobj = This;
492 return 0;
494 if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
495 IDirectInputDevice2_AddRef(iface);
496 *ppobj = This;
497 return 0;
499 return E_FAIL;
502 static ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
503 LPDIRECTINPUTDEVICE2A iface)
505 ICOM_THIS(IDirectInputDevice2AImpl,iface);
506 return ++This->ref;
509 static HRESULT WINAPI IDirectInputDevice2AImpl_GetCapabilities(
510 LPDIRECTINPUTDEVICE2A iface,
511 LPDIDEVCAPS lpDIDevCaps)
513 FIXME(dinput, "stub!\n");
514 return DI_OK;
517 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
518 LPDIRECTINPUTDEVICE2A iface,
519 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
520 LPVOID lpvRef,
521 DWORD dwFlags)
523 FIXME(dinput, "stub!\n");
524 #if 0
525 if (lpCallback)
526 lpCallback(NULL, lpvRef);
527 #endif
528 return DI_OK;
531 static HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
532 LPDIRECTINPUTDEVICE2A iface,
533 REFGUID rguid,
534 LPDIPROPHEADER pdiph)
536 FIXME(dinput, "stub!\n");
537 return DI_OK;
540 static HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
541 LPDIRECTINPUTDEVICE2A iface,
542 LPDIDEVICEOBJECTINSTANCEA pdidoi,
543 DWORD dwObj,
544 DWORD dwHow)
546 FIXME(dinput, "stub!\n");
547 return DI_OK;
550 static HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
551 LPDIRECTINPUTDEVICE2A iface,
552 LPDIDEVICEINSTANCEA pdidi)
554 FIXME(dinput, "stub!\n");
555 return DI_OK;
558 static HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
559 LPDIRECTINPUTDEVICE2A iface,
560 HWND hwndOwner,
561 DWORD dwFlags)
563 FIXME(dinput, "stub!\n");
564 return DI_OK;
567 static HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
568 LPDIRECTINPUTDEVICE2A iface,
569 HINSTANCE hinst,
570 DWORD dwVersion,
571 REFGUID rguid)
573 FIXME(dinput, "stub!\n");
574 return DI_OK;
577 /******************************************************************************
578 * IDirectInputDevice2A
581 static HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
582 LPDIRECTINPUTDEVICE2A iface,
583 REFGUID rguid,
584 LPCDIEFFECT lpeff,
585 LPDIRECTINPUTEFFECT *ppdef,
586 LPUNKNOWN pUnkOuter)
588 FIXME(dinput, "stub!\n");
589 return DI_OK;
592 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
593 LPDIRECTINPUTDEVICE2A iface,
594 LPDIENUMEFFECTSCALLBACKA lpCallback,
595 LPVOID lpvRef,
596 DWORD dwFlags)
598 FIXME(dinput, "stub!\n");
599 if (lpCallback)
600 lpCallback(NULL, lpvRef);
601 return DI_OK;
604 static HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
605 LPDIRECTINPUTDEVICE2A iface,
606 LPDIEFFECTINFOA lpdei,
607 REFGUID rguid)
609 FIXME(dinput, "stub!\n");
610 return DI_OK;
613 static HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
614 LPDIRECTINPUTDEVICE2A iface,
615 LPDWORD pdwOut)
617 FIXME(dinput, "stub!\n");
618 return DI_OK;
621 static HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
622 LPDIRECTINPUTDEVICE2A iface,
623 DWORD dwFlags)
625 FIXME(dinput, "stub!\n");
626 return DI_OK;
629 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
630 LPDIRECTINPUTDEVICE2A iface,
631 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
632 LPVOID lpvRef,
633 DWORD dwFlags)
635 FIXME(dinput, "stub!\n");
636 if (lpCallback)
637 lpCallback(NULL, lpvRef);
638 return DI_OK;
641 static HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
642 LPDIRECTINPUTDEVICE2A iface,
643 LPDIEFFESCAPE lpDIEEsc)
645 FIXME(dinput, "stub!\n");
646 return DI_OK;
649 static HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
650 LPDIRECTINPUTDEVICE2A iface)
652 FIXME(dinput, "stub!\n");
653 return DI_OK;
656 static HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
657 LPDIRECTINPUTDEVICE2A iface,
658 DWORD cbObjectData,
659 LPDIDEVICEOBJECTDATA rgdod,
660 LPDWORD pdwInOut,
661 DWORD dwFlags)
663 FIXME(dinput, "stub!\n");
664 return DI_OK;
667 /******************************************************************************
668 * SysMouseA (DInput Mouse support)
671 /******************************************************************************
672 * Release : release the mouse buffer.
674 static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
676 ICOM_THIS(SysMouseAImpl,iface);
678 This->ref--;
679 if (This->ref)
680 return This->ref;
682 /* Free the data queue */
683 if (This->data_queue != NULL)
684 HeapFree(GetProcessHeap(),0,This->data_queue);
686 /* Install the previous event handler (in case of releasing an aquired
687 mouse device) */
688 if (This->prev_handler != NULL)
689 MOUSE_Enable(This->prev_handler);
691 HeapFree(GetProcessHeap(),0,This);
692 return 0;
696 /******************************************************************************
697 * SetCooperativeLevel : store the window in which we will do our
698 * grabbing.
700 static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
701 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
704 ICOM_THIS(SysMouseAImpl,iface);
706 TRACE(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
708 if (TRACE_ON(dinput))
709 _dump_cooperativelevel(dwflags);
711 /* Store the window which asks for the mouse */
712 This->win = hwnd;
714 return 0;
718 /******************************************************************************
719 * SetDataFormat : the application can choose the format of the data
720 * the device driver sends back with GetDeviceState.
722 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
723 * in absolute and relative mode.
725 static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
726 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
729 ICOM_THIS(SysMouseAImpl,iface);
730 int i;
732 TRACE(dinput,"(this=%p,%p)\n",This,df);
734 TRACE(dinput,"(df.dwSize=%ld)\n",df->dwSize);
735 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
736 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
737 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
738 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
740 for (i=0;i<df->dwNumObjs;i++) {
741 char xbuf[50];
743 if (df->rgodf[i].pguid)
744 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
745 else
746 strcpy(xbuf,"<no guid>");
747 TRACE(dinput,"df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
748 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
749 TRACE(dinput,"dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
750 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
753 /* Check size of data format to prevent crashes if the applications
754 sends a smaller buffer */
755 if (df->dwDataSize != sizeof(struct DIMOUSESTATE)) {
756 FIXME(dinput, "non-standard mouse configuration not supported yet.");
757 return DIERR_INVALIDPARAM;
760 /* For the moment, ignore these fields and return always as if
761 c_dfDIMouse was passed as format... */
763 /* Check if the mouse is in absolute or relative mode */
764 if (df->dwFlags == DIDF_ABSAXIS)
765 This->absolute = 1;
766 else
767 This->absolute = 0;
769 return 0;
772 #define GEN_EVENT(offset,data,time,seq) \
774 if (This->queue_pos < This->queue_len) { \
775 This->data_queue[This->queue_pos].dwOfs = offset; \
776 This->data_queue[This->queue_pos].dwData = data; \
777 This->data_queue[This->queue_pos].dwTimeStamp = time; \
778 This->data_queue[This->queue_pos].dwSequence = seq; \
779 This->queue_pos++; \
783 /* Our private mouse event handler */
784 static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
785 DWORD cButtons, DWORD dwExtraInfo )
787 DWORD posX, posY, keyState, time, extra;
788 SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
790 if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
791 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
792 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
793 keyState = wme->keyState;
794 time = wme->time;
795 extra = (DWORD)wme->hWnd;
797 assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
798 posX = (dx * SYSMETRICS_CXSCREEN) >> 16;
799 posY = (dy * SYSMETRICS_CYSCREEN) >> 16;
800 } else {
801 ERR(dinput, "Mouse event not supported...\n");
802 return ;
805 TRACE(dinput, " %ld %ld ", posX, posY);
807 if ( dwFlags & MOUSEEVENTF_MOVE ) {
808 if (This->absolute) {
809 if (posX != This->prevX)
810 GEN_EVENT(DIMOFS_X, posX, time, 0);
811 if (posY != This->prevY)
812 GEN_EVENT(DIMOFS_Y, posY, time, 0);
813 } else {
814 /* Relative mouse input : the real fun starts here... */
815 if (This->need_warp) {
816 if (posX != This->prevX)
817 GEN_EVENT(DIMOFS_X, posX - This->prevX, time, 0);
818 if (posY != This->prevY)
819 GEN_EVENT(DIMOFS_Y, posY - This->prevY, time, 0);
820 } else {
821 /* This is the first time the event handler has been called after a
822 GetData of GetState. */
823 if (posX != This->win_centerX) {
824 GEN_EVENT(DIMOFS_X, posX - This->win_centerX, time, 0);
825 This->need_warp = 1;
828 if (posY != This->win_centerY) {
829 GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, time, 0);
830 This->need_warp = 1;
835 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
836 if (TRACE_ON(dinput))
837 DUMP(" LD ");
839 GEN_EVENT(DIMOFS_BUTTON0, 0xFF, time, 0);
841 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
842 if (TRACE_ON(dinput))
843 DUMP(" LU ");
845 GEN_EVENT(DIMOFS_BUTTON0, 0x00, time, 0);
847 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
848 if (TRACE_ON(dinput))
849 DUMP(" RD ");
851 GEN_EVENT(DIMOFS_BUTTON1, 0xFF, time, 0);
853 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
854 if (TRACE_ON(dinput))
855 DUMP(" RU ");
857 GEN_EVENT(DIMOFS_BUTTON1, 0x00, time, 0);
859 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
860 if (TRACE_ON(dinput))
861 DUMP(" MD ");
863 GEN_EVENT(DIMOFS_BUTTON2, 0xFF, time, 0);
865 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
866 if (TRACE_ON(dinput))
867 DUMP(" MU ");
869 GEN_EVENT(DIMOFS_BUTTON2, 0x00, time, 0);
871 if (TRACE_ON(dinput))
872 DUMP("\n");
874 This->prevX = posX;
875 This->prevY = posY;
879 /******************************************************************************
880 * Acquire : gets exclusive control of the mouse
882 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
884 ICOM_THIS(SysMouseAImpl,iface);
885 RECT rect;
887 TRACE(dinput,"(this=%p)\n",This);
889 if (This->acquired == 0) {
890 POINT point;
892 /* This stores the current mouse handler. */
893 This->prev_handler = mouse_event;
895 /* Store (in a global variable) the current lock */
896 current_lock = (IDirectInputDevice2A*)This;
898 /* Install our own mouse event handler */
899 MOUSE_Enable(dinput_mouse_event);
901 /* Get the window dimension and find the center */
902 GetWindowRect(This->win, &rect);
903 This->win_centerX = (rect.right - rect.left) / 2;
904 This->win_centerY = (rect.bottom - rect.top ) / 2;
906 /* Warp the mouse to the center of the window */
907 TRACE(dinput, "Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
908 point.x = This->win_centerX;
909 point.y = This->win_centerY;
910 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
911 DISPLAY_MoveCursor(point.x, point.y);
913 This->acquired = 1;
915 return 0;
918 /******************************************************************************
919 * Unacquire : frees the mouse
921 static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
923 ICOM_THIS(SysMouseAImpl,iface);
925 TRACE(dinput,"(this=%p)\n",This);
927 /* Reinstall previous mouse event handler */
928 MOUSE_Enable(This->prev_handler);
929 This->prev_handler = NULL;
931 /* No more locks */
932 current_lock = NULL;
934 /* Unacquire device */
935 This->acquired = 0;
937 return 0;
940 /******************************************************************************
941 * GetDeviceState : returns the "state" of the mouse.
943 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
944 * supported.
946 static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
947 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
949 ICOM_THIS(SysMouseAImpl,iface);
950 DWORD rx, ry, state;
951 struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
953 TRACE(dinput,"(this=%p,0x%08lx,%p): \n",This,len,ptr);
955 /* Check if the buffer is big enough */
956 if (len < sizeof(struct DIMOUSESTATE)) {
957 FIXME(dinput, "unsupported state structure.");
958 return DIERR_INVALIDPARAM;
961 /* Get the mouse position */
962 EVENT_QueryPointer(&rx, &ry, &state);
963 TRACE(dinput,"(X:%ld - Y:%ld)\n", rx, ry);
965 /* Fill the mouse state structure */
966 if (This->absolute) {
967 mstate->lX = rx;
968 mstate->lY = ry;
969 } else {
970 mstate->lX = rx - This->win_centerX;
971 mstate->lY = ry - This->win_centerY;
973 if ((mstate->lX != 0) || (mstate->lY != 0))
974 This->need_warp = 1;
976 mstate->lZ = 0;
977 mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00);
978 mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00);
979 mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00);
980 mstate->rgbButtons[3] = 0x00;
982 /* Check if we need to do a mouse warping */
983 if (This->need_warp) {
984 POINT point;
986 TRACE(dinput, "Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
987 point.x = This->win_centerX;
988 point.y = This->win_centerY;
989 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
990 DISPLAY_MoveCursor(point.x, point.y);
992 This->need_warp = 0;
995 TRACE(dinput, "(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
996 mstate->lX, mstate->lY,
997 mstate->rgbButtons[0], mstate->rgbButtons[2], mstate->rgbButtons[1]);
999 return 0;
1002 /******************************************************************************
1003 * GetDeviceState : gets buffered input data.
1005 static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1006 DWORD dodsize,
1007 LPDIDEVICEOBJECTDATA dod,
1008 LPDWORD entries,
1009 DWORD flags
1011 ICOM_THIS(SysMouseAImpl,iface);
1013 TRACE(dinput,"(%p)->(%ld,%p,%p(0x%08lx),0x%08lx)\n",
1014 This,dodsize,dod,entries,*entries,flags);
1016 if (flags & DIGDD_PEEK)
1017 TRACE(dinput, "DIGDD_PEEK\n");
1019 if (dod == NULL) {
1020 *entries = This->queue_pos;
1021 This->queue_pos = 0;
1022 } else {
1023 /* Check for buffer overflow */
1024 if (This->queue_pos > *entries) {
1025 WARN(dinput, "Buffer overflow not handled properly yet...\n");
1026 This->queue_pos = *entries;
1028 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1029 ERR(dinput, "Wrong structure size !\n");
1030 return DIERR_INVALIDPARAM;
1033 TRACE(dinput, "Application retrieving %d event(s).\n", This->queue_pos);
1035 /* Copy the buffered data into the application queue */
1036 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1038 /* Reset the event queue */
1039 This->queue_pos = 0;
1042 /* Check if we need to do a mouse warping */
1043 if (This->need_warp) {
1044 POINT point;
1046 TRACE(dinput, "Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1047 point.x = This->win_centerX;
1048 point.y = This->win_centerY;
1049 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1050 DISPLAY_MoveCursor(point.x, point.y);
1052 This->need_warp = 0;
1055 return 0;
1058 /******************************************************************************
1059 * SetProperty : change input device properties
1061 static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1062 REFGUID rguid,
1063 LPCDIPROPHEADER ph)
1065 ICOM_THIS(SysMouseAImpl,iface);
1066 char xbuf[50];
1068 if (HIWORD(rguid))
1069 WINE_StringFromCLSID(rguid,xbuf);
1070 else
1071 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1073 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ph);
1075 if (!HIWORD(rguid)) {
1076 switch ((DWORD)rguid) {
1077 case DIPROP_BUFFERSIZE: {
1078 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1080 TRACE(dinput,"buffersize = %ld\n",pd->dwData);
1082 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1083 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1084 This->queue_pos = 0;
1085 This->queue_len = pd->dwData;
1086 break;
1088 default:
1089 WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
1090 break;
1094 return 0;
1098 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt={
1099 IDirectInputDevice2AImpl_QueryInterface,
1100 IDirectInputDevice2AImpl_AddRef,
1101 IDirectInputDevice2AImpl_Release,
1102 IDirectInputDevice2AImpl_GetCapabilities,
1103 IDirectInputDevice2AImpl_EnumObjects,
1104 IDirectInputDevice2AImpl_GetProperty,
1105 SysKeyboardAImpl_SetProperty,
1106 SysKeyboardAImpl_Acquire,
1107 SysKeyboardAImpl_Unacquire,
1108 SysKeyboardAImpl_GetDeviceState,
1109 SysKeyboardAImpl_GetDeviceData,
1110 IDirectInputDevice2AImpl_SetDataFormat,
1111 IDirectInputDevice2AImpl_SetEventNotification,
1112 IDirectInputDevice2AImpl_SetCooperativeLevel,
1113 IDirectInputDevice2AImpl_GetObjectInfo,
1114 IDirectInputDevice2AImpl_GetDeviceInfo,
1115 IDirectInputDevice2AImpl_RunControlPanel,
1116 IDirectInputDevice2AImpl_Initialize,
1117 IDirectInputDevice2AImpl_CreateEffect,
1118 IDirectInputDevice2AImpl_EnumEffects,
1119 IDirectInputDevice2AImpl_GetEffectInfo,
1120 IDirectInputDevice2AImpl_GetForceFeedbackState,
1121 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1122 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1123 IDirectInputDevice2AImpl_Escape,
1124 IDirectInputDevice2AImpl_Poll,
1125 IDirectInputDevice2AImpl_SendDeviceData,
1128 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt={
1129 IDirectInputDevice2AImpl_QueryInterface,
1130 IDirectInputDevice2AImpl_AddRef,
1131 SysMouseAImpl_Release,
1132 IDirectInputDevice2AImpl_GetCapabilities,
1133 IDirectInputDevice2AImpl_EnumObjects,
1134 IDirectInputDevice2AImpl_GetProperty,
1135 SysMouseAImpl_SetProperty,
1136 SysMouseAImpl_Acquire,
1137 SysMouseAImpl_Unacquire,
1138 SysMouseAImpl_GetDeviceState,
1139 SysMouseAImpl_GetDeviceData,
1140 SysMouseAImpl_SetDataFormat,
1141 IDirectInputDevice2AImpl_SetEventNotification,
1142 SysMouseAImpl_SetCooperativeLevel,
1143 IDirectInputDevice2AImpl_GetObjectInfo,
1144 IDirectInputDevice2AImpl_GetDeviceInfo,
1145 IDirectInputDevice2AImpl_RunControlPanel,
1146 IDirectInputDevice2AImpl_Initialize,
1147 IDirectInputDevice2AImpl_CreateEffect,
1148 IDirectInputDevice2AImpl_EnumEffects,
1149 IDirectInputDevice2AImpl_GetEffectInfo,
1150 IDirectInputDevice2AImpl_GetForceFeedbackState,
1151 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1152 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1153 IDirectInputDevice2AImpl_Escape,
1154 IDirectInputDevice2AImpl_Poll,
1155 IDirectInputDevice2AImpl_SendDeviceData,