Release 990214.
[wine/multimedia.git] / windows / dinput.c
blob52379bd3a3a793b226d3448bfc9ee8243ae6922b
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 "windows.h"
28 #include "winerror.h"
29 #include "shell.h"
30 #include "gdi.h"
31 #include "heap.h"
32 #include "win.h"
33 #include "dinput.h"
34 #include "objbase.h"
35 #include "debug.h"
36 #include "message.h"
38 #include "mouse.h"
39 #include "ts_xlib.h"
40 #include "sysmetrics.h"
41 #include "x11drv.h"
43 extern BYTE InputKeyStateTable[256];
44 extern int min_keycode, max_keycode;
45 extern WORD keyc2vkey[256];
47 static IDirectInputA_VTable ddiavt;
48 static IDirectInputDeviceA_VTable SysKeyboardAvt;
49 static IDirectInputDeviceA_VTable SysMouseAvt;
51 /* UIDs for Wine "drivers".
52 When enumerating each device supporting DInput, they have two UIDs :
53 - the 'windows' UID
54 - a vendor UID */
55 static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
56 0x9e573ed8,
57 0x7734,
58 0x11d2,
59 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
61 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
62 0x0ab8648a,
63 0x7735,
64 0x11d2,
65 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
68 /* This is ugly and not thread safe :/ */
69 static LPDIRECTINPUTDEVICE32A current_lock = NULL;
71 /******************************************************************************
72 * Various debugging tools
74 static void _dump_cooperativelevel(DWORD dwFlags) {
75 int i;
76 const struct {
77 DWORD mask;
78 char *name;
79 } flags[] = {
80 #define FE(x) { x, #x},
81 FE(DISCL_BACKGROUND)
82 FE(DISCL_EXCLUSIVE)
83 FE(DISCL_FOREGROUND)
84 FE(DISCL_NONEXCLUSIVE)
86 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
87 if (flags[i].mask & dwFlags)
88 DUMP("%s ",flags[i].name);
89 DUMP("\n");
93 /******************************************************************************
94 * DirectInputCreate32A
96 HRESULT WINAPI DirectInputCreate32A(HINSTANCE32 hinst, DWORD dwVersion, LPDIRECTINPUT32A *ppDI, LPUNKNOWN punkOuter) {
97 TRACE(dinput, "(0x%08lx,%04lx,%p,%p)\n",
98 (DWORD)hinst,dwVersion,ppDI,punkOuter
100 (*ppDI) = (LPDIRECTINPUT32A)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInput32A));
101 (*ppDI)->ref = 1;
102 (*ppDI)->lpvtbl = &ddiavt;
103 return 0;
105 /******************************************************************************
106 * IDirectInputA_EnumDevices
108 static HRESULT WINAPI IDirectInputA_EnumDevices(
109 LPDIRECTINPUT32A this, DWORD dwDevType, LPDIENUMDEVICESCALLBACK32A lpCallback,
110 LPVOID pvRef, DWORD dwFlags
112 DIDEVICEINSTANCE32A devInstance;
113 int ret;
115 TRACE(dinput, "(this=%p,0x%04lx,%p,%p,%04lx)\n", this, dwDevType, lpCallback, pvRef, dwFlags);
117 devInstance.dwSize = sizeof(DIDEVICEINSTANCE32A);
119 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
120 /* Return keyboard */
121 devInstance.guidInstance = GUID_SysKeyboard; /* DInput's GUID */
122 devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
123 devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
124 strcpy(devInstance.tszInstanceName, "Keyboard");
125 strcpy(devInstance.tszProductName, "Wine Keyboard");
127 ret = lpCallback(&devInstance, pvRef);
128 TRACE(dinput, "Keyboard registered\n");
130 if (ret == DIENUM_STOP)
131 return 0;
134 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
135 /* Return mouse */
136 devInstance.guidInstance = GUID_SysMouse; /* DInput's GUID */
137 devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
138 devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
139 strcpy(devInstance.tszInstanceName, "Mouse");
140 strcpy(devInstance.tszProductName, "Wine Mouse");
142 ret = lpCallback(&devInstance, pvRef);
143 TRACE(dinput, "Mouse registered\n");
146 /* Should also do joystick enumerations.... */
148 return 0;
151 static ULONG WINAPI IDirectInputA_AddRef(LPDIRECTINPUT32A this) {
152 return ++(this->ref);
155 static ULONG WINAPI IDirectInputA_Release(LPDIRECTINPUT32A this) {
156 if (!(--this->ref)) {
157 HeapFree(GetProcessHeap(),0,this);
158 return 0;
160 return this->ref;
163 static HRESULT WINAPI IDirectInputA_CreateDevice(
164 LPDIRECTINPUT32A this,REFGUID rguid,LPDIRECTINPUTDEVICE32A* pdev,
165 LPUNKNOWN punk
167 char xbuf[50];
169 WINE_StringFromCLSID(rguid,xbuf);
170 FIXME(dinput,"(this=%p,%s,%p,%p): stub\n",this,xbuf,pdev,punk);
171 if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) || /* Generic Keyboard */
172 (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
173 *pdev = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboard32A));
174 (*pdev)->ref = 1;
175 (*pdev)->lpvtbl = &SysKeyboardAvt;
176 memcpy(&((*pdev)->guid),rguid,sizeof(*rguid));
177 memset(((LPSYSKEYBOARD32A)(*pdev))->keystate,0,256);
178 return 0;
180 if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) || /* Generic Mouse */
181 (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysMouse)))) { /* Wine Mouse */
182 *pdev = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouse32A));
183 (*pdev)->ref = 1;
184 (*pdev)->lpvtbl = &SysMouseAvt;
185 memcpy(&((*pdev)->guid),rguid,sizeof(*rguid));
186 return 0;
188 return E_FAIL;
191 static HRESULT WINAPI IDirectInputA_QueryInterface(
192 LPDIRECTINPUT32A this,REFIID riid,LPVOID *ppobj
194 char xbuf[50];
196 WINE_StringFromCLSID(riid,xbuf);
197 TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ppobj);
198 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
199 this->lpvtbl->fnAddRef(this);
200 *ppobj = this;
201 return 0;
203 if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
204 this->lpvtbl->fnAddRef(this);
205 *ppobj = this;
206 return 0;
208 return E_FAIL;
211 static HRESULT WINAPI IDirectInputA_Initialize(
212 LPDIRECTINPUT32A this,HINSTANCE32 hinst,DWORD x
214 return DIERR_ALREADYINITIALIZED;
217 static IDirectInputA_VTable ddiavt= {
218 IDirectInputA_QueryInterface,
219 IDirectInputA_AddRef,
220 IDirectInputA_Release,
221 IDirectInputA_CreateDevice,
222 IDirectInputA_EnumDevices,
223 (void*)6,
224 (void*)7,
225 IDirectInputA_Initialize
228 /******************************************************************************
229 * IDirectInputDeviceA
231 static HRESULT WINAPI IDirectInputDeviceA_SetDataFormat(
232 LPDIRECTINPUTDEVICE32A this,LPCDIDATAFORMAT df
235 int i;
236 TRACE(dinput,"(this=%p,%p)\n",this,df);
238 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
239 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
240 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
241 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
242 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
244 for (i=0;i<df->dwNumObjs;i++) {
245 char xbuf[50];
247 if (df->rgodf[i].pguid)
248 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
249 else
250 strcpy(xbuf,"<no guid>");
251 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
252 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
253 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
254 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
257 return 0;
260 static HRESULT WINAPI IDirectInputDeviceA_SetCooperativeLevel(
261 LPDIRECTINPUTDEVICE32A this,HWND32 hwnd,DWORD dwflags
263 FIXME(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",this,(DWORD)hwnd,dwflags);
264 if (TRACE_ON(dinput))
265 _dump_cooperativelevel(dwflags);
266 return 0;
269 static HRESULT WINAPI IDirectInputDeviceA_SetEventNotification(
270 LPDIRECTINPUTDEVICE32A this,HANDLE32 hnd
272 FIXME(dinput,"(this=%p,0x%08lx): stub\n",this,(DWORD)hnd);
273 return 0;
276 static ULONG WINAPI IDirectInputDeviceA_Release(LPDIRECTINPUTDEVICE32A this) {
277 this->ref--;
278 if (this->ref)
279 return this->ref;
280 HeapFree(GetProcessHeap(),0,this);
281 return 0;
284 static HRESULT WINAPI SysKeyboardA_SetProperty(
285 LPDIRECTINPUTDEVICE32A this,REFGUID rguid,LPCDIPROPHEADER ph
287 char xbuf[50];
289 if (HIWORD(rguid))
290 WINE_StringFromCLSID(rguid,xbuf);
291 else
292 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
293 TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ph);
294 TRACE(dinput,"(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
295 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
296 if (!HIWORD(rguid)) {
297 switch ((DWORD)rguid) {
298 case DIPROP_BUFFERSIZE: {
299 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
301 TRACE(dinput,"(buffersize=%ld)\n",pd->dwData);
302 break;
304 default:
305 WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
306 break;
309 return 0;
312 static HRESULT WINAPI SysKeyboardA_GetDeviceState(
313 LPDIRECTINPUTDEVICE32A this,DWORD len,LPVOID ptr
315 if (len==256) {
316 int keyc,vkey;
318 memset(ptr,0,256);
319 for (keyc=min_keycode;keyc<max_keycode;keyc++)
321 /* X keycode to virtual key */
322 vkey = keyc2vkey[keyc] & 0xFF;
323 /* The windows scancode is keyc-min_keycode */
324 if (InputKeyStateTable[vkey]&0x80) {
325 ((LPBYTE)ptr)[keyc-min_keycode]=0x80;
326 ((LPBYTE)ptr)[(keyc-min_keycode)|0x80]=0x80;
329 return 0;
331 WARN(dinput,"whoops, SysKeyboardA_GetDeviceState got len %ld?\n",len);
332 return 0;
335 static HRESULT WINAPI SysKeyboardA_GetDeviceData(
336 LPDIRECTINPUTDEVICE32A this,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
337 LPDWORD entries,DWORD flags
339 int keyc,n,vkey,xentries;
340 LPSYSKEYBOARD32A kthis = (LPSYSKEYBOARD32A)this;
342 TRACE(dinput,"(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
343 this,dodsize,dod,entries,entries?*entries:0,flags);
344 EVENT_WaitNetEvent(FALSE,TRUE);
345 if (entries)
346 xentries = *entries;
347 else
348 xentries = 1;
350 n = 0;
352 for (keyc=min_keycode;(keyc<max_keycode) && (n<*entries);keyc++)
354 /* X keycode to virtual key */
355 vkey = keyc2vkey[keyc] & 0xFF;
356 if (kthis->keystate[vkey] == (InputKeyStateTable[vkey]&0x80))
357 continue;
358 if (dod) {
359 /* add an entry */
360 dod[n].dwOfs = keyc-min_keycode; /* scancode */
361 dod[n].dwData = InputKeyStateTable[vkey]&0x80;
362 dod[n].dwTimeStamp = 0; /* umm */
363 dod[n].dwSequence = 0; /* umm */
364 n++;
366 if (!(flags & DIGDD_PEEK))
367 kthis->keystate[vkey] = InputKeyStateTable[vkey]&0x80;
371 if (n) fprintf(stderr,"%d entries\n",n);
372 *entries = n;
373 return 0;
376 static HRESULT WINAPI SysKeyboardA_Acquire(LPDIRECTINPUTDEVICE32A this) {
377 TRACE(dinput,"(this=%p): stub\n",this);
378 return 0;
381 static HRESULT WINAPI SysKeyboardA_Unacquire(LPDIRECTINPUTDEVICE32A this) {
382 TRACE(dinput,"(this=%p): stub\n",this);
383 return 0;
386 static HRESULT WINAPI IDirectInputDeviceA_QueryInterface(
387 LPDIRECTINPUTDEVICE32A this,REFIID riid,LPVOID *ppobj
389 char xbuf[50];
391 WINE_StringFromCLSID(riid,xbuf);
392 TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ppobj);
393 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
394 this->lpvtbl->fnAddRef(this);
395 *ppobj = this;
396 return 0;
398 if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
399 this->lpvtbl->fnAddRef(this);
400 *ppobj = this;
401 return 0;
403 if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
404 this->lpvtbl->fnAddRef(this);
405 *ppobj = this;
406 return 0;
408 return E_FAIL;
411 static ULONG WINAPI IDirectInputDeviceA_AddRef(
412 LPDIRECTINPUTDEVICE32A this)
414 return ++this->ref;
417 static HRESULT WINAPI IDirectInputDeviceA_GetCapabilities(
418 LPDIRECTINPUTDEVICE32A this,
419 LPDIDEVCAPS lpDIDevCaps)
421 FIXME(dinput, "stub!\n");
422 return DI_OK;
425 static HRESULT WINAPI IDirectInputDeviceA_EnumObjects(
426 LPDIRECTINPUTDEVICE32A this,
427 LPDIENUMDEVICEOBJECTSCALLBACK32A lpCallback,
428 LPVOID lpvRef,
429 DWORD dwFlags)
431 FIXME(dinput, "stub!\n");
432 #if 0
433 if (lpCallback)
434 lpCallback(NULL, lpvRef);
435 #endif
436 return DI_OK;
439 static HRESULT WINAPI IDirectInputDeviceA_GetProperty(
440 LPDIRECTINPUTDEVICE32A this,
441 REFGUID rguid,
442 LPDIPROPHEADER pdiph)
444 FIXME(dinput, "stub!\n");
445 return DI_OK;
448 static HRESULT WINAPI IDirectInputDeviceA_GetObjectInfo(
449 LPDIRECTINPUTDEVICE32A this,
450 LPDIDEVICEOBJECTINSTANCE32A pdidoi,
451 DWORD dwObj,
452 DWORD dwHow)
454 FIXME(dinput, "stub!\n");
455 return DI_OK;
458 static HRESULT WINAPI IDirectInputDeviceA_GetDeviceInfo(
459 LPDIRECTINPUTDEVICE32A this,
460 LPDIDEVICEINSTANCE32A pdidi)
462 FIXME(dinput, "stub!\n");
463 return DI_OK;
466 static HRESULT WINAPI IDirectInputDeviceA_RunControlPanel(
467 LPDIRECTINPUTDEVICE32A this,
468 HWND32 hwndOwner,
469 DWORD dwFlags)
471 FIXME(dinput, "stub!\n");
472 return DI_OK;
475 static HRESULT WINAPI IDirectInputDeviceA_Initialize(
476 LPDIRECTINPUTDEVICE32A this,
477 HINSTANCE32 hinst,
478 DWORD dwVersion,
479 REFGUID rguid)
481 FIXME(dinput, "stub!\n");
482 return DI_OK;
485 /******************************************************************************
486 * IDirectInputDevice2A
489 static HRESULT WINAPI IDirectInputDevice2A_CreateEffect(
490 LPDIRECTINPUTDEVICE32A this,
491 REFGUID rguid,
492 LPCDIEFFECT lpeff,
493 LPDIRECTINPUTEFFECT *ppdef,
494 LPUNKNOWN pUnkOuter)
496 FIXME(dinput, "stub!\n");
497 return DI_OK;
500 static HRESULT WINAPI IDirectInputDevice2A_EnumEffects(
501 LPDIRECTINPUTDEVICE32A this,
502 LPDIENUMEFFECTSCALLBACKA lpCallback,
503 LPVOID lpvRef,
504 DWORD dwFlags)
506 FIXME(dinput, "stub!\n");
507 if (lpCallback)
508 lpCallback(NULL, lpvRef);
509 return DI_OK;
512 static HRESULT WINAPI IDirectInputDevice2A_GetEffectInfo(
513 LPDIRECTINPUTDEVICE32A this,
514 LPDIEFFECTINFOA lpdei,
515 REFGUID rguid)
517 FIXME(dinput, "stub!\n");
518 return DI_OK;
521 static HRESULT WINAPI IDirectInputDevice2A_GetForceFeedbackState(
522 LPDIRECTINPUTDEVICE32A this,
523 LPDWORD pdwOut)
525 FIXME(dinput, "stub!\n");
526 return DI_OK;
529 static HRESULT WINAPI IDirectInputDevice2A_SendForceFeedbackCommand(
530 LPDIRECTINPUTDEVICE32A this,
531 DWORD dwFlags)
533 FIXME(dinput, "stub!\n");
534 return DI_OK;
537 static HRESULT WINAPI IDirectInputDevice2A_EnumCreatedEffectObjects(
538 LPDIRECTINPUTDEVICE32A this,
539 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
540 LPVOID lpvRef,
541 DWORD dwFlags)
543 FIXME(dinput, "stub!\n");
544 if (lpCallback)
545 lpCallback(NULL, lpvRef);
546 return DI_OK;
549 static HRESULT WINAPI IDirectInputDevice2A_Escape(
550 LPDIRECTINPUTDEVICE32A this,
551 LPDIEFFESCAPE lpDIEEsc)
553 FIXME(dinput, "stub!\n");
554 return DI_OK;
557 static HRESULT WINAPI IDirectInputDevice2A_Poll(
558 LPDIRECTINPUTDEVICE32A this)
560 FIXME(dinput, "stub!\n");
561 return DI_OK;
564 static HRESULT WINAPI IDirectInputDevice2A_SendDeviceData(
565 LPDIRECTINPUTDEVICE32A this,
566 DWORD cbObjectData,
567 LPDIDEVICEOBJECTDATA rgdod,
568 LPDWORD pdwInOut,
569 DWORD dwFlags)
571 FIXME(dinput, "stub!\n");
572 return DI_OK;
575 /******************************************************************************
576 * SysMouseA (DInput Mouse support)
579 /******************************************************************************
580 * Release : release the mouse buffer.
582 static ULONG WINAPI SysMouseA_Release(LPDIRECTINPUTDEVICE32A this) {
583 LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
585 this->ref--;
586 if (this->ref)
587 return this->ref;
589 /* Free the data queue */
590 if (mthis->data_queue != NULL)
591 HeapFree(GetProcessHeap(),0,mthis->data_queue);
593 /* Install the previous event handler (in case of releasing an aquired
594 mouse device) */
595 if (mthis->prev_handler != NULL)
596 MOUSE_Enable(mthis->prev_handler);
598 HeapFree(GetProcessHeap(),0,this);
599 return 0;
603 /******************************************************************************
604 * SetCooperativeLevel : store the window in which we will do our
605 * grabbing.
607 static HRESULT WINAPI SysMouseA_SetCooperativeLevel(
608 LPDIRECTINPUTDEVICE32A this,HWND32 hwnd,DWORD dwflags
610 LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
612 TRACE(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",this,(DWORD)hwnd,dwflags);
614 if (TRACE_ON(dinput))
615 _dump_cooperativelevel(dwflags);
617 /* Store the window which asks for the mouse */
618 mthis->win = hwnd;
620 return 0;
624 /******************************************************************************
625 * SetDataFormat : the application can choose the format of the data
626 * the device driver sends back with GetDeviceState.
628 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
629 * in absolute and relative mode.
631 static HRESULT WINAPI SysMouseA_SetDataFormat(
632 LPDIRECTINPUTDEVICE32A this,LPCDIDATAFORMAT df
634 int i;
635 LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
637 TRACE(dinput,"(this=%p,%p)\n",this,df);
639 TRACE(dinput,"(df.dwSize=%ld)\n",df->dwSize);
640 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
641 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
642 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
643 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
645 for (i=0;i<df->dwNumObjs;i++) {
646 char xbuf[50];
648 if (df->rgodf[i].pguid)
649 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
650 else
651 strcpy(xbuf,"<no guid>");
652 TRACE(dinput,"df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
653 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
654 TRACE(dinput,"dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
655 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
658 /* Check size of data format to prevent crashes if the applications
659 sends a smaller buffer */
660 if (df->dwDataSize != sizeof(struct DIMOUSESTATE)) {
661 FIXME(dinput, "non-standard mouse configuration not supported yet.");
662 return DIERR_INVALIDPARAM;
665 /* For the moment, ignore these fields and return always as if
666 c_dfDIMouse was passed as format... */
668 /* Check if the mouse is in absolute or relative mode */
669 if (df->dwFlags == DIDF_ABSAXIS)
670 mthis->absolute = 1;
671 else
672 mthis->absolute = 0;
674 return 0;
677 #define GEN_EVENT(offset,data,time,seq) \
679 if (mthis->queue_pos < mthis->queue_len) { \
680 mthis->data_queue[mthis->queue_pos].dwOfs = offset; \
681 mthis->data_queue[mthis->queue_pos].dwData = data; \
682 mthis->data_queue[mthis->queue_pos].dwTimeStamp = time; \
683 mthis->data_queue[mthis->queue_pos].dwSequence = seq; \
684 mthis->queue_pos++; \
688 /* Our private mouse event handler */
689 static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
690 DWORD cButtons, DWORD dwExtraInfo )
692 DWORD posX, posY, keyState, time, extra;
693 LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) current_lock;
695 if ( !IsBadReadPtr32( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
696 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
697 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
698 keyState = wme->keyState;
699 time = wme->time;
700 extra = (DWORD)wme->hWnd;
702 assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
703 posX = (dx * SYSMETRICS_CXSCREEN) >> 16;
704 posY = (dy * SYSMETRICS_CYSCREEN) >> 16;
705 } else {
706 ERR(dinput, "Mouse event not supported...\n");
707 return ;
710 TRACE(dinput, " %ld %ld ", posX, posY);
712 if ( dwFlags & MOUSEEVENTF_MOVE ) {
713 if (mthis->absolute) {
714 if (posX != mthis->prevX)
715 GEN_EVENT(DIMOFS_X, posX, time, 0);
716 if (posY != mthis->prevY)
717 GEN_EVENT(DIMOFS_Y, posY, time, 0);
718 } else {
719 /* Relative mouse input : the real fun starts here... */
720 if (mthis->need_warp) {
721 if (posX != mthis->prevX)
722 GEN_EVENT(DIMOFS_X, posX - mthis->prevX, time, 0);
723 if (posY != mthis->prevY)
724 GEN_EVENT(DIMOFS_Y, posY - mthis->prevY, time, 0);
725 } else {
726 /* This is the first time the event handler has been called after a
727 GetData of GetState. */
728 if (posX != mthis->win_centerX) {
729 GEN_EVENT(DIMOFS_X, posX - mthis->win_centerX, time, 0);
730 mthis->need_warp = 1;
733 if (posY != mthis->win_centerY) {
734 GEN_EVENT(DIMOFS_Y, posY - mthis->win_centerY, time, 0);
735 mthis->need_warp = 1;
740 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
741 if (TRACE_ON(dinput))
742 DUMP(" LD ");
744 GEN_EVENT(DIMOFS_BUTTON0, 0xFF, time, 0);
746 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
747 if (TRACE_ON(dinput))
748 DUMP(" LU ");
750 GEN_EVENT(DIMOFS_BUTTON0, 0x00, time, 0);
752 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
753 if (TRACE_ON(dinput))
754 DUMP(" RD ");
756 GEN_EVENT(DIMOFS_BUTTON1, 0xFF, time, 0);
758 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
759 if (TRACE_ON(dinput))
760 DUMP(" RU ");
762 GEN_EVENT(DIMOFS_BUTTON1, 0x00, time, 0);
764 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
765 if (TRACE_ON(dinput))
766 DUMP(" MD ");
768 GEN_EVENT(DIMOFS_BUTTON2, 0xFF, time, 0);
770 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
771 if (TRACE_ON(dinput))
772 DUMP(" MU ");
774 GEN_EVENT(DIMOFS_BUTTON2, 0x00, time, 0);
776 if (TRACE_ON(dinput))
777 DUMP("\n");
779 mthis->prevX = posX;
780 mthis->prevY = posY;
784 /******************************************************************************
785 * Acquire : gets exclusive control of the mouse
787 static HRESULT WINAPI SysMouseA_Acquire(LPDIRECTINPUTDEVICE32A this) {
788 LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
789 RECT32 rect;
791 TRACE(dinput,"(this=%p)\n",this);
793 if (mthis->acquired == 0) {
794 /* This stores the current mouse handler.
795 FIXME : need to be fixed for native USER use */
796 mthis->prev_handler = mouse_event;
798 /* Store (in a global variable) the current lock */
799 current_lock = this;
801 /* Install our own mouse event handler */
802 MOUSE_Enable(dinput_mouse_event);
804 /* Get the window dimension and find the center */
805 GetWindowRect32(mthis->win, &rect);
806 mthis->xwin = ((X11DRV_WND_DATA *) WIN_FindWndPtr(mthis->win)->pDriverData)->window;
807 mthis->win_centerX = (rect.right - rect.left) / 2;
808 mthis->win_centerY = (rect.bottom - rect.top ) / 2;
809 /* Warp the mouse to the center of the window */
810 TRACE(dinput, "Warping mouse to %ld - %ld\n", mthis->win_centerX, mthis->win_centerY);
811 TSXWarpPointer(display, DefaultRootWindow(display),
812 mthis->xwin, 0, 0, 0, 0,
813 mthis->win_centerX, mthis->win_centerY);
815 mthis->acquired = 1;
817 return 0;
820 /******************************************************************************
821 * Unacquire : frees the mouse
823 static HRESULT WINAPI SysMouseA_Unacquire(LPDIRECTINPUTDEVICE32A this) {
824 LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
826 TRACE(dinput,"(this=%p)\n",this);
828 /* Reinstall previous mouse event handler */
829 MOUSE_Enable(mthis->prev_handler);
830 mthis->prev_handler = NULL;
832 /* No more locks */
833 current_lock = NULL;
835 /* Unacquire device */
836 mthis->acquired = 0;
838 return 0;
841 /******************************************************************************
842 * GetDeviceState : returns the "state" of the mouse.
844 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
845 * supported.
847 static HRESULT WINAPI SysMouseA_GetDeviceState(
848 LPDIRECTINPUTDEVICE32A this,DWORD len,LPVOID ptr
850 DWORD rx, ry, state;
851 struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
852 LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
854 TRACE(dinput,"(this=%p,0x%08lx,%p): \n",this,len,ptr);
856 /* Check if the buffer is big enough */
857 if (len < sizeof(struct DIMOUSESTATE)) {
858 FIXME(dinput, "unsupported state structure.");
859 return DIERR_INVALIDPARAM;
862 /* Get the mouse position */
863 EVENT_QueryPointer(&rx, &ry, &state);
864 TRACE(dinput,"(X:%ld - Y:%ld)\n", rx, ry);
866 /* Fill the mouse state structure */
867 if (mthis->absolute) {
868 mstate->lX = rx;
869 mstate->lY = ry;
870 } else {
871 mstate->lX = rx - mthis->win_centerX;
872 mstate->lY = ry - mthis->win_centerY;
874 if ((mstate->lX != 0) || (mstate->lY != 0))
875 mthis->need_warp = 1;
877 mstate->lZ = 0;
878 mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00);
879 mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00);
880 mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00);
881 mstate->rgbButtons[3] = 0x00;
883 /* Check if we need to do a mouse warping */
884 if (mthis->need_warp) {
885 TRACE(dinput, "Warping mouse to %ld - %ld\n", mthis->win_centerX, mthis->win_centerY);
886 TSXWarpPointer(display, DefaultRootWindow(display),
887 mthis->xwin, 0, 0, 0, 0,
888 mthis->win_centerX, mthis->win_centerY);
889 mthis->need_warp = 0;
892 TRACE(dinput, "(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
893 mstate->lX, mstate->lY,
894 mstate->rgbButtons[0], mstate->rgbButtons[2], mstate->rgbButtons[1]);
896 return 0;
899 /******************************************************************************
900 * GetDeviceState : gets buffered input data.
902 static HRESULT WINAPI SysMouseA_GetDeviceData(LPDIRECTINPUTDEVICE32A this,
903 DWORD dodsize,
904 LPDIDEVICEOBJECTDATA dod,
905 LPDWORD entries,
906 DWORD flags
908 LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
910 TRACE(dinput,"(%p)->(%ld,%p,%p(0x%08lx),0x%08lx)\n",
911 this,dodsize,dod,entries,*entries,flags);
913 if (flags & DIGDD_PEEK)
914 TRACE(dinput, "DIGDD_PEEK\n");
916 if (dod == NULL) {
917 *entries = mthis->queue_pos;
918 mthis->queue_pos = 0;
919 } else {
920 /* Check for buffer overflow */
921 if (mthis->queue_pos > *entries) {
922 WARN(dinput, "Buffer overflow not handled properly yet...\n");
923 mthis->queue_pos = *entries;
925 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
926 ERR(dinput, "Wrong structure size !\n");
927 return DIERR_INVALIDPARAM;
930 /* Copy the buffered data into the application queue */
931 memcpy(dod, mthis->data_queue, mthis->queue_pos * dodsize);
933 /* Reset the event queue */
934 mthis->queue_pos = 0;
937 /* Check if we need to do a mouse warping */
938 if (mthis->need_warp) {
939 TRACE(dinput, "Warping mouse to %ld - %ld\n", mthis->win_centerX, mthis->win_centerY);
940 TSXWarpPointer(display, DefaultRootWindow(display),
941 mthis->xwin, 0, 0, 0, 0,
942 mthis->win_centerX, mthis->win_centerY);
943 mthis->need_warp = 0;
946 return 0;
949 /******************************************************************************
950 * SetProperty : change input device properties
952 static HRESULT WINAPI SysMouseA_SetProperty(LPDIRECTINPUTDEVICE32A this,
953 REFGUID rguid,
954 LPCDIPROPHEADER ph) {
955 char xbuf[50];
956 LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
958 if (HIWORD(rguid))
959 WINE_StringFromCLSID(rguid,xbuf);
960 else
961 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
963 TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ph);
965 if (!HIWORD(rguid)) {
966 switch ((DWORD)rguid) {
967 case DIPROP_BUFFERSIZE: {
968 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
970 TRACE(dinput,"buffersize = %ld\n",pd->dwData);
972 mthis->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
973 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
974 mthis->queue_pos = 0;
975 mthis->queue_len = pd->dwData;
976 break;
978 default:
979 WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
980 break;
984 return 0;
988 static IDirectInputDeviceA_VTable SysKeyboardAvt={
989 IDirectInputDeviceA_QueryInterface,
990 IDirectInputDeviceA_AddRef,
991 IDirectInputDeviceA_Release,
992 IDirectInputDeviceA_GetCapabilities,
993 IDirectInputDeviceA_EnumObjects,
994 IDirectInputDeviceA_GetProperty,
995 SysKeyboardA_SetProperty,
996 SysKeyboardA_Acquire,
997 SysKeyboardA_Unacquire,
998 SysKeyboardA_GetDeviceState,
999 SysKeyboardA_GetDeviceData,
1000 IDirectInputDeviceA_SetDataFormat,
1001 IDirectInputDeviceA_SetEventNotification,
1002 IDirectInputDeviceA_SetCooperativeLevel,
1003 IDirectInputDeviceA_GetObjectInfo,
1004 IDirectInputDeviceA_GetDeviceInfo,
1005 IDirectInputDeviceA_RunControlPanel,
1006 IDirectInputDeviceA_Initialize,
1007 IDirectInputDevice2A_CreateEffect,
1008 IDirectInputDevice2A_EnumEffects,
1009 IDirectInputDevice2A_GetEffectInfo,
1010 IDirectInputDevice2A_GetForceFeedbackState,
1011 IDirectInputDevice2A_SendForceFeedbackCommand,
1012 IDirectInputDevice2A_EnumCreatedEffectObjects,
1013 IDirectInputDevice2A_Escape,
1014 IDirectInputDevice2A_Poll,
1015 IDirectInputDevice2A_SendDeviceData,
1018 static IDirectInputDeviceA_VTable SysMouseAvt={
1019 IDirectInputDeviceA_QueryInterface,
1020 IDirectInputDeviceA_AddRef,
1021 SysMouseA_Release,
1022 IDirectInputDeviceA_GetCapabilities,
1023 IDirectInputDeviceA_EnumObjects,
1024 IDirectInputDeviceA_GetProperty,
1025 SysMouseA_SetProperty,
1026 SysMouseA_Acquire,
1027 SysMouseA_Unacquire,
1028 SysMouseA_GetDeviceState,
1029 SysMouseA_GetDeviceData,
1030 SysMouseA_SetDataFormat,
1031 IDirectInputDeviceA_SetEventNotification,
1032 SysMouseA_SetCooperativeLevel,
1033 IDirectInputDeviceA_GetObjectInfo,
1034 IDirectInputDeviceA_GetDeviceInfo,
1035 IDirectInputDeviceA_RunControlPanel,
1036 IDirectInputDeviceA_Initialize,
1037 IDirectInputDevice2A_CreateEffect,
1038 IDirectInputDevice2A_EnumEffects,
1039 IDirectInputDevice2A_GetEffectInfo,
1040 IDirectInputDevice2A_GetForceFeedbackState,
1041 IDirectInputDevice2A_SendForceFeedbackCommand,
1042 IDirectInputDevice2A_EnumCreatedEffectObjects,
1043 IDirectInputDevice2A_Escape,
1044 IDirectInputDevice2A_Poll,
1045 IDirectInputDevice2A_SendDeviceData,