Implementation of the pushed close button.
[wine] / windows / dinput.c
1 /*              DirectInput
2  *
3  * Copyright 1998 Marcus Meissner
4  * Copyright 1998,1999 Lionel Ulmer
5  *
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 "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"
37
38 #include "mouse.h"
39 #include "ts_xlib.h"
40 #include "sysmetrics.h"
41 #include "x11drv.h"
42
43 extern BYTE InputKeyStateTable[256];
44 extern int min_keycode, max_keycode;
45 extern WORD keyc2vkey[256];
46
47 static IDirectInputA_VTable ddiavt;
48 static IDirectInputDeviceA_VTable SysKeyboardAvt;
49 static IDirectInputDeviceA_VTable SysMouseAvt;
50
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}
60 };
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}
66 };
67
68 /* This is ugly and not thread safe :/ */
69 static LPDIRECTINPUTDEVICE32A current_lock = NULL;
70
71 /******************************************************************************
72  *      Various debugging tools
73  */
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)
85   };
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");
90 }
91
92
93 /******************************************************************************
94  *      DirectInputCreate32A
95  */
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
99         );
100         (*ppDI) = (LPDIRECTINPUT32A)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInput32A));
101         (*ppDI)->ref = 1;
102         (*ppDI)->lpvtbl = &ddiavt;
103         return 0;
104 }
105 /******************************************************************************
106  *      IDirectInputA_EnumDevices
107  */
108 static HRESULT WINAPI IDirectInputA_EnumDevices(
109         LPDIRECTINPUT32A this, DWORD dwDevType, LPDIENUMDEVICESCALLBACK32A lpCallback,
110         LPVOID pvRef, DWORD dwFlags
111 ) {
112   DIDEVICEINSTANCE32A devInstance;
113   int ret;
114
115   TRACE(dinput, "(this=%p,0x%04lx,%p,%p,%04lx)\n", this, dwDevType, lpCallback, pvRef, dwFlags);
116
117   devInstance.dwSize = sizeof(DIDEVICEINSTANCE32A);
118   
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");
126   
127   ret = lpCallback(&devInstance, pvRef);
128     TRACE(dinput, "Keyboard registered\n");
129   
130     if (ret == DIENUM_STOP)
131     return 0;
132   }
133   
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");
141   
142   ret = lpCallback(&devInstance, pvRef);
143     TRACE(dinput, "Mouse registered\n");
144   }
145
146   /* Should also do joystick enumerations.... */
147   
148         return 0;
149 }
150
151 static ULONG WINAPI IDirectInputA_AddRef(LPDIRECTINPUT32A this) {
152         return ++(this->ref);
153 }
154
155 static ULONG WINAPI IDirectInputA_Release(LPDIRECTINPUT32A this) {
156         if (!(--this->ref)) {
157                 HeapFree(GetProcessHeap(),0,this);
158                 return 0;
159         }
160         return this->ref;
161 }
162
163 static HRESULT WINAPI IDirectInputA_CreateDevice(
164         LPDIRECTINPUT32A this,REFGUID rguid,LPDIRECTINPUTDEVICE32A* pdev,
165         LPUNKNOWN punk
166 ) {
167         char    xbuf[50];
168         
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;
179         }
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;
187         }
188         return E_FAIL;
189 }
190
191 static HRESULT WINAPI IDirectInputA_QueryInterface(
192         LPDIRECTINPUT32A this,REFIID riid,LPVOID *ppobj
193 ) {
194         char    xbuf[50];
195
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;
202         }
203         if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
204                 this->lpvtbl->fnAddRef(this);
205                 *ppobj = this;
206                 return 0;
207         }
208         return E_FAIL;
209 }
210
211 static HRESULT WINAPI IDirectInputA_Initialize(
212         LPDIRECTINPUT32A this,HINSTANCE32 hinst,DWORD x
213 ) {
214         return DIERR_ALREADYINITIALIZED;
215 }
216
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
226 };
227
228 /******************************************************************************
229  *      IDirectInputDeviceA
230  */
231 static HRESULT WINAPI IDirectInputDeviceA_SetDataFormat(
232         LPDIRECTINPUTDEVICE32A this,LPCDIDATAFORMAT df
233 ) {
234         /*
235         int i;
236         TRACE(dinput,"(this=%p,%p)\n",this,df);
237
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);
243
244         for (i=0;i<df->dwNumObjs;i++) {
245                 char    xbuf[50];
246
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);
255         }
256         */
257         return 0;
258 }
259
260 static HRESULT WINAPI IDirectInputDeviceA_SetCooperativeLevel(
261         LPDIRECTINPUTDEVICE32A this,HWND32 hwnd,DWORD dwflags
262 ) {
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;
267 }
268
269 static HRESULT WINAPI IDirectInputDeviceA_SetEventNotification(
270         LPDIRECTINPUTDEVICE32A this,HANDLE32 hnd
271 ) {
272         FIXME(dinput,"(this=%p,0x%08lx): stub\n",this,(DWORD)hnd);
273         return 0;
274 }
275
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;
282 }
283
284 static HRESULT WINAPI SysKeyboardA_SetProperty(
285         LPDIRECTINPUTDEVICE32A this,REFGUID rguid,LPCDIPROPHEADER ph
286 ) {
287         char                    xbuf[50];
288
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;
300
301                         TRACE(dinput,"(buffersize=%ld)\n",pd->dwData);
302                         break;
303                 }
304                 default:
305                         WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
306                         break;
307                 }
308         }
309         return 0;
310 }
311
312 static HRESULT WINAPI SysKeyboardA_GetDeviceState(
313         LPDIRECTINPUTDEVICE32A this,DWORD len,LPVOID ptr
314 ) {
315         if (len==256) {
316                 int keyc,vkey;
317
318                 memset(ptr,0,256);
319                 for (keyc=min_keycode;keyc<max_keycode;keyc++)
320                 {
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;
327                     }
328                 }
329                 return 0;
330         }
331         WARN(dinput,"whoops, SysKeyboardA_GetDeviceState got len %ld?\n",len);
332         return 0;
333 }
334
335 static HRESULT WINAPI SysKeyboardA_GetDeviceData(
336         LPDIRECTINPUTDEVICE32A this,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
337         LPDWORD entries,DWORD flags
338 ) {
339         int                     keyc,n,vkey,xentries;
340         LPSYSKEYBOARD32A        kthis = (LPSYSKEYBOARD32A)this;
341
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;
349
350         n = 0;
351
352         for (keyc=min_keycode;(keyc<max_keycode) && (n<*entries);keyc++)
353         {
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++;
365                 }
366                 if (!(flags & DIGDD_PEEK))
367                         kthis->keystate[vkey] = InputKeyStateTable[vkey]&0x80;
368                     
369         }
370         
371         if (n) fprintf(stderr,"%d entries\n",n);
372         *entries = n;
373         return 0;
374 }
375
376 static HRESULT WINAPI SysKeyboardA_Acquire(LPDIRECTINPUTDEVICE32A this) {
377         TRACE(dinput,"(this=%p): stub\n",this);
378         return 0;
379 }
380
381 static HRESULT WINAPI SysKeyboardA_Unacquire(LPDIRECTINPUTDEVICE32A this) {
382         TRACE(dinput,"(this=%p): stub\n",this);
383         return 0;
384 }
385
386 static HRESULT WINAPI IDirectInputDeviceA_QueryInterface(
387         LPDIRECTINPUTDEVICE32A this,REFIID riid,LPVOID *ppobj
388 ) {
389         char    xbuf[50];
390
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;
397         }
398         if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
399                 this->lpvtbl->fnAddRef(this);
400                 *ppobj = this;
401                 return 0;
402         }
403         if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
404                 this->lpvtbl->fnAddRef(this);
405                 *ppobj = this;
406                 return 0;
407         }
408         return E_FAIL;
409 }
410
411 static ULONG WINAPI IDirectInputDeviceA_AddRef(
412         LPDIRECTINPUTDEVICE32A this)
413 {
414         return ++this->ref;
415 }
416
417 static HRESULT WINAPI IDirectInputDeviceA_GetCapabilities(
418         LPDIRECTINPUTDEVICE32A this,
419         LPDIDEVCAPS lpDIDevCaps)
420 {
421         FIXME(dinput, "stub!\n");
422         return DI_OK;
423 }
424
425 static HRESULT WINAPI IDirectInputDeviceA_EnumObjects(
426         LPDIRECTINPUTDEVICE32A this,
427         LPDIENUMDEVICEOBJECTSCALLBACK32A lpCallback,
428         LPVOID lpvRef,
429         DWORD dwFlags)
430 {
431         FIXME(dinput, "stub!\n");
432 #if 0
433         if (lpCallback)
434                 lpCallback(NULL, lpvRef);
435 #endif
436         return DI_OK;
437 }
438         
439 static HRESULT WINAPI IDirectInputDeviceA_GetProperty(
440         LPDIRECTINPUTDEVICE32A this,
441         REFGUID rguid,
442         LPDIPROPHEADER pdiph)
443 {
444         FIXME(dinput, "stub!\n");
445         return DI_OK;
446 }
447
448 static HRESULT WINAPI IDirectInputDeviceA_GetObjectInfo(
449         LPDIRECTINPUTDEVICE32A this,
450         LPDIDEVICEOBJECTINSTANCE32A pdidoi,
451         DWORD dwObj,
452         DWORD dwHow)
453 {
454         FIXME(dinput, "stub!\n");
455         return DI_OK;
456 }
457         
458 static HRESULT WINAPI IDirectInputDeviceA_GetDeviceInfo(
459         LPDIRECTINPUTDEVICE32A this,
460         LPDIDEVICEINSTANCE32A pdidi)
461 {
462         FIXME(dinput, "stub!\n");
463         return DI_OK;
464 }
465         
466 static HRESULT WINAPI IDirectInputDeviceA_RunControlPanel(
467         LPDIRECTINPUTDEVICE32A this,
468         HWND32 hwndOwner,
469         DWORD dwFlags)
470 {
471         FIXME(dinput, "stub!\n");
472         return DI_OK;
473 }
474         
475 static HRESULT WINAPI IDirectInputDeviceA_Initialize(
476         LPDIRECTINPUTDEVICE32A this,
477         HINSTANCE32 hinst,
478         DWORD dwVersion,
479         REFGUID rguid)
480 {
481         FIXME(dinput, "stub!\n");
482         return DI_OK;
483 }
484         
485 /******************************************************************************
486  *      IDirectInputDevice2A
487  */
488
489 static HRESULT WINAPI IDirectInputDevice2A_CreateEffect(
490         LPDIRECTINPUTDEVICE32A this,
491         REFGUID rguid,
492         LPCDIEFFECT lpeff,
493         LPDIRECTINPUTEFFECT *ppdef,
494         LPUNKNOWN pUnkOuter)
495 {
496         FIXME(dinput, "stub!\n");
497         return DI_OK;
498 }
499
500 static HRESULT WINAPI IDirectInputDevice2A_EnumEffects(
501         LPDIRECTINPUTDEVICE32A this,
502         LPDIENUMEFFECTSCALLBACKA lpCallback,
503         LPVOID lpvRef,
504         DWORD dwFlags)
505 {
506         FIXME(dinput, "stub!\n");
507         if (lpCallback)
508                 lpCallback(NULL, lpvRef);
509         return DI_OK;
510 }
511
512 static HRESULT WINAPI IDirectInputDevice2A_GetEffectInfo(
513         LPDIRECTINPUTDEVICE32A this,
514         LPDIEFFECTINFOA lpdei,
515         REFGUID rguid)
516 {
517         FIXME(dinput, "stub!\n");
518         return DI_OK;
519 }
520
521 static HRESULT WINAPI IDirectInputDevice2A_GetForceFeedbackState(
522         LPDIRECTINPUTDEVICE32A this,
523         LPDWORD pdwOut)
524 {
525         FIXME(dinput, "stub!\n");
526         return DI_OK;
527 }
528
529 static HRESULT WINAPI IDirectInputDevice2A_SendForceFeedbackCommand(
530         LPDIRECTINPUTDEVICE32A this,
531         DWORD dwFlags)
532 {
533         FIXME(dinput, "stub!\n");
534         return DI_OK;
535 }
536
537 static HRESULT WINAPI IDirectInputDevice2A_EnumCreatedEffectObjects(
538         LPDIRECTINPUTDEVICE32A this,
539         LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
540         LPVOID lpvRef,
541         DWORD dwFlags)
542 {
543         FIXME(dinput, "stub!\n");
544         if (lpCallback)
545                 lpCallback(NULL, lpvRef);
546         return DI_OK;
547 }
548
549 static HRESULT WINAPI IDirectInputDevice2A_Escape(
550         LPDIRECTINPUTDEVICE32A this,
551         LPDIEFFESCAPE lpDIEEsc)
552 {
553         FIXME(dinput, "stub!\n");
554         return DI_OK;
555 }
556
557 static HRESULT WINAPI IDirectInputDevice2A_Poll(
558         LPDIRECTINPUTDEVICE32A this)
559 {
560         FIXME(dinput, "stub!\n");
561         return DI_OK;
562 }
563
564 static HRESULT WINAPI IDirectInputDevice2A_SendDeviceData(
565         LPDIRECTINPUTDEVICE32A this,
566         DWORD cbObjectData,
567         LPDIDEVICEOBJECTDATA rgdod,
568         LPDWORD pdwInOut,
569         DWORD dwFlags)
570 {
571         FIXME(dinput, "stub!\n");
572         return DI_OK;
573 }
574
575 /******************************************************************************
576  *      SysMouseA (DInput Mouse support)
577  */
578
579 /******************************************************************************
580   *     Release : release the mouse buffer.
581   */
582 static ULONG WINAPI SysMouseA_Release(LPDIRECTINPUTDEVICE32A this) {
583         LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
584
585         this->ref--;
586         if (this->ref)
587                 return this->ref;
588
589         /* Free the data queue */
590         if (mthis->data_queue != NULL)
591           HeapFree(GetProcessHeap(),0,mthis->data_queue);
592
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);
597         
598         HeapFree(GetProcessHeap(),0,this);
599         return 0;
600 }
601
602
603 /******************************************************************************
604   *     SetCooperativeLevel : store the window in which we will do our
605   *   grabbing.
606   */
607 static HRESULT WINAPI SysMouseA_SetCooperativeLevel(
608         LPDIRECTINPUTDEVICE32A this,HWND32 hwnd,DWORD dwflags
609 ) {
610   LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
611
612   TRACE(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",this,(DWORD)hwnd,dwflags);
613
614   if (TRACE_ON(dinput))
615     _dump_cooperativelevel(dwflags);
616
617   /* Store the window which asks for the mouse */
618   mthis->win = hwnd;
619   
620   return 0;
621 }
622
623
624 /******************************************************************************
625   *     SetDataFormat : the application can choose the format of the data
626   *   the device driver sends back with GetDeviceState.
627   *
628   *   For the moment, only the "standard" configuration (c_dfDIMouse) is supported
629   *   in absolute and relative mode.
630   */
631 static HRESULT WINAPI SysMouseA_SetDataFormat(
632         LPDIRECTINPUTDEVICE32A this,LPCDIDATAFORMAT df
633 ) {
634   int i;
635   LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
636   
637   TRACE(dinput,"(this=%p,%p)\n",this,df);
638
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);
644
645   for (i=0;i<df->dwNumObjs;i++) {
646     char        xbuf[50];
647     
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);
656   }
657
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;
663   }
664   
665   /* For the moment, ignore these fields and return always as if
666      c_dfDIMouse was passed as format... */
667
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;
673   
674   return 0;
675 }
676
677 #define GEN_EVENT(offset,data,time,seq)                                         \
678 {                                                                               \
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++;                                                         \
685   }                                                                             \
686   }
687   
688 /* Our private mouse event handler */
689 static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
690                                       DWORD cButtons, DWORD dwExtraInfo )
691 {
692   DWORD posX, posY, keyState, time, extra;
693   LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) current_lock;
694   
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;
701     
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 ;
708   }
709
710   TRACE(dinput, " %ld %ld ", posX, posY);
711
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;
731         }
732           
733         if (posY != mthis->win_centerY) {
734           GEN_EVENT(DIMOFS_Y, posY - mthis->win_centerY, time, 0);
735           mthis->need_warp = 1;
736         }
737       }
738     }
739   }
740   if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
741     if (TRACE_ON(dinput))
742       DUMP(" LD ");
743
744     GEN_EVENT(DIMOFS_BUTTON0, 0xFF, time, 0);
745   }
746   if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
747     if (TRACE_ON(dinput))
748       DUMP(" LU ");
749
750     GEN_EVENT(DIMOFS_BUTTON0, 0x00, time, 0);
751   }
752   if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
753     if (TRACE_ON(dinput))
754       DUMP(" RD ");
755
756     GEN_EVENT(DIMOFS_BUTTON1, 0xFF, time, 0);
757   }
758   if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
759     if (TRACE_ON(dinput))
760       DUMP(" RU ");
761
762     GEN_EVENT(DIMOFS_BUTTON1, 0x00, time, 0);
763   }
764   if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
765     if (TRACE_ON(dinput))
766       DUMP(" MD ");
767
768     GEN_EVENT(DIMOFS_BUTTON2, 0xFF, time, 0);
769   }
770   if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
771     if (TRACE_ON(dinput))
772       DUMP(" MU ");
773
774     GEN_EVENT(DIMOFS_BUTTON2, 0x00, time, 0);
775   }
776   if (TRACE_ON(dinput))
777     DUMP("\n");
778
779   mthis->prevX = posX;
780   mthis->prevY = posY;
781 }
782
783
784 /******************************************************************************
785   *     Acquire : gets exclusive control of the mouse
786   */
787 static HRESULT WINAPI SysMouseA_Acquire(LPDIRECTINPUTDEVICE32A this) {
788   LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
789   RECT32        rect;
790   
791   TRACE(dinput,"(this=%p)\n",this);
792
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;
797     
798     /* Store (in a global variable) the current lock */
799     current_lock = this;
800     
801     /* Install our own mouse event handler */
802     MOUSE_Enable(dinput_mouse_event);
803     
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);
814     
815     mthis->acquired = 1;
816   }
817   return 0;
818 }
819
820 /******************************************************************************
821   *     Unacquire : frees the mouse
822   */
823 static HRESULT WINAPI SysMouseA_Unacquire(LPDIRECTINPUTDEVICE32A this) {
824   LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
825
826   TRACE(dinput,"(this=%p)\n",this);
827
828   /* Reinstall previous mouse event handler */
829   MOUSE_Enable(mthis->prev_handler);
830   mthis->prev_handler = NULL;
831   
832   /* No more locks */
833   current_lock = NULL;
834
835   /* Unacquire device */
836   mthis->acquired = 0;
837   
838   return 0;
839 }
840
841 /******************************************************************************
842   *     GetDeviceState : returns the "state" of the mouse.
843   *
844   *   For the moment, only the "standard" return structure (DIMOUSESTATE) is
845   *   supported.
846   */
847 static HRESULT WINAPI SysMouseA_GetDeviceState(
848         LPDIRECTINPUTDEVICE32A this,DWORD len,LPVOID ptr
849 ) {
850   DWORD rx, ry, state;
851   struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
852   LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
853   
854   TRACE(dinput,"(this=%p,0x%08lx,%p): \n",this,len,ptr);
855   
856   /* Check if the buffer is big enough */
857   if (len < sizeof(struct DIMOUSESTATE)) {
858     FIXME(dinput, "unsupported state structure.");
859     return DIERR_INVALIDPARAM;
860   }
861   
862   /* Get the mouse position */
863   EVENT_QueryPointer(&rx, &ry, &state);
864   TRACE(dinput,"(X:%ld - Y:%ld)\n", rx, ry);
865
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;
873
874     if ((mstate->lX != 0) || (mstate->lY != 0))
875       mthis->need_warp = 1;
876   }
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;
882   
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;
890   }
891   
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]);
895   
896   return 0;
897 }
898
899 /******************************************************************************
900   *     GetDeviceState : gets buffered input data.
901   */
902 static HRESULT WINAPI SysMouseA_GetDeviceData(LPDIRECTINPUTDEVICE32A this,
903                                               DWORD dodsize,
904                                               LPDIDEVICEOBJECTDATA dod,
905                                               LPDWORD entries,
906                                               DWORD flags
907 ) {
908   LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
909   
910   TRACE(dinput,"(%p)->(%ld,%p,%p(0x%08lx),0x%08lx)\n",
911         this,dodsize,dod,entries,*entries,flags);
912
913   if (flags & DIGDD_PEEK)
914     TRACE(dinput, "DIGDD_PEEK\n");
915
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;
924     }
925     if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
926       ERR(dinput, "Wrong structure size !\n");
927       return DIERR_INVALIDPARAM;
928     }
929     
930     /* Copy the buffered data into the application queue */
931     memcpy(dod, mthis->data_queue, mthis->queue_pos * dodsize);
932     
933     /* Reset the event queue */
934     mthis->queue_pos = 0;
935   }
936   
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;
944   }
945   
946   return 0;
947 }
948
949 /******************************************************************************
950   *     SetProperty : change input device properties
951   */
952 static HRESULT WINAPI SysMouseA_SetProperty(LPDIRECTINPUTDEVICE32A this,
953                                             REFGUID rguid,
954                                             LPCDIPROPHEADER ph) {
955   char  xbuf[50];
956   LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
957
958   if (HIWORD(rguid))
959     WINE_StringFromCLSID(rguid,xbuf);
960   else
961     sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
962
963   TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ph);
964   
965   if (!HIWORD(rguid)) {
966     switch ((DWORD)rguid) {
967     case DIPROP_BUFFERSIZE: {
968       LPCDIPROPDWORD    pd = (LPCDIPROPDWORD)ph;
969       
970       TRACE(dinput,"buffersize = %ld\n",pd->dwData);
971
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;
977     }
978     default:
979       WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
980       break;
981     }
982   }
983   
984   return 0;
985 }
986
987
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,
1016 };
1017
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,
1046 };