Moved more things to the X11 driver.
[wine] / windows / dinput.c
1 /*              DirectInput
2  *
3  * Copyright 1998 Marcus Meissner
4  *
5  * Additions (mouse support) Copyright 1998 Lionel Ulmer
6  */
7 /* Status:
8  *
9  * - Tomb Raider 2 Demo:
10  *   Playable using keyboard only.
11  * - WingCommander Prophecy Demo:
12  *   Doesn't get Input Focus.
13  * 
14  * - Fallout : works great in X and DGA mode
15  *
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.)
19  */
20
21 #include "config.h"
22 #include <string.h>
23 #include <unistd.h>
24 #include <assert.h>
25 #include <sys/signal.h>
26
27 #include "windows.h"
28 #include "winerror.h"
29 #include "shell.h"
30 #include "ole.h"
31 #include "compobj.h"
32 #include "interfaces.h"
33 #include "gdi.h"
34 #include "heap.h"
35 #include "win.h"
36 #include "dinput.h"
37 #include "debug.h"
38 #include "message.h"
39
40 extern BYTE InputKeyStateTable[256];
41 extern int min_keycode, max_keycode;
42 extern WORD keyc2vkey[256];
43
44 static IDirectInputA_VTable ddiavt;
45 static IDirectInputDeviceA_VTable SysKeyboardAvt;
46 static IDirectInputDeviceA_VTable SysMouseAvt;
47
48 /* UIDs for Wine "drivers".
49    When enumerating each device supporting DInput, they have two UIDs :
50     - the 'windows' UID
51     - a vendor UID */
52 static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
53   0x9e573ed8,
54   0x7734,
55   0x11d2,
56   {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
57 };
58 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
59   0x0ab8648a,
60   0x7735,
61   0x11d2,
62   {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
63 };
64
65 /******************************************************************************
66  *      DirectInputCreate32A
67  */
68 HRESULT WINAPI DirectInputCreate32A(HINSTANCE32 hinst, DWORD dwVersion, LPDIRECTINPUT32A *ppDI, LPUNKNOWN punkOuter) {
69         TRACE(dinput, "(0x%08lx,%04lx,%p,%p)\n",
70                 (DWORD)hinst,dwVersion,ppDI,punkOuter
71         );
72         (*ppDI) = (LPDIRECTINPUT32A)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInput32A));
73         (*ppDI)->ref = 1;
74         (*ppDI)->lpvtbl = &ddiavt;
75         return 0;
76 }
77 /******************************************************************************
78  *      IDirectInputA_EnumDevices
79  */
80 static HRESULT WINAPI IDirectInputA_EnumDevices(
81         LPDIRECTINPUT32A this, DWORD dwDevType, LPDIENUMDEVICESCALLBACK32A lpCallback,
82         LPVOID pvRef, DWORD dwFlags
83 ) {
84   DIDEVICEINSTANCE32A devInstance;
85   int ret;
86
87   TRACE(dinput, "(this=%p,0x%04lx,%p,%p,%04lx)\n", this, dwDevType, lpCallback, pvRef, dwFlags);
88
89   devInstance.dwSize = sizeof(DIDEVICEINSTANCE32A);
90   
91   if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
92   /* Return keyboard */
93     devInstance.guidInstance = GUID_SysKeyboard;         /* DInput's GUID */
94     devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
95     devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
96   strcpy(devInstance.tszInstanceName, "Keyboard");
97   strcpy(devInstance.tszProductName, "Wine Keyboard");
98   
99   ret = lpCallback(&devInstance, pvRef);
100     TRACE(dinput, "Keyboard registered\n");
101   
102     if (ret == DIENUM_STOP)
103     return 0;
104   }
105   
106   if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
107   /* Return mouse */
108     devInstance.guidInstance = GUID_SysMouse;         /* DInput's GUID */
109     devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
110     devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
111   strcpy(devInstance.tszInstanceName, "Mouse");
112   strcpy(devInstance.tszProductName, "Wine Mouse");
113   
114   ret = lpCallback(&devInstance, pvRef);
115     TRACE(dinput, "Mouse registered\n");
116   }
117
118   /* Should also do joystick enumerations.... */
119   
120         return 0;
121 }
122
123 static ULONG WINAPI IDirectInputA_AddRef(LPDIRECTINPUT32A this) {
124         return ++(this->ref);
125 }
126
127 static ULONG WINAPI IDirectInputA_Release(LPDIRECTINPUT32A this) {
128         if (!(--this->ref)) {
129                 HeapFree(GetProcessHeap(),0,this);
130                 return 0;
131         }
132         return this->ref;
133 }
134
135 static HRESULT WINAPI IDirectInputA_CreateDevice(
136         LPDIRECTINPUT32A this,REFGUID rguid,LPDIRECTINPUTDEVICE32A* pdev,
137         LPUNKNOWN punk
138 ) {
139         char    xbuf[50];
140         
141         WINE_StringFromCLSID(rguid,xbuf);
142         FIXME(dinput,"(this=%p,%s,%p,%p): stub\n",this,xbuf,pdev,punk);
143         if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) ||          /* Generic Keyboard */
144             (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
145                 *pdev = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboard32A));
146                 (*pdev)->ref = 1;
147                 (*pdev)->lpvtbl = &SysKeyboardAvt;
148                 memcpy(&((*pdev)->guid),rguid,sizeof(*rguid));
149                 memset(((LPSYSKEYBOARD32A)(*pdev))->keystate,0,256);
150                 return 0;
151         }
152         if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) ||             /* Generic Mouse */
153             (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Mouse */
154                 *pdev = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouse32A));
155                 (*pdev)->ref = 1;
156                 (*pdev)->lpvtbl = &SysMouseAvt;
157                 memcpy(&((*pdev)->guid),rguid,sizeof(*rguid));
158                 return 0;
159         }
160         return E_FAIL;
161 }
162
163 static HRESULT WINAPI IDirectInputA_QueryInterface(
164         LPDIRECTINPUT32A this,REFIID riid,LPVOID *ppobj
165 ) {
166         char    xbuf[50];
167
168         WINE_StringFromCLSID(riid,xbuf);
169         TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ppobj);
170         if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
171                 this->lpvtbl->fnAddRef(this);
172                 *ppobj = this;
173                 return 0;
174         }
175         if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
176                 this->lpvtbl->fnAddRef(this);
177                 *ppobj = this;
178                 return 0;
179         }
180         return E_FAIL;
181 }
182
183 static HRESULT WINAPI IDirectInputA_Initialize(
184         LPDIRECTINPUT32A this,HINSTANCE32 hinst,DWORD x
185 ) {
186         return DIERR_ALREADYINITIALIZED;
187 }
188
189 static IDirectInputA_VTable ddiavt= {
190         IDirectInputA_QueryInterface,
191         IDirectInputA_AddRef,
192         IDirectInputA_Release,
193         IDirectInputA_CreateDevice,
194         IDirectInputA_EnumDevices,
195         (void*)6,
196         (void*)7,
197         IDirectInputA_Initialize
198 };
199
200 /******************************************************************************
201  *      IDirectInputDeviceA
202  */
203 static HRESULT WINAPI IDirectInputDeviceA_SetDataFormat(
204         LPDIRECTINPUTDEVICE32A this,LPCDIDATAFORMAT df
205 ) {
206         /*
207         int i;
208         TRACE(dinput,"(this=%p,%p)\n",this,df);
209
210         TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
211         TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
212         TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
213         TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
214         TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
215
216         for (i=0;i<df->dwNumObjs;i++) {
217                 char    xbuf[50];
218
219                 if (df->rgodf[i].pguid)
220                         WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
221                 else
222                         strcpy(xbuf,"<no guid>");
223                 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
224                 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
225                 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
226                 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
227         }
228         */
229         return 0;
230 }
231
232 static HRESULT WINAPI IDirectInputDeviceA_SetCooperativeLevel(
233         LPDIRECTINPUTDEVICE32A this,HWND32 hwnd,DWORD dwflags
234 ) {
235         FIXME(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",this,(DWORD)hwnd,dwflags);
236         return 0;
237 }
238
239 static HRESULT WINAPI IDirectInputDeviceA_SetProperty(
240         LPDIRECTINPUTDEVICE32A this,REFGUID rguid,LPCDIPROPHEADER ph
241 ) {
242         char    xbuf[50];
243
244         if (HIWORD(rguid))
245                 WINE_StringFromCLSID(rguid,xbuf);
246         else
247                 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
248         TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ph);
249         if (!HIWORD(rguid)) {
250                 switch ((DWORD)rguid) {
251                 case DIPROP_BUFFERSIZE: {
252                         LPCDIPROPDWORD  pd = (LPCDIPROPDWORD)ph;
253
254                         TRACE(dinput,"buffersize = %ld\n",pd->dwData);
255                         break;
256                 }
257                 default:
258                         WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
259                         break;
260                 }
261         }
262         return 0;
263 }
264
265 static HRESULT WINAPI IDirectInputDeviceA_SetEventNotification(
266         LPDIRECTINPUTDEVICE32A this,HANDLE32 hnd
267 ) {
268         FIXME(dinput,"(this=%p,0x%08lx): stub\n",this,(DWORD)hnd);
269         return 0;
270 }
271
272 static HRESULT WINAPI IDirectInputDeviceA_GetDeviceData(
273         LPDIRECTINPUTDEVICE32A this,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
274         LPDWORD entries,DWORD flags
275 ) {
276   TRACE(dinput,"IDirectInputDeviceA(%p)->GetDeviceData(%ld,%p,%p(0x%08lx),0x%08lx)\n",
277         this,dodsize,dod,entries,*entries,flags);
278         return 0;
279 }
280
281
282 static HRESULT WINAPI IDirectInputDeviceA_Acquire(LPDIRECTINPUTDEVICE32A this) {
283         TRACE(dinput,"(this=%p): stub\n",this);
284         return 0;
285 }
286
287 static HRESULT WINAPI IDirectInputDeviceA_Unacquire(LPDIRECTINPUTDEVICE32A this) {
288         TRACE(dinput,"(this=%p): stub\n",this);
289         return 0;
290 }
291
292 static ULONG WINAPI IDirectInputDeviceA_Release(LPDIRECTINPUTDEVICE32A this) {
293         this->ref--;
294         if (this->ref)
295                 return this->ref;
296         HeapFree(GetProcessHeap(),0,this);
297         return 0;
298 }
299
300 static HRESULT WINAPI SysKeyboardA_SetProperty(
301         LPDIRECTINPUTDEVICE32A this,REFGUID rguid,LPCDIPROPHEADER ph
302 ) {
303         char                    xbuf[50];
304
305         if (HIWORD(rguid))
306                 WINE_StringFromCLSID(rguid,xbuf);
307         else
308                 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
309         TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ph);
310         TRACE(dinput,"(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
311             ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
312         if (!HIWORD(rguid)) {
313                 switch ((DWORD)rguid) {
314                 case DIPROP_BUFFERSIZE: {
315                         LPCDIPROPDWORD  pd = (LPCDIPROPDWORD)ph;
316
317                         TRACE(dinput,"(buffersize=%ld)\n",pd->dwData);
318                         break;
319                 }
320                 default:
321                         WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
322                         break;
323                 }
324         }
325         return 0;
326 }
327
328 static HRESULT WINAPI SysKeyboardA_GetDeviceState(
329         LPDIRECTINPUTDEVICE32A this,DWORD len,LPVOID ptr
330 ) {
331         if (len==256) {
332                 int keyc,vkey;
333
334                 memset(ptr,0,256);
335                 for (keyc=min_keycode;keyc<max_keycode;keyc++)
336                 {
337                     /* X keycode to virtual key */
338                     vkey = keyc2vkey[keyc] & 0xFF;
339                     /* The windows scancode is keyc-min_keycode */
340                     if (InputKeyStateTable[vkey]&0x80) {
341                         ((LPBYTE)ptr)[keyc-min_keycode]=0x80;
342                         ((LPBYTE)ptr)[(keyc-min_keycode)|0x80]=0x80;
343                     }
344                 }
345                 return 0;
346         }
347         WARN(dinput,"whoops, SysKeyboardA_GetDeviceState got len %ld?\n",len);
348         return 0;
349 }
350
351 static HRESULT WINAPI SysKeyboardA_GetDeviceData(
352         LPDIRECTINPUTDEVICE32A this,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
353         LPDWORD entries,DWORD flags
354 ) {
355         int                     keyc,n,vkey,xentries;
356         LPSYSKEYBOARD32A        kthis = (LPSYSKEYBOARD32A)this;
357
358         TRACE(dinput,"(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
359                 this,dodsize,dod,entries,entries?*entries:0,flags);
360         EVENT_WaitNetEvent(FALSE,TRUE);
361         if (entries)
362                 xentries = *entries; 
363         else
364                 xentries = 1;
365
366         n = 0;
367
368         for (keyc=min_keycode;(keyc<max_keycode) && (n<*entries);keyc++)
369         {
370                     /* X keycode to virtual key */
371                     vkey = keyc2vkey[keyc] & 0xFF;
372                     if (kthis->keystate[vkey] == (InputKeyStateTable[vkey]&0x80))
373                         continue;
374                 if (dod) {
375                         /* add an entry */
376                         dod[n].dwOfs            = keyc-min_keycode; /* scancode */
377                         dod[n].dwData           = InputKeyStateTable[vkey]&0x80;
378                         dod[n].dwTimeStamp      = 0; /* umm */
379                         dod[n].dwSequence       = 0; /* umm */
380                         n++;
381                 }
382                 if (!(flags & DIGDD_PEEK))
383                         kthis->keystate[vkey] = InputKeyStateTable[vkey]&0x80;
384                     
385         }
386         
387         if (n) fprintf(stderr,"%d entries\n",n);
388         *entries = n;
389         return 0;
390 }
391
392 static HRESULT WINAPI SysKeyboardA_Acquire(LPDIRECTINPUTDEVICE32A this) {
393         TRACE(dinput,"(this=%p): stub\n",this);
394         return 0;
395 }
396
397 static HRESULT WINAPI SysKeyboardA_Unacquire(LPDIRECTINPUTDEVICE32A this) {
398         TRACE(dinput,"(this=%p): stub\n",this);
399         return 0;
400 }
401
402 static HRESULT WINAPI IDirectInputDeviceA_QueryInterface(
403         LPDIRECTINPUTDEVICE32A this,REFIID riid,LPVOID *ppobj
404 ) {
405         char    xbuf[50];
406
407         WINE_StringFromCLSID(riid,xbuf);
408         TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ppobj);
409         if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
410                 this->lpvtbl->fnAddRef(this);
411                 *ppobj = this;
412                 return 0;
413         }
414         if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
415                 this->lpvtbl->fnAddRef(this);
416                 *ppobj = this;
417                 return 0;
418         }
419         if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
420                 this->lpvtbl->fnAddRef(this);
421                 *ppobj = this;
422                 return 0;
423         }
424         return E_FAIL;
425 }
426
427 static ULONG WINAPI IDirectInputDeviceA_AddRef(
428         LPDIRECTINPUTDEVICE32A this)
429 {
430         return ++this->ref;
431 }
432
433 static HRESULT WINAPI IDirectInputDeviceA_GetCapabilities(
434         LPDIRECTINPUTDEVICE32A this,
435         LPDIDEVCAPS lpDIDevCaps)
436 {
437         FIXME(dinput, "stub!\n");
438         return DI_OK;
439 }
440
441 static HRESULT WINAPI IDirectInputDeviceA_EnumObjects(
442         LPDIRECTINPUTDEVICE32A this,
443         LPDIENUMDEVICEOBJECTSCALLBACK32A lpCallback,
444         LPVOID lpvRef,
445         DWORD dwFlags)
446 {
447         FIXME(dinput, "stub!\n");
448         if (lpCallback)
449                 lpCallback(NULL, lpvRef);
450         return DI_OK;
451 }
452         
453 static HRESULT WINAPI IDirectInputDeviceA_GetProperty(
454         LPDIRECTINPUTDEVICE32A this,
455         REFGUID rguid,
456         LPDIPROPHEADER pdiph)
457 {
458         FIXME(dinput, "stub!\n");
459         return DI_OK;
460 }
461
462 static HRESULT WINAPI IDirectInputDeviceA_GetObjectInfo(
463         LPDIRECTINPUTDEVICE32A this,
464         LPDIDEVICEOBJECTINSTANCE32A pdidoi,
465         DWORD dwObj,
466         DWORD dwHow)
467 {
468         FIXME(dinput, "stub!\n");
469         return DI_OK;
470 }
471         
472 static HRESULT WINAPI IDirectInputDeviceA_GetDeviceInfo(
473         LPDIRECTINPUTDEVICE32A this,
474         LPDIDEVICEINSTANCE32A pdidi)
475 {
476         FIXME(dinput, "stub!\n");
477         return DI_OK;
478 }
479         
480 static HRESULT WINAPI IDirectInputDeviceA_RunControlPanel(
481         LPDIRECTINPUTDEVICE32A this,
482         HWND32 hwndOwner,
483         DWORD dwFlags)
484 {
485         FIXME(dinput, "stub!\n");
486         return DI_OK;
487 }
488         
489 static HRESULT WINAPI IDirectInputDeviceA_Initialize(
490         LPDIRECTINPUTDEVICE32A this,
491         HINSTANCE32 hinst,
492         DWORD dwVersion,
493         REFGUID rguid)
494 {
495         FIXME(dinput, "stub!\n");
496         return DI_OK;
497 }
498         
499 /******************************************************************************
500  *      IDirectInputDevice2A
501  */
502
503 static HRESULT WINAPI IDirectInputDevice2A_CreateEffect(
504         LPDIRECTINPUTDEVICE32A this,
505         REFGUID rguid,
506         LPCDIEFFECT lpeff,
507         LPDIRECTINPUTEFFECT *ppdef,
508         LPUNKNOWN pUnkOuter)
509 {
510         FIXME(dinput, "stub!\n");
511         return DI_OK;
512 }
513
514 static HRESULT WINAPI IDirectInputDevice2A_EnumEffects(
515         LPDIRECTINPUTDEVICE32A this,
516         LPDIENUMEFFECTSCALLBACKA lpCallback,
517         LPVOID lpvRef,
518         DWORD dwFlags)
519 {
520         FIXME(dinput, "stub!\n");
521         if (lpCallback)
522                 lpCallback(NULL, lpvRef);
523         return DI_OK;
524 }
525
526 static HRESULT WINAPI IDirectInputDevice2A_GetEffectInfo(
527         LPDIRECTINPUTDEVICE32A this,
528         LPDIEFFECTINFOA lpdei,
529         REFGUID rguid)
530 {
531         FIXME(dinput, "stub!\n");
532         return DI_OK;
533 }
534
535 static HRESULT WINAPI IDirectInputDevice2A_GetForceFeedbackState(
536         LPDIRECTINPUTDEVICE32A this,
537         LPDWORD pdwOut)
538 {
539         FIXME(dinput, "stub!\n");
540         return DI_OK;
541 }
542
543 static HRESULT WINAPI IDirectInputDevice2A_SendForceFeedbackCommand(
544         LPDIRECTINPUTDEVICE32A this,
545         DWORD dwFlags)
546 {
547         FIXME(dinput, "stub!\n");
548         return DI_OK;
549 }
550
551 static HRESULT WINAPI IDirectInputDevice2A_EnumCreatedEffectObjects(
552         LPDIRECTINPUTDEVICE32A this,
553         LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
554         LPVOID lpvRef,
555         DWORD dwFlags)
556 {
557         FIXME(dinput, "stub!\n");
558         if (lpCallback)
559                 lpCallback(NULL, lpvRef);
560         return DI_OK;
561 }
562
563 static HRESULT WINAPI IDirectInputDevice2A_Escape(
564         LPDIRECTINPUTDEVICE32A this,
565         LPDIEFFESCAPE lpDIEEsc)
566 {
567         FIXME(dinput, "stub!\n");
568         return DI_OK;
569 }
570
571 static HRESULT WINAPI IDirectInputDevice2A_Poll(
572         LPDIRECTINPUTDEVICE32A this)
573 {
574         FIXME(dinput, "stub!\n");
575         return DI_OK;
576 }
577
578 static HRESULT WINAPI IDirectInputDevice2A_SendDeviceData(
579         LPDIRECTINPUTDEVICE32A this,
580         DWORD cbObjectData,
581         LPDIDEVICEOBJECTDATA rgdod,
582         LPDWORD pdwInOut,
583         DWORD dwFlags)
584 {
585         FIXME(dinput, "stub!\n");
586         return DI_OK;
587 }
588
589 /******************************************************************************
590  *      SysMouseA (DInput Mouse support)
591  */
592
593 /******************************************************************************
594   *     SetDataFormat : the application can choose the format of the data
595   *   the device driver sends back with GetDeviceState.
596   *
597   *   For the moment, only the "standard" configuration (c_dfDIMouse) is supported
598   *   in absolute and relative mode.
599   */
600 static HRESULT WINAPI SysMouseA_SetDataFormat(
601         LPDIRECTINPUTDEVICE32A this,LPCDIDATAFORMAT df
602 ) {
603   int i;
604   LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
605   
606   TRACE(dinput,"(this=%p,%p)\n",this,df);
607
608   TRACE(dinput,"(df.dwSize=%ld)\n",df->dwSize);
609   TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
610   TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
611   TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
612   TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
613
614   for (i=0;i<df->dwNumObjs;i++) {
615     char        xbuf[50];
616     
617     if (df->rgodf[i].pguid)
618       WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
619     else
620       strcpy(xbuf,"<no guid>");
621     TRACE(dinput,"df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
622     TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
623     TRACE(dinput,"dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
624     TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
625   }
626
627   /* Check size of data format to prevent crashes if the applications
628      sends a smaller buffer */
629   if (df->dwDataSize != sizeof(struct DIMOUSESTATE)) {
630     FIXME(dinput, "non-standard mouse configuration not supported yet.");
631     return DIERR_INVALIDPARAM;
632   }
633   
634   /* For the moment, ignore these fields and return always as if
635      c_dfDIMouse was passed as format... */
636   if (df->dwFlags == DIDF_ABSAXIS)
637     mthis->absolute = 1;
638   else {
639     DWORD rx, ry;
640     
641     /* We need to get the initial "previous" position to be able
642        to return deltas */
643     mthis->absolute = 0;
644   
645     /* Get the mouse position */
646     EVENT_QueryPointer(&rx, &ry, NULL);
647
648     /* Fill the initial mouse state structure */
649     mthis->prevX = rx;
650     mthis->prevY = ry;
651   }
652   
653   return 0;
654 }
655
656 /******************************************************************************
657   *     GetDeviceState : returns the "state" of the mouse.
658   *
659   *   For the moment, only the "standard" return structure (DIMOUSESTATE) is
660   *   supported.
661   */
662 static HRESULT WINAPI SysMouseA_GetDeviceState(
663         LPDIRECTINPUTDEVICE32A this,DWORD len,LPVOID ptr
664 ) {
665   DWORD rx, ry, state;
666   struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
667   LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
668   
669   TRACE(dinput,"(this=%p,0x%08lx,%p): \n",this,len,ptr);
670   
671   /* Check if the buffer is big enough */
672   if (len < sizeof(struct DIMOUSESTATE)) {
673     FIXME(dinput, "unsupported state structure.");
674     return DIERR_INVALIDPARAM;
675   }
676   
677   /* Get the mouse position */
678   EVENT_QueryPointer(&rx, &ry, &state);
679   TRACE(dinput,"(X:%d - Y:%d)\n", rx, ry);
680
681   /* Fill the mouse state structure */
682   if (mthis->absolute) {
683     mstate->lX = rx;
684     mstate->lY = ry;
685   } else {
686     mstate->lX = rx - mthis->prevX;
687     mstate->lY = ry - mthis->prevY;
688     /* Fill the previous positions */
689     mthis->prevX = rx;
690     mthis->prevY = ry;
691   }
692   mstate->lZ = 0;
693   mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00);
694   mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00);
695   mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00);
696   mstate->rgbButtons[3] = 0x00;
697   
698   return 0;
699 }
700
701
702
703 static IDirectInputDeviceA_VTable SysKeyboardAvt={
704         IDirectInputDeviceA_QueryInterface,
705         IDirectInputDeviceA_AddRef,
706         IDirectInputDeviceA_Release,
707         IDirectInputDeviceA_GetCapabilities,
708         IDirectInputDeviceA_EnumObjects,
709         IDirectInputDeviceA_GetProperty,
710         SysKeyboardA_SetProperty,
711         SysKeyboardA_Acquire,
712         SysKeyboardA_Unacquire,
713         SysKeyboardA_GetDeviceState,
714         SysKeyboardA_GetDeviceData,
715         IDirectInputDeviceA_SetDataFormat,
716         IDirectInputDeviceA_SetEventNotification,
717         IDirectInputDeviceA_SetCooperativeLevel,
718         IDirectInputDeviceA_GetObjectInfo,
719         IDirectInputDeviceA_GetDeviceInfo,
720         IDirectInputDeviceA_RunControlPanel,
721         IDirectInputDeviceA_Initialize,
722         IDirectInputDevice2A_CreateEffect,
723         IDirectInputDevice2A_EnumEffects,
724         IDirectInputDevice2A_GetEffectInfo,
725         IDirectInputDevice2A_GetForceFeedbackState,
726         IDirectInputDevice2A_SendForceFeedbackCommand,
727         IDirectInputDevice2A_EnumCreatedEffectObjects,
728         IDirectInputDevice2A_Escape,
729         IDirectInputDevice2A_Poll,
730         IDirectInputDevice2A_SendDeviceData,
731 };
732
733 static IDirectInputDeviceA_VTable SysMouseAvt={
734         IDirectInputDeviceA_QueryInterface,
735         IDirectInputDeviceA_AddRef,
736         IDirectInputDeviceA_Release,
737         IDirectInputDeviceA_GetCapabilities,
738         IDirectInputDeviceA_EnumObjects,
739         IDirectInputDeviceA_GetProperty,
740         IDirectInputDeviceA_SetProperty,
741         IDirectInputDeviceA_Acquire,
742         IDirectInputDeviceA_Unacquire,
743         SysMouseA_GetDeviceState,
744         IDirectInputDeviceA_GetDeviceData,
745         SysMouseA_SetDataFormat,
746         IDirectInputDeviceA_SetEventNotification,
747         IDirectInputDeviceA_SetCooperativeLevel,
748         IDirectInputDeviceA_GetObjectInfo,
749         IDirectInputDeviceA_GetDeviceInfo,
750         IDirectInputDeviceA_RunControlPanel,
751         IDirectInputDeviceA_Initialize,
752         IDirectInputDevice2A_CreateEffect,
753         IDirectInputDevice2A_EnumEffects,
754         IDirectInputDevice2A_GetEffectInfo,
755         IDirectInputDevice2A_GetForceFeedbackState,
756         IDirectInputDevice2A_SendForceFeedbackCommand,
757         IDirectInputDevice2A_EnumCreatedEffectObjects,
758         IDirectInputDevice2A_Escape,
759         IDirectInputDevice2A_Poll,
760         IDirectInputDevice2A_SendDeviceData,
761 };