Fixed a silly VGA-emulation palette bug.
[wine/multimedia.git] / windows / dinput.c
blob7812ca6c49c176643fceb181b2a4e5b94cff7e91
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"
35 #include "mouse.h"
36 #include "ts_xlib.h"
37 #include "sysmetrics.h"
38 #include "x11drv.h"
40 extern BYTE InputKeyStateTable[256];
41 extern int min_keycode, max_keycode;
42 extern WORD keyc2vkey[256];
44 static ICOM_VTABLE(IDirectInputA) ddiavt;
45 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt;
46 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt;
48 typedef struct IDirectInputAImpl IDirectInputAImpl;
49 typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
50 typedef struct SysKeyboardAImpl SysKeyboardAImpl;
51 typedef struct SysMouseAImpl SysMouseAImpl;
53 struct IDirectInputDevice2AImpl
55 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
56 DWORD ref;
57 GUID guid;
60 struct SysKeyboardAImpl
62 /* IDirectInputDevice2AImpl */
63 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
64 DWORD ref;
65 GUID guid;
66 /* SysKeyboardAImpl */
67 BYTE keystate[256];
70 struct SysMouseAImpl
72 /* IDirectInputDevice2AImpl */
73 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
74 DWORD ref;
75 GUID guid;
76 /* SysMouseAImpl */
77 BYTE absolute;
78 /* Previous position for relative moves */
79 LONG prevX, prevY;
80 LPMOUSE_EVENT_PROC prev_handler;
81 HWND win;
82 int xwin;
83 DWORD win_centerX, win_centerY;
84 LPDIDEVICEOBJECTDATA data_queue;
85 int queue_pos, queue_len;
86 int need_warp;
87 int acquired;
91 /* UIDs for Wine "drivers".
92 When enumerating each device supporting DInput, they have two UIDs :
93 - the 'windows' UID
94 - a vendor UID */
95 static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
96 0x9e573ed8,
97 0x7734,
98 0x11d2,
99 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
101 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
102 0x0ab8648a,
103 0x7735,
104 0x11d2,
105 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
108 /* FIXME: This is ugly and not thread safe :/ */
109 static IDirectInputDevice2A* current_lock = NULL;
111 /******************************************************************************
112 * Various debugging tools
114 static void _dump_cooperativelevel(DWORD dwFlags) {
115 int i;
116 const struct {
117 DWORD mask;
118 char *name;
119 } flags[] = {
120 #define FE(x) { x, #x},
121 FE(DISCL_BACKGROUND)
122 FE(DISCL_EXCLUSIVE)
123 FE(DISCL_FOREGROUND)
124 FE(DISCL_NONEXCLUSIVE)
126 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
127 if (flags[i].mask & dwFlags)
128 DUMP("%s ",flags[i].name);
129 DUMP("\n");
132 struct IDirectInputAImpl
134 ICOM_VTABLE(IDirectInputA)* lpvtbl;
135 DWORD ref;
138 /******************************************************************************
139 * DirectInputCreate32A
141 HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
143 IDirectInputAImpl* This;
144 TRACE(dinput, "(0x%08lx,%04lx,%p,%p)\n",
145 (DWORD)hinst,dwVersion,ppDI,punkOuter
147 This = (IDirectInputAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputAImpl));
148 This->ref = 1;
149 This->lpvtbl = &ddiavt;
150 *ppDI=(IDirectInputA*)This;
151 return 0;
153 /******************************************************************************
154 * IDirectInputA_EnumDevices
156 static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
157 LPDIRECTINPUTA iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
158 LPVOID pvRef, DWORD dwFlags
161 ICOM_THIS(IDirectInputAImpl,iface);
162 DIDEVICEINSTANCEA devInstance;
163 int ret;
165 TRACE(dinput, "(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
167 devInstance.dwSize = sizeof(DIDEVICEINSTANCEA);
169 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
170 /* Return keyboard */
171 devInstance.guidInstance = GUID_SysKeyboard; /* DInput's GUID */
172 devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
173 devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
174 strcpy(devInstance.tszInstanceName, "Keyboard");
175 strcpy(devInstance.tszProductName, "Wine Keyboard");
177 ret = lpCallback(&devInstance, pvRef);
178 TRACE(dinput, "Keyboard registered\n");
180 if (ret == DIENUM_STOP)
181 return 0;
184 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
185 /* Return mouse */
186 devInstance.guidInstance = GUID_SysMouse; /* DInput's GUID */
187 devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
188 devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
189 strcpy(devInstance.tszInstanceName, "Mouse");
190 strcpy(devInstance.tszProductName, "Wine Mouse");
192 ret = lpCallback(&devInstance, pvRef);
193 TRACE(dinput, "Mouse registered\n");
196 /* Should also do joystick enumerations.... */
198 return 0;
201 static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUTA iface)
203 ICOM_THIS(IDirectInputAImpl,iface);
204 return ++(This->ref);
207 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
209 ICOM_THIS(IDirectInputAImpl,iface);
210 if (!(--This->ref)) {
211 HeapFree(GetProcessHeap(),0,This);
212 return 0;
214 return This->ref;
217 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
218 LPDIRECTINPUTA iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
219 LPUNKNOWN punk
221 ICOM_THIS(IDirectInputAImpl,iface);
222 char xbuf[50];
224 WINE_StringFromCLSID(rguid,xbuf);
225 FIXME(dinput,"(this=%p,%s,%p,%p): stub\n",This,xbuf,pdev,punk);
226 if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) || /* Generic Keyboard */
227 (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
228 SysKeyboardAImpl* newDevice;
229 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
230 newDevice->ref = 1;
231 newDevice->lpvtbl = &SysKeyboardAvt;
232 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
233 memset(newDevice->keystate,0,256);
234 *pdev=(IDirectInputDeviceA*)newDevice;
235 return DI_OK;
237 if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) || /* Generic Mouse */
238 (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysMouse)))) { /* Wine Mouse */
239 SysKeyboardAImpl* newDevice;
240 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
241 newDevice->ref = 1;
242 newDevice->lpvtbl = &SysMouseAvt;
243 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
244 *pdev=(IDirectInputDeviceA*)newDevice;
245 return DI_OK;
247 return E_FAIL;
250 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
251 LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj
253 ICOM_THIS(IDirectInputAImpl,iface);
254 char xbuf[50];
256 WINE_StringFromCLSID(riid,xbuf);
257 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ppobj);
258 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
259 IDirectInputA_AddRef(iface);
260 *ppobj = This;
261 return 0;
263 if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
264 IDirectInputA_AddRef(iface);
265 *ppobj = This;
266 return 0;
268 return E_FAIL;
271 static HRESULT WINAPI IDirectInputAImpl_Initialize(
272 LPDIRECTINPUTA iface,HINSTANCE hinst,DWORD x
274 return DIERR_ALREADYINITIALIZED;
277 static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
278 REFGUID rguid) {
279 ICOM_THIS(IDirectInputAImpl,iface);
280 char xbuf[50];
282 WINE_StringFromCLSID(rguid,xbuf);
283 FIXME(dinput,"(%p)->(%s): stub\n",This,xbuf);
285 return DI_OK;
288 static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUTA iface,
289 HWND hwndOwner,
290 DWORD dwFlags) {
291 ICOM_THIS(IDirectInputAImpl,iface);
292 FIXME(dinput,"(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
294 return DI_OK;
297 static ICOM_VTABLE(IDirectInputA) ddiavt= {
298 IDirectInputAImpl_QueryInterface,
299 IDirectInputAImpl_AddRef,
300 IDirectInputAImpl_Release,
301 IDirectInputAImpl_CreateDevice,
302 IDirectInputAImpl_EnumDevices,
303 IDirectInputAImpl_GetDeviceStatus,
304 IDirectInputAImpl_RunControlPanel,
305 IDirectInputAImpl_Initialize
308 /******************************************************************************
309 * IDirectInputDeviceA
312 static HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
313 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
316 int i;
317 TRACE(dinput,"(this=%p,%p)\n",This,df);
319 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
320 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
321 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
322 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
323 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
325 for (i=0;i<df->dwNumObjs;i++) {
326 char xbuf[50];
328 if (df->rgodf[i].pguid)
329 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
330 else
331 strcpy(xbuf,"<no guid>");
332 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
333 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
334 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
335 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
338 return 0;
341 static HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
342 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
344 ICOM_THIS(IDirectInputDevice2AImpl,iface);
345 FIXME(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
346 if (TRACE_ON(dinput))
347 _dump_cooperativelevel(dwflags);
348 return 0;
351 static HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
352 LPDIRECTINPUTDEVICE2A iface,HANDLE hnd
354 ICOM_THIS(IDirectInputDevice2AImpl,iface);
355 FIXME(dinput,"(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
356 return 0;
359 static ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE2A iface)
361 ICOM_THIS(IDirectInputDevice2AImpl,iface);
362 This->ref--;
363 if (This->ref)
364 return This->ref;
365 HeapFree(GetProcessHeap(),0,This);
366 return 0;
369 static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
370 LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
373 ICOM_THIS(SysKeyboardAImpl,iface);
374 char xbuf[50];
376 if (HIWORD(rguid))
377 WINE_StringFromCLSID(rguid,xbuf);
378 else
379 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
380 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ph);
381 TRACE(dinput,"(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
382 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
383 if (!HIWORD(rguid)) {
384 switch ((DWORD)rguid) {
385 case DIPROP_BUFFERSIZE: {
386 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
388 TRACE(dinput,"(buffersize=%ld)\n",pd->dwData);
389 break;
391 default:
392 WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
393 break;
396 return 0;
399 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
400 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
403 if (len==256) {
404 int keyc,vkey;
406 memset(ptr,0,256);
407 for (keyc=min_keycode;keyc<max_keycode;keyc++)
409 /* X keycode to virtual key */
410 vkey = keyc2vkey[keyc] & 0xFF;
411 /* The windows scancode is keyc-min_keycode */
412 if (InputKeyStateTable[vkey]&0x80) {
413 ((LPBYTE)ptr)[keyc-min_keycode]=0x80;
414 ((LPBYTE)ptr)[(keyc-min_keycode)|0x80]=0x80;
417 return 0;
419 WARN(dinput,"whoops, SysKeyboardAImpl_GetDeviceState got len %ld?\n",len);
420 return 0;
423 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
424 LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
425 LPDWORD entries,DWORD flags
428 ICOM_THIS(SysKeyboardAImpl,iface);
429 int keyc,n,vkey,xentries;
431 TRACE(dinput,"(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
432 This,dodsize,dod,entries,entries?*entries:0,flags);
433 EVENT_WaitNetEvent(FALSE,TRUE);
434 if (entries)
435 xentries = *entries;
436 else
437 xentries = 1;
439 n = 0;
441 for (keyc=min_keycode;(keyc<max_keycode) && (n<*entries);keyc++)
443 /* X keycode to virtual key */
444 vkey = keyc2vkey[keyc] & 0xFF;
445 if (This->keystate[vkey] == (InputKeyStateTable[vkey]&0x80))
446 continue;
447 if (dod) {
448 /* add an entry */
449 dod[n].dwOfs = keyc-min_keycode; /* scancode */
450 dod[n].dwData = InputKeyStateTable[vkey]&0x80;
451 dod[n].dwTimeStamp = 0; /* umm */
452 dod[n].dwSequence = 0; /* umm */
453 n++;
455 if (!(flags & DIGDD_PEEK))
456 This->keystate[vkey] = InputKeyStateTable[vkey]&0x80;
460 if (n) fprintf(stderr,"%d entries\n",n);
461 *entries = n;
462 return 0;
465 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
467 ICOM_THIS(SysKeyboardAImpl,iface);
468 TRACE(dinput,"(this=%p): stub\n",This);
469 return 0;
472 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
474 ICOM_THIS(SysKeyboardAImpl,iface);
475 TRACE(dinput,"(this=%p): stub\n",This);
476 return 0;
479 static HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
480 LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
483 ICOM_THIS(IDirectInputDevice2AImpl,iface);
484 char xbuf[50];
486 WINE_StringFromCLSID(riid,xbuf);
487 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ppobj);
488 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
489 IDirectInputDevice2_AddRef(iface);
490 *ppobj = This;
491 return 0;
493 if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
494 IDirectInputDevice2_AddRef(iface);
495 *ppobj = This;
496 return 0;
498 if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
499 IDirectInputDevice2_AddRef(iface);
500 *ppobj = This;
501 return 0;
503 return E_FAIL;
506 static ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
507 LPDIRECTINPUTDEVICE2A iface)
509 ICOM_THIS(IDirectInputDevice2AImpl,iface);
510 return ++This->ref;
513 static HRESULT WINAPI IDirectInputDevice2AImpl_GetCapabilities(
514 LPDIRECTINPUTDEVICE2A iface,
515 LPDIDEVCAPS lpDIDevCaps)
517 FIXME(dinput, "stub!\n");
518 return DI_OK;
521 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
522 LPDIRECTINPUTDEVICE2A iface,
523 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
524 LPVOID lpvRef,
525 DWORD dwFlags)
527 FIXME(dinput, "stub!\n");
528 #if 0
529 if (lpCallback)
530 lpCallback(NULL, lpvRef);
531 #endif
532 return DI_OK;
535 static HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
536 LPDIRECTINPUTDEVICE2A iface,
537 REFGUID rguid,
538 LPDIPROPHEADER pdiph)
540 FIXME(dinput, "stub!\n");
541 return DI_OK;
544 static HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
545 LPDIRECTINPUTDEVICE2A iface,
546 LPDIDEVICEOBJECTINSTANCEA pdidoi,
547 DWORD dwObj,
548 DWORD dwHow)
550 FIXME(dinput, "stub!\n");
551 return DI_OK;
554 static HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
555 LPDIRECTINPUTDEVICE2A iface,
556 LPDIDEVICEINSTANCEA pdidi)
558 FIXME(dinput, "stub!\n");
559 return DI_OK;
562 static HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
563 LPDIRECTINPUTDEVICE2A iface,
564 HWND hwndOwner,
565 DWORD dwFlags)
567 FIXME(dinput, "stub!\n");
568 return DI_OK;
571 static HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
572 LPDIRECTINPUTDEVICE2A iface,
573 HINSTANCE hinst,
574 DWORD dwVersion,
575 REFGUID rguid)
577 FIXME(dinput, "stub!\n");
578 return DI_OK;
581 /******************************************************************************
582 * IDirectInputDevice2A
585 static HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
586 LPDIRECTINPUTDEVICE2A iface,
587 REFGUID rguid,
588 LPCDIEFFECT lpeff,
589 LPDIRECTINPUTEFFECT *ppdef,
590 LPUNKNOWN pUnkOuter)
592 FIXME(dinput, "stub!\n");
593 return DI_OK;
596 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
597 LPDIRECTINPUTDEVICE2A iface,
598 LPDIENUMEFFECTSCALLBACKA lpCallback,
599 LPVOID lpvRef,
600 DWORD dwFlags)
602 FIXME(dinput, "stub!\n");
603 if (lpCallback)
604 lpCallback(NULL, lpvRef);
605 return DI_OK;
608 static HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
609 LPDIRECTINPUTDEVICE2A iface,
610 LPDIEFFECTINFOA lpdei,
611 REFGUID rguid)
613 FIXME(dinput, "stub!\n");
614 return DI_OK;
617 static HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
618 LPDIRECTINPUTDEVICE2A iface,
619 LPDWORD pdwOut)
621 FIXME(dinput, "stub!\n");
622 return DI_OK;
625 static HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
626 LPDIRECTINPUTDEVICE2A iface,
627 DWORD dwFlags)
629 FIXME(dinput, "stub!\n");
630 return DI_OK;
633 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
634 LPDIRECTINPUTDEVICE2A iface,
635 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
636 LPVOID lpvRef,
637 DWORD dwFlags)
639 FIXME(dinput, "stub!\n");
640 if (lpCallback)
641 lpCallback(NULL, lpvRef);
642 return DI_OK;
645 static HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
646 LPDIRECTINPUTDEVICE2A iface,
647 LPDIEFFESCAPE lpDIEEsc)
649 FIXME(dinput, "stub!\n");
650 return DI_OK;
653 static HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
654 LPDIRECTINPUTDEVICE2A iface)
656 FIXME(dinput, "stub!\n");
657 return DI_OK;
660 static HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
661 LPDIRECTINPUTDEVICE2A iface,
662 DWORD cbObjectData,
663 LPDIDEVICEOBJECTDATA rgdod,
664 LPDWORD pdwInOut,
665 DWORD dwFlags)
667 FIXME(dinput, "stub!\n");
668 return DI_OK;
671 /******************************************************************************
672 * SysMouseA (DInput Mouse support)
675 /******************************************************************************
676 * Release : release the mouse buffer.
678 static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
680 ICOM_THIS(SysMouseAImpl,iface);
682 This->ref--;
683 if (This->ref)
684 return This->ref;
686 /* Free the data queue */
687 if (This->data_queue != NULL)
688 HeapFree(GetProcessHeap(),0,This->data_queue);
690 /* Install the previous event handler (in case of releasing an aquired
691 mouse device) */
692 if (This->prev_handler != NULL)
693 MOUSE_Enable(This->prev_handler);
695 HeapFree(GetProcessHeap(),0,This);
696 return 0;
700 /******************************************************************************
701 * SetCooperativeLevel : store the window in which we will do our
702 * grabbing.
704 static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
705 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
708 ICOM_THIS(SysMouseAImpl,iface);
710 TRACE(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
712 if (TRACE_ON(dinput))
713 _dump_cooperativelevel(dwflags);
715 /* Store the window which asks for the mouse */
716 This->win = hwnd;
718 return 0;
722 /******************************************************************************
723 * SetDataFormat : the application can choose the format of the data
724 * the device driver sends back with GetDeviceState.
726 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
727 * in absolute and relative mode.
729 static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
730 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
733 ICOM_THIS(SysMouseAImpl,iface);
734 int i;
736 TRACE(dinput,"(this=%p,%p)\n",This,df);
738 TRACE(dinput,"(df.dwSize=%ld)\n",df->dwSize);
739 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
740 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
741 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
742 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
744 for (i=0;i<df->dwNumObjs;i++) {
745 char xbuf[50];
747 if (df->rgodf[i].pguid)
748 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
749 else
750 strcpy(xbuf,"<no guid>");
751 TRACE(dinput,"df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
752 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
753 TRACE(dinput,"dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
754 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
757 /* Check size of data format to prevent crashes if the applications
758 sends a smaller buffer */
759 if (df->dwDataSize != sizeof(struct DIMOUSESTATE)) {
760 FIXME(dinput, "non-standard mouse configuration not supported yet.");
761 return DIERR_INVALIDPARAM;
764 /* For the moment, ignore these fields and return always as if
765 c_dfDIMouse was passed as format... */
767 /* Check if the mouse is in absolute or relative mode */
768 if (df->dwFlags == DIDF_ABSAXIS)
769 This->absolute = 1;
770 else
771 This->absolute = 0;
773 return 0;
776 #define GEN_EVENT(offset,data,time,seq) \
778 if (This->queue_pos < This->queue_len) { \
779 This->data_queue[This->queue_pos].dwOfs = offset; \
780 This->data_queue[This->queue_pos].dwData = data; \
781 This->data_queue[This->queue_pos].dwTimeStamp = time; \
782 This->data_queue[This->queue_pos].dwSequence = seq; \
783 This->queue_pos++; \
787 /* Our private mouse event handler */
788 static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
789 DWORD cButtons, DWORD dwExtraInfo )
791 DWORD posX, posY, keyState, time, extra;
792 SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
794 if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
795 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
796 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
797 keyState = wme->keyState;
798 time = wme->time;
799 extra = (DWORD)wme->hWnd;
801 assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
802 posX = (dx * SYSMETRICS_CXSCREEN) >> 16;
803 posY = (dy * SYSMETRICS_CYSCREEN) >> 16;
804 } else {
805 ERR(dinput, "Mouse event not supported...\n");
806 return ;
809 TRACE(dinput, " %ld %ld ", posX, posY);
811 if ( dwFlags & MOUSEEVENTF_MOVE ) {
812 if (This->absolute) {
813 if (posX != This->prevX)
814 GEN_EVENT(DIMOFS_X, posX, time, 0);
815 if (posY != This->prevY)
816 GEN_EVENT(DIMOFS_Y, posY, time, 0);
817 } else {
818 /* Relative mouse input : the real fun starts here... */
819 if (This->need_warp) {
820 if (posX != This->prevX)
821 GEN_EVENT(DIMOFS_X, posX - This->prevX, time, 0);
822 if (posY != This->prevY)
823 GEN_EVENT(DIMOFS_Y, posY - This->prevY, time, 0);
824 } else {
825 /* This is the first time the event handler has been called after a
826 GetData of GetState. */
827 if (posX != This->win_centerX) {
828 GEN_EVENT(DIMOFS_X, posX - This->win_centerX, time, 0);
829 This->need_warp = 1;
832 if (posY != This->win_centerY) {
833 GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, time, 0);
834 This->need_warp = 1;
839 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
840 if (TRACE_ON(dinput))
841 DUMP(" LD ");
843 GEN_EVENT(DIMOFS_BUTTON0, 0xFF, time, 0);
845 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
846 if (TRACE_ON(dinput))
847 DUMP(" LU ");
849 GEN_EVENT(DIMOFS_BUTTON0, 0x00, time, 0);
851 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
852 if (TRACE_ON(dinput))
853 DUMP(" RD ");
855 GEN_EVENT(DIMOFS_BUTTON1, 0xFF, time, 0);
857 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
858 if (TRACE_ON(dinput))
859 DUMP(" RU ");
861 GEN_EVENT(DIMOFS_BUTTON1, 0x00, time, 0);
863 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
864 if (TRACE_ON(dinput))
865 DUMP(" MD ");
867 GEN_EVENT(DIMOFS_BUTTON2, 0xFF, time, 0);
869 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
870 if (TRACE_ON(dinput))
871 DUMP(" MU ");
873 GEN_EVENT(DIMOFS_BUTTON2, 0x00, time, 0);
875 if (TRACE_ON(dinput))
876 DUMP("\n");
878 This->prevX = posX;
879 This->prevY = posY;
883 /******************************************************************************
884 * Acquire : gets exclusive control of the mouse
886 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
888 ICOM_THIS(SysMouseAImpl,iface);
889 RECT rect;
891 TRACE(dinput,"(this=%p)\n",This);
893 if (This->acquired == 0) {
894 /* This stores the current mouse handler.
895 FIXME : need to be fixed for native USER use */
896 This->prev_handler = mouse_event;
898 /* Store (in a global variable) the current lock */
899 current_lock = (IDirectInputDevice2A*)This;
901 /* Install our own mouse event handler */
902 MOUSE_Enable(dinput_mouse_event);
904 /* Get the window dimension and find the center */
905 GetWindowRect(This->win, &rect);
906 This->xwin = ((X11DRV_WND_DATA *) WIN_FindWndPtr(This->win)->pDriverData)->window;
907 This->win_centerX = (rect.right - rect.left) / 2;
908 This->win_centerY = (rect.bottom - rect.top ) / 2;
909 /* Warp the mouse to the center of the window */
910 TRACE(dinput, "Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
911 TSXWarpPointer(display, DefaultRootWindow(display),
912 This->xwin, 0, 0, 0, 0,
913 This->win_centerX, This->win_centerY);
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 TRACE(dinput, "Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
987 TSXWarpPointer(display, DefaultRootWindow(display),
988 This->xwin, 0, 0, 0, 0,
989 This->win_centerX, This->win_centerY);
990 This->need_warp = 0;
993 TRACE(dinput, "(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
994 mstate->lX, mstate->lY,
995 mstate->rgbButtons[0], mstate->rgbButtons[2], mstate->rgbButtons[1]);
997 return 0;
1000 /******************************************************************************
1001 * GetDeviceState : gets buffered input data.
1003 static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1004 DWORD dodsize,
1005 LPDIDEVICEOBJECTDATA dod,
1006 LPDWORD entries,
1007 DWORD flags
1009 ICOM_THIS(SysMouseAImpl,iface);
1011 TRACE(dinput,"(%p)->(%ld,%p,%p(0x%08lx),0x%08lx)\n",
1012 This,dodsize,dod,entries,*entries,flags);
1014 if (flags & DIGDD_PEEK)
1015 TRACE(dinput, "DIGDD_PEEK\n");
1017 if (dod == NULL) {
1018 *entries = This->queue_pos;
1019 This->queue_pos = 0;
1020 } else {
1021 /* Check for buffer overflow */
1022 if (This->queue_pos > *entries) {
1023 WARN(dinput, "Buffer overflow not handled properly yet...\n");
1024 This->queue_pos = *entries;
1026 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1027 ERR(dinput, "Wrong structure size !\n");
1028 return DIERR_INVALIDPARAM;
1031 TRACE(dinput, "Application retrieving %d event(s).\n", This->queue_pos);
1033 /* Copy the buffered data into the application queue */
1034 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1036 /* Reset the event queue */
1037 This->queue_pos = 0;
1040 /* Check if we need to do a mouse warping */
1041 if (This->need_warp) {
1042 TRACE(dinput, "Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1043 TSXWarpPointer(display, DefaultRootWindow(display),
1044 This->xwin, 0, 0, 0, 0,
1045 This->win_centerX, This->win_centerY);
1046 This->need_warp = 0;
1049 return 0;
1052 /******************************************************************************
1053 * SetProperty : change input device properties
1055 static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1056 REFGUID rguid,
1057 LPCDIPROPHEADER ph)
1059 ICOM_THIS(SysMouseAImpl,iface);
1060 char xbuf[50];
1062 if (HIWORD(rguid))
1063 WINE_StringFromCLSID(rguid,xbuf);
1064 else
1065 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1067 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ph);
1069 if (!HIWORD(rguid)) {
1070 switch ((DWORD)rguid) {
1071 case DIPROP_BUFFERSIZE: {
1072 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1074 TRACE(dinput,"buffersize = %ld\n",pd->dwData);
1076 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1077 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1078 This->queue_pos = 0;
1079 This->queue_len = pd->dwData;
1080 break;
1082 default:
1083 WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
1084 break;
1088 return 0;
1092 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt={
1093 IDirectInputDevice2AImpl_QueryInterface,
1094 IDirectInputDevice2AImpl_AddRef,
1095 IDirectInputDevice2AImpl_Release,
1096 IDirectInputDevice2AImpl_GetCapabilities,
1097 IDirectInputDevice2AImpl_EnumObjects,
1098 IDirectInputDevice2AImpl_GetProperty,
1099 SysKeyboardAImpl_SetProperty,
1100 SysKeyboardAImpl_Acquire,
1101 SysKeyboardAImpl_Unacquire,
1102 SysKeyboardAImpl_GetDeviceState,
1103 SysKeyboardAImpl_GetDeviceData,
1104 IDirectInputDevice2AImpl_SetDataFormat,
1105 IDirectInputDevice2AImpl_SetEventNotification,
1106 IDirectInputDevice2AImpl_SetCooperativeLevel,
1107 IDirectInputDevice2AImpl_GetObjectInfo,
1108 IDirectInputDevice2AImpl_GetDeviceInfo,
1109 IDirectInputDevice2AImpl_RunControlPanel,
1110 IDirectInputDevice2AImpl_Initialize,
1111 IDirectInputDevice2AImpl_CreateEffect,
1112 IDirectInputDevice2AImpl_EnumEffects,
1113 IDirectInputDevice2AImpl_GetEffectInfo,
1114 IDirectInputDevice2AImpl_GetForceFeedbackState,
1115 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1116 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1117 IDirectInputDevice2AImpl_Escape,
1118 IDirectInputDevice2AImpl_Poll,
1119 IDirectInputDevice2AImpl_SendDeviceData,
1122 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt={
1123 IDirectInputDevice2AImpl_QueryInterface,
1124 IDirectInputDevice2AImpl_AddRef,
1125 SysMouseAImpl_Release,
1126 IDirectInputDevice2AImpl_GetCapabilities,
1127 IDirectInputDevice2AImpl_EnumObjects,
1128 IDirectInputDevice2AImpl_GetProperty,
1129 SysMouseAImpl_SetProperty,
1130 SysMouseAImpl_Acquire,
1131 SysMouseAImpl_Unacquire,
1132 SysMouseAImpl_GetDeviceState,
1133 SysMouseAImpl_GetDeviceData,
1134 SysMouseAImpl_SetDataFormat,
1135 IDirectInputDevice2AImpl_SetEventNotification,
1136 SysMouseAImpl_SetCooperativeLevel,
1137 IDirectInputDevice2AImpl_GetObjectInfo,
1138 IDirectInputDevice2AImpl_GetDeviceInfo,
1139 IDirectInputDevice2AImpl_RunControlPanel,
1140 IDirectInputDevice2AImpl_Initialize,
1141 IDirectInputDevice2AImpl_CreateEffect,
1142 IDirectInputDevice2AImpl_EnumEffects,
1143 IDirectInputDevice2AImpl_GetEffectInfo,
1144 IDirectInputDevice2AImpl_GetForceFeedbackState,
1145 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1146 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1147 IDirectInputDevice2AImpl_Escape,
1148 IDirectInputDevice2AImpl_Poll,
1149 IDirectInputDevice2AImpl_SendDeviceData,