3 * Copyright 1998 Marcus Meissner
5 * Additions (mouse support) Copyright 1998 Lionel Ulmer
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
26 #include <sys/signal.h>
33 #include "interfaces.h"
40 extern BYTE InputKeyStateTable
[256];
41 extern int min_keycode
, max_keycode
;
42 extern WORD keyc2vkey
[256];
44 static IDirectInputA_VTable ddiavt
;
45 static IDirectInputDeviceA_VTable SysKeyboardAvt
;
46 static IDirectInputDeviceA_VTable SysMouseAvt
;
48 /******************************************************************************
49 * DirectInputCreate32A
51 HRESULT WINAPI
DirectInputCreate32A(HINSTANCE32 hinst
, DWORD dwVersion
, LPDIRECTINPUT32A
*ppDI
, LPUNKNOWN punkOuter
) {
52 TRACE(dinput
, "(0x%08lx,%04lx,%p,%p)\n",
53 (DWORD
)hinst
,dwVersion
,ppDI
,punkOuter
55 (*ppDI
) = (LPDIRECTINPUT32A
)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInput32A
));
57 (*ppDI
)->lpvtbl
= &ddiavt
;
60 /******************************************************************************
61 * IDirectInputA_EnumDevices
63 static HRESULT WINAPI
IDirectInputA_EnumDevices(
64 LPDIRECTINPUT32A
this, DWORD dwDevType
, LPDIENUMDEVICESCALLBACK32A lpCallback
,
65 LPVOID pvRef
, DWORD dwFlags
67 DIDEVICEINSTANCE32A devInstance
;
70 TRACE(dinput
, "(this=%p,0x%04lx,%p,%p,%04lx)\n", this, dwDevType
, lpCallback
, pvRef
, dwFlags
);
72 #if 0 /* Not compiled for the moment as long as I do not find
73 the needed constants */
74 /* Ignore this field for the moment */
76 FIXME(dinput
, "device filtering not supported.\n");
79 devInstance
.dwSize
= sizeof(DIDEVICEINSTANCE32A
);
82 devInstance
.guidInstance
= GUID_SysKeyboard
;
83 devInstance
.guidProduct
= GUID_SysKeyboard
;
84 devInstance
.dwDevType
= 1; /* Constant unknown :-( */
85 strcpy(devInstance
.tszInstanceName
, "Keyboard");
86 strcpy(devInstance
.tszProductName
, "Wine Keyboard");
88 ret
= lpCallback(&devInstance
, pvRef
);
89 TRACE(dinput
, "Keyboard registered (%d)\n", ret
);
95 devInstance
.guidInstance
= GUID_SysMouse
;
96 devInstance
.guidProduct
= GUID_SysMouse
;
97 devInstance
.dwDevType
= 2; /* Constant unknown :-( */
98 strcpy(devInstance
.tszInstanceName
, "Mouse");
99 strcpy(devInstance
.tszProductName
, "Wine Mouse");
101 ret
= lpCallback(&devInstance
, pvRef
);
102 TRACE(dinput
, "Mouse registered (%d)\n", ret
);
108 static ULONG WINAPI
IDirectInputA_AddRef(LPDIRECTINPUT32A
this) {
109 return ++(this->ref
);
112 static ULONG WINAPI
IDirectInputA_Release(LPDIRECTINPUT32A
this) {
113 if (!(--this->ref
)) {
114 HeapFree(GetProcessHeap(),0,this);
120 static HRESULT WINAPI
IDirectInputA_CreateDevice(
121 LPDIRECTINPUT32A
this,REFGUID rguid
,LPDIRECTINPUTDEVICE32A
* pdev
,
126 WINE_StringFromCLSID(rguid
,xbuf
);
127 FIXME(dinput
,"(this=%p,%s,%p,%p): stub\n",this,xbuf
,pdev
,punk
);
128 if (!memcmp(&GUID_SysKeyboard
,rguid
,sizeof(GUID_SysKeyboard
))) {
129 *pdev
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(SysKeyboard32A
));
131 (*pdev
)->lpvtbl
= &SysKeyboardAvt
;
132 memcpy(&((*pdev
)->guid
),rguid
,sizeof(*rguid
));
133 memset(((LPSYSKEYBOARD32A
)(*pdev
))->keystate
,0,256);
136 if (!memcmp(&GUID_SysMouse
,rguid
,sizeof(GUID_SysMouse
))) {
137 *pdev
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(SysMouse32A
));
139 (*pdev
)->lpvtbl
= &SysMouseAvt
;
140 memcpy(&((*pdev
)->guid
),rguid
,sizeof(*rguid
));
146 static HRESULT WINAPI
IDirectInputA_QueryInterface(
147 LPDIRECTINPUT32A
this,REFIID riid
,LPVOID
*ppobj
151 WINE_StringFromCLSID(riid
,xbuf
);
152 TRACE(dinput
,"(this=%p,%s,%p)\n",this,xbuf
,ppobj
);
153 if (!memcmp(&IID_IUnknown
,riid
,sizeof(*riid
))) {
154 this->lpvtbl
->fnAddRef(this);
158 if (!memcmp(&IID_IDirectInputA
,riid
,sizeof(*riid
))) {
159 this->lpvtbl
->fnAddRef(this);
166 static HRESULT WINAPI
IDirectInputA_Initialize(
167 LPDIRECTINPUT32A
this,HINSTANCE32 hinst
,DWORD x
169 return DIERR_ALREADYINITIALIZED
;
172 static IDirectInputA_VTable ddiavt
= {
173 IDirectInputA_QueryInterface
,
174 IDirectInputA_AddRef
,
175 IDirectInputA_Release
,
176 IDirectInputA_CreateDevice
,
177 IDirectInputA_EnumDevices
,
180 IDirectInputA_Initialize
183 /******************************************************************************
184 * IDirectInputDeviceA
186 static HRESULT WINAPI
IDirectInputDeviceA_SetDataFormat(
187 LPDIRECTINPUTDEVICE32A
this,LPCDIDATAFORMAT df
191 TRACE(dinput,"(this=%p,%p)\n",this,df);
193 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
194 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
195 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
196 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
197 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
199 for (i=0;i<df->dwNumObjs;i++) {
202 if (df->rgodf[i].pguid)
203 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
205 strcpy(xbuf,"<no guid>");
206 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
207 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
208 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
209 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
215 static HRESULT WINAPI
IDirectInputDeviceA_SetCooperativeLevel(
216 LPDIRECTINPUTDEVICE32A
this,HWND32 hwnd
,DWORD dwflags
218 FIXME(dinput
,"(this=%p,0x%08lx,0x%08lx): stub\n",this,(DWORD
)hwnd
,dwflags
);
222 static HRESULT WINAPI
IDirectInputDeviceA_SetProperty(
223 LPDIRECTINPUTDEVICE32A
this,REFGUID rguid
,LPCDIPROPHEADER ph
228 WINE_StringFromCLSID(rguid
,xbuf
);
230 sprintf(xbuf
,"<special guid %ld>",(DWORD
)rguid
);
231 TRACE(dinput
,"(this=%p,%s,%p)\n",this,xbuf
,ph
);
232 if (!HIWORD(rguid
)) {
233 switch ((DWORD
)rguid
) {
234 case DIPROP_BUFFERSIZE
: {
235 LPCDIPROPDWORD pd
= (LPCDIPROPDWORD
)ph
;
237 TRACE(dinput
,"buffersize = %ld\n",pd
->dwData
);
241 WARN(dinput
,"Unknown type %ld\n",(DWORD
)rguid
);
248 static HRESULT WINAPI
IDirectInputDeviceA_SetEventNotification(
249 LPDIRECTINPUTDEVICE32A
this,HANDLE32 hnd
251 FIXME(dinput
,"(this=%p,0x%08lx): stub\n",this,(DWORD
)hnd
);
255 static HRESULT WINAPI
IDirectInputDeviceA_GetDeviceData(
256 LPDIRECTINPUTDEVICE32A
this,DWORD dodsize
,LPDIDEVICEOBJECTDATA dod
,
257 LPDWORD entries
,DWORD flags
259 TRACE(dinput
,"IDirectInputDeviceA(%p)->GetDeviceData(%ld,%p,%p(0x%08lx),0x%08lx)\n",
260 this,dodsize
,dod
,entries
,*entries
,flags
);
265 static HRESULT WINAPI
IDirectInputDeviceA_Acquire(LPDIRECTINPUTDEVICE32A
this) {
266 FIXME(dinput
,"(this=%p): stub\n",this);
270 static HRESULT WINAPI
IDirectInputDeviceA_Unacquire(LPDIRECTINPUTDEVICE32A
this) {
271 FIXME(dinput
,"(this=%p): stub\n",this);
275 static ULONG WINAPI
IDirectInputDeviceA_Release(LPDIRECTINPUTDEVICE32A
this) {
279 HeapFree(GetProcessHeap(),0,this);
283 static HRESULT WINAPI
SysKeyboardA_SetProperty(
284 LPDIRECTINPUTDEVICE32A
this,REFGUID rguid
,LPCDIPROPHEADER ph
289 WINE_StringFromCLSID(rguid
,xbuf
);
291 sprintf(xbuf
,"<special guid %ld>",(DWORD
)rguid
);
292 TRACE(dinput
,"(this=%p,%s,%p)\n",this,xbuf
,ph
);
293 TRACE(dinput
,"(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
294 ph
->dwSize
,ph
->dwHeaderSize
,ph
->dwObj
,ph
->dwHow
);
295 if (!HIWORD(rguid
)) {
296 switch ((DWORD
)rguid
) {
297 case DIPROP_BUFFERSIZE
: {
298 LPCDIPROPDWORD pd
= (LPCDIPROPDWORD
)ph
;
300 TRACE(dinput
,"(buffersize=%ld)\n",pd
->dwData
);
304 WARN(dinput
,"Unknown type %ld\n",(DWORD
)rguid
);
311 static HRESULT WINAPI
SysKeyboardA_GetDeviceState(
312 LPDIRECTINPUTDEVICE32A
this,DWORD len
,LPVOID ptr
318 for (keyc
=min_keycode
;keyc
<max_keycode
;keyc
++)
320 /* X keycode to virtual key */
321 vkey
= keyc2vkey
[keyc
] & 0xFF;
322 /* The windows scancode is keyc-min_keycode */
323 if (InputKeyStateTable
[vkey
]&0x80) {
324 ((LPBYTE
)ptr
)[keyc
-min_keycode
]=0x80;
325 ((LPBYTE
)ptr
)[(keyc
-min_keycode
)|0x80]=0x80;
330 WARN(dinput
,"whoops, SysKeyboardA_GetDeviceState got len %ld?\n",len
);
334 static HRESULT WINAPI
SysKeyboardA_GetDeviceData(
335 LPDIRECTINPUTDEVICE32A
this,DWORD dodsize
,LPDIDEVICEOBJECTDATA dod
,
336 LPDWORD entries
,DWORD flags
338 int keyc
,n
,vkey
,xentries
;
339 LPSYSKEYBOARD32A kthis
= (LPSYSKEYBOARD32A
)this;
341 TRACE(dinput
,"(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
342 this,dodsize
,dod
,entries
,entries
?*entries
:0,flags
);
343 EVENT_WaitNetEvent(FALSE
,TRUE
);
351 for (keyc
=min_keycode
;(keyc
<max_keycode
) && (n
<*entries
);keyc
++)
353 /* X keycode to virtual key */
354 vkey
= keyc2vkey
[keyc
] & 0xFF;
355 if (kthis
->keystate
[vkey
] == (InputKeyStateTable
[vkey
]&0x80))
359 dod
[n
].dwOfs
= keyc
-min_keycode
; /* scancode */
360 dod
[n
].dwData
= InputKeyStateTable
[vkey
]&0x80;
361 dod
[n
].dwTimeStamp
= 0; /* umm */
362 dod
[n
].dwSequence
= 0; /* umm */
365 if (!(flags
& DIGDD_PEEK
))
366 kthis
->keystate
[vkey
] = InputKeyStateTable
[vkey
]&0x80;
370 if (n
) fprintf(stderr
,"%d entries\n",n
);
375 static HRESULT WINAPI
SysKeyboardA_Acquire(LPDIRECTINPUTDEVICE32A
this) {
376 FIXME(dinput
,"(this=%p): stub\n",this);
380 static HRESULT WINAPI
SysKeyboardA_Unacquire(LPDIRECTINPUTDEVICE32A
this) {
381 FIXME(dinput
,"(this=%p): stub\n",this);
385 static HRESULT WINAPI
IDirectInputDeviceA_QueryInterface(
386 LPDIRECTINPUTDEVICE32A
this,REFIID riid
,LPVOID
*ppobj
390 WINE_StringFromCLSID(riid
,xbuf
);
391 TRACE(dinput
,"(this=%p,%s,%p)\n",this,xbuf
,ppobj
);
392 if (!memcmp(&IID_IUnknown
,riid
,sizeof(*riid
))) {
393 this->lpvtbl
->fnAddRef(this);
397 if (!memcmp(&IID_IDirectInputDeviceA
,riid
,sizeof(*riid
))) {
398 this->lpvtbl
->fnAddRef(this);
405 /******************************************************************************
406 * SysMouseA (DInput Mouse support)
409 /******************************************************************************
410 * SetDataFormat : the application can choose the format of the data
411 * the device driver sends back with GetDeviceState.
413 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
414 * in absolute and relative mode.
416 static HRESULT WINAPI
SysMouseA_SetDataFormat(
417 LPDIRECTINPUTDEVICE32A
this,LPCDIDATAFORMAT df
420 LPSYSMOUSE32A mthis
= (LPSYSMOUSE32A
) this;
422 TRACE(dinput
,"(this=%p,%p)\n",this,df
);
424 TRACE(dinput
,"(df.dwSize=%ld)\n",df
->dwSize
);
425 TRACE(dinput
,"(df.dwObjsize=%ld)\n",df
->dwObjSize
);
426 TRACE(dinput
,"(df.dwFlags=0x%08lx)\n",df
->dwFlags
);
427 TRACE(dinput
,"(df.dwDataSize=%ld)\n",df
->dwDataSize
);
428 TRACE(dinput
,"(df.dwNumObjs=%ld)\n",df
->dwNumObjs
);
430 for (i
=0;i
<df
->dwNumObjs
;i
++) {
433 if (df
->rgodf
[i
].pguid
)
434 WINE_StringFromCLSID(df
->rgodf
[i
].pguid
,xbuf
);
436 strcpy(xbuf
,"<no guid>");
437 TRACE(dinput
,"df.rgodf[%d].guid %s (%p)\n",i
,xbuf
, df
->rgodf
[i
].pguid
);
438 TRACE(dinput
,"df.rgodf[%d].dwOfs %ld\n",i
,df
->rgodf
[i
].dwOfs
);
439 TRACE(dinput
,"dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df
->rgodf
[i
].dwType
),DIDFT_GETINSTANCE(df
->rgodf
[i
].dwType
));
440 TRACE(dinput
,"df.rgodf[%d].dwFlags 0x%08lx\n",i
,df
->rgodf
[i
].dwFlags
);
443 /* Check size of data format to prevent crashes if the applications
444 sends a smaller buffer */
445 if (df
->dwDataSize
!= sizeof(struct DIMOUSESTATE
)) {
446 FIXME(dinput
, "non-standard mouse configuration not supported yet.");
447 return DIERR_INVALIDPARAM
;
450 /* For the moment, ignore these fields and return always as if
451 c_dfDIMouse was passed as format... */
452 if (df
->dwFlags
== DIDF_ABSAXIS
)
459 /* We need to get the initial "previous" position to be able
463 /* Get the mouse position */
464 TSXQueryPointer(display
, rootWindow
, &rw
, &cr
,
465 &rx
, &ry
, &cx
, &cy
, &mask
);
466 /* Fill the initial mouse state structure */
474 /******************************************************************************
475 * GetDeviceState : returns the "state" of the mouse.
477 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
480 static HRESULT WINAPI
SysMouseA_GetDeviceState(
481 LPDIRECTINPUTDEVICE32A
this,DWORD len
,LPVOID ptr
486 struct DIMOUSESTATE
*mstate
= (struct DIMOUSESTATE
*) ptr
;
487 LPSYSMOUSE32A mthis
= (LPSYSMOUSE32A
) this;
489 TRACE(dinput
,"(this=%p,0x%08lx,%p): \n",this,len
,ptr
);
491 /* Check if the buffer is big enough */
492 if (len
< sizeof(struct DIMOUSESTATE
)) {
493 FIXME(dinput
, "unsupported state structure.");
494 return DIERR_INVALIDPARAM
;
497 /* Get the mouse position */
498 TSXQueryPointer(display
, rootWindow
, &rw
, &cr
,
499 &rx
, &ry
, &cx
, &cy
, &mask
);
500 TRACE(dinput
,"(X:%d - Y:%d)\n", rx
, ry
);
502 /* Fill the mouse state structure */
503 if (mthis
->absolute
) {
507 mstate
->lX
= rx
- mthis
->prevX
;
508 mstate
->lY
= ry
- mthis
->prevY
;
509 /* Fill the previous positions */
514 mstate
->rgbButtons
[0] = (mask
& Button1Mask
? 0xFF : 0x00);
515 mstate
->rgbButtons
[1] = (mask
& Button3Mask
? 0xFF : 0x00); /* Windows button two is X button 3 */
516 mstate
->rgbButtons
[2] = (mask
& Button2Mask
? 0xFF : 0x00);
517 mstate
->rgbButtons
[3] = (mask
& Button4Mask
? 0xFF : 0x00);
524 static IDirectInputDeviceA_VTable SysKeyboardAvt
={
525 IDirectInputDeviceA_QueryInterface
,
527 IDirectInputDeviceA_Release
,
531 SysKeyboardA_SetProperty
,
532 SysKeyboardA_Acquire
,
533 SysKeyboardA_Unacquire
,
534 SysKeyboardA_GetDeviceState
,
535 SysKeyboardA_GetDeviceData
,
536 IDirectInputDeviceA_SetDataFormat
,
537 IDirectInputDeviceA_SetEventNotification
,
538 IDirectInputDeviceA_SetCooperativeLevel
,
545 static IDirectInputDeviceA_VTable SysMouseAvt
={
546 IDirectInputDeviceA_QueryInterface
,
548 IDirectInputDeviceA_Release
,
552 IDirectInputDeviceA_SetProperty
,
553 IDirectInputDeviceA_Acquire
,
554 IDirectInputDeviceA_Unacquire
,
555 SysMouseA_GetDeviceState
,
556 IDirectInputDeviceA_GetDeviceData
,
557 SysMouseA_SetDataFormat
,
558 IDirectInputDeviceA_SetEventNotification
,
559 IDirectInputDeviceA_SetCooperativeLevel
,