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
27 #include <sys/signal.h>
34 #include "interfaces.h"
42 extern BYTE InputKeyStateTable[256];
43 extern int min_keycode, max_keycode;
44 extern WORD keyc2vkey[256];
46 static IDirectInputA_VTable ddiavt;
47 static IDirectInputDeviceA_VTable SysKeyboardAvt;
48 static IDirectInputDeviceA_VTable SysMouseAvt;
50 /* UIDs for Wine "drivers".
51 When enumerating each device supporting DInput, they have two UIDs :
54 static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
58 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
60 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
64 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
67 /******************************************************************************
68 * DirectInputCreate32A
70 HRESULT WINAPI DirectInputCreate32A(HINSTANCE32 hinst, DWORD dwVersion, LPDIRECTINPUT32A *ppDI, LPUNKNOWN punkOuter) {
71 TRACE(dinput, "(0x%08lx,%04lx,%p,%p)\n",
72 (DWORD)hinst,dwVersion,ppDI,punkOuter
74 (*ppDI) = (LPDIRECTINPUT32A)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInput32A));
76 (*ppDI)->lpvtbl = &ddiavt;
79 /******************************************************************************
80 * IDirectInputA_EnumDevices
82 static HRESULT WINAPI IDirectInputA_EnumDevices(
83 LPDIRECTINPUT32A this, DWORD dwDevType, LPDIENUMDEVICESCALLBACK32A lpCallback,
84 LPVOID pvRef, DWORD dwFlags
86 DIDEVICEINSTANCE32A devInstance;
89 TRACE(dinput, "(this=%p,0x%04lx,%p,%p,%04lx)\n", this, dwDevType, lpCallback, pvRef, dwFlags);
91 devInstance.dwSize = sizeof(DIDEVICEINSTANCE32A);
93 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
95 devInstance.guidInstance = GUID_SysKeyboard; /* DInput's GUID */
96 devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
97 devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
98 strcpy(devInstance.tszInstanceName, "Keyboard");
99 strcpy(devInstance.tszProductName, "Wine Keyboard");
101 ret = lpCallback(&devInstance, pvRef);
102 TRACE(dinput, "Keyboard registered\n");
104 if (ret == DIENUM_STOP)
108 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
110 devInstance.guidInstance = GUID_SysMouse; /* DInput's GUID */
111 devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
112 devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
113 strcpy(devInstance.tszInstanceName, "Mouse");
114 strcpy(devInstance.tszProductName, "Wine Mouse");
116 ret = lpCallback(&devInstance, pvRef);
117 TRACE(dinput, "Mouse registered\n");
120 /* Should also do joystick enumerations.... */
125 static ULONG WINAPI IDirectInputA_AddRef(LPDIRECTINPUT32A this) {
126 return ++(this->ref);
129 static ULONG WINAPI IDirectInputA_Release(LPDIRECTINPUT32A this) {
130 if (!(--this->ref)) {
131 HeapFree(GetProcessHeap(),0,this);
137 static HRESULT WINAPI IDirectInputA_CreateDevice(
138 LPDIRECTINPUT32A this,REFGUID rguid,LPDIRECTINPUTDEVICE32A* pdev,
143 WINE_StringFromCLSID(rguid,xbuf);
144 FIXME(dinput,"(this=%p,%s,%p,%p): stub\n",this,xbuf,pdev,punk);
145 if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) || /* Generic Keyboard */
146 (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
147 *pdev = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboard32A));
149 (*pdev)->lpvtbl = &SysKeyboardAvt;
150 memcpy(&((*pdev)->guid),rguid,sizeof(*rguid));
151 memset(((LPSYSKEYBOARD32A)(*pdev))->keystate,0,256);
154 if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) || /* Generic Mouse */
155 (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Mouse */
156 *pdev = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouse32A));
158 (*pdev)->lpvtbl = &SysMouseAvt;
159 memcpy(&((*pdev)->guid),rguid,sizeof(*rguid));
165 static HRESULT WINAPI IDirectInputA_QueryInterface(
166 LPDIRECTINPUT32A this,REFIID riid,LPVOID *ppobj
170 WINE_StringFromCLSID(riid,xbuf);
171 TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ppobj);
172 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
173 this->lpvtbl->fnAddRef(this);
177 if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
178 this->lpvtbl->fnAddRef(this);
185 static HRESULT WINAPI IDirectInputA_Initialize(
186 LPDIRECTINPUT32A this,HINSTANCE32 hinst,DWORD x
188 return DIERR_ALREADYINITIALIZED;
191 static IDirectInputA_VTable ddiavt= {
192 IDirectInputA_QueryInterface,
193 IDirectInputA_AddRef,
194 IDirectInputA_Release,
195 IDirectInputA_CreateDevice,
196 IDirectInputA_EnumDevices,
199 IDirectInputA_Initialize
202 /******************************************************************************
203 * IDirectInputDeviceA
205 static HRESULT WINAPI IDirectInputDeviceA_SetDataFormat(
206 LPDIRECTINPUTDEVICE32A this,LPCDIDATAFORMAT df
210 TRACE(dinput,"(this=%p,%p)\n",this,df);
212 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
213 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
214 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
215 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
216 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
218 for (i=0;i<df->dwNumObjs;i++) {
221 if (df->rgodf[i].pguid)
222 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
224 strcpy(xbuf,"<no guid>");
225 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
226 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
227 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
228 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
234 static HRESULT WINAPI IDirectInputDeviceA_SetCooperativeLevel(
235 LPDIRECTINPUTDEVICE32A this,HWND32 hwnd,DWORD dwflags
237 FIXME(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",this,(DWORD)hwnd,dwflags);
241 static HRESULT WINAPI IDirectInputDeviceA_SetProperty(
242 LPDIRECTINPUTDEVICE32A this,REFGUID rguid,LPCDIPROPHEADER ph
247 WINE_StringFromCLSID(rguid,xbuf);
249 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
250 TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ph);
251 if (!HIWORD(rguid)) {
252 switch ((DWORD)rguid) {
253 case DIPROP_BUFFERSIZE: {
254 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
256 TRACE(dinput,"buffersize = %ld\n",pd->dwData);
260 WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
267 static HRESULT WINAPI IDirectInputDeviceA_SetEventNotification(
268 LPDIRECTINPUTDEVICE32A this,HANDLE32 hnd
270 FIXME(dinput,"(this=%p,0x%08lx): stub\n",this,(DWORD)hnd);
274 static HRESULT WINAPI IDirectInputDeviceA_GetDeviceData(
275 LPDIRECTINPUTDEVICE32A this,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
276 LPDWORD entries,DWORD flags
278 TRACE(dinput,"IDirectInputDeviceA(%p)->GetDeviceData(%ld,%p,%p(0x%08lx),0x%08lx)\n",
279 this,dodsize,dod,entries,*entries,flags);
284 static HRESULT WINAPI IDirectInputDeviceA_Acquire(LPDIRECTINPUTDEVICE32A this) {
285 TRACE(dinput,"(this=%p): stub\n",this);
289 static HRESULT WINAPI IDirectInputDeviceA_Unacquire(LPDIRECTINPUTDEVICE32A this) {
290 TRACE(dinput,"(this=%p): stub\n",this);
294 static ULONG WINAPI IDirectInputDeviceA_Release(LPDIRECTINPUTDEVICE32A this) {
298 HeapFree(GetProcessHeap(),0,this);
302 static HRESULT WINAPI SysKeyboardA_SetProperty(
303 LPDIRECTINPUTDEVICE32A this,REFGUID rguid,LPCDIPROPHEADER ph
308 WINE_StringFromCLSID(rguid,xbuf);
310 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
311 TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ph);
312 TRACE(dinput,"(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
313 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
314 if (!HIWORD(rguid)) {
315 switch ((DWORD)rguid) {
316 case DIPROP_BUFFERSIZE: {
317 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
319 TRACE(dinput,"(buffersize=%ld)\n",pd->dwData);
323 WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
330 static HRESULT WINAPI SysKeyboardA_GetDeviceState(
331 LPDIRECTINPUTDEVICE32A this,DWORD len,LPVOID ptr
337 for (keyc=min_keycode;keyc<max_keycode;keyc++)
339 /* X keycode to virtual key */
340 vkey = keyc2vkey[keyc] & 0xFF;
341 /* The windows scancode is keyc-min_keycode */
342 if (InputKeyStateTable[vkey]&0x80) {
343 ((LPBYTE)ptr)[keyc-min_keycode]=0x80;
344 ((LPBYTE)ptr)[(keyc-min_keycode)|0x80]=0x80;
349 WARN(dinput,"whoops, SysKeyboardA_GetDeviceState got len %ld?\n",len);
353 static HRESULT WINAPI SysKeyboardA_GetDeviceData(
354 LPDIRECTINPUTDEVICE32A this,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
355 LPDWORD entries,DWORD flags
357 int keyc,n,vkey,xentries;
358 LPSYSKEYBOARD32A kthis = (LPSYSKEYBOARD32A)this;
360 TRACE(dinput,"(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
361 this,dodsize,dod,entries,entries?*entries:0,flags);
362 EVENT_WaitNetEvent(FALSE,TRUE);
370 for (keyc=min_keycode;(keyc<max_keycode) && (n<*entries);keyc++)
372 /* X keycode to virtual key */
373 vkey = keyc2vkey[keyc] & 0xFF;
374 if (kthis->keystate[vkey] == (InputKeyStateTable[vkey]&0x80))
378 dod[n].dwOfs = keyc-min_keycode; /* scancode */
379 dod[n].dwData = InputKeyStateTable[vkey]&0x80;
380 dod[n].dwTimeStamp = 0; /* umm */
381 dod[n].dwSequence = 0; /* umm */
384 if (!(flags & DIGDD_PEEK))
385 kthis->keystate[vkey] = InputKeyStateTable[vkey]&0x80;
389 if (n) fprintf(stderr,"%d entries\n",n);
394 static HRESULT WINAPI SysKeyboardA_Acquire(LPDIRECTINPUTDEVICE32A this) {
395 TRACE(dinput,"(this=%p): stub\n",this);
399 static HRESULT WINAPI SysKeyboardA_Unacquire(LPDIRECTINPUTDEVICE32A this) {
400 TRACE(dinput,"(this=%p): stub\n",this);
404 static HRESULT WINAPI IDirectInputDeviceA_QueryInterface(
405 LPDIRECTINPUTDEVICE32A this,REFIID riid,LPVOID *ppobj
409 WINE_StringFromCLSID(riid,xbuf);
410 TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ppobj);
411 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
412 this->lpvtbl->fnAddRef(this);
416 if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
417 this->lpvtbl->fnAddRef(this);
424 /******************************************************************************
425 * SysMouseA (DInput Mouse support)
428 /******************************************************************************
429 * SetDataFormat : the application can choose the format of the data
430 * the device driver sends back with GetDeviceState.
432 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
433 * in absolute and relative mode.
435 static HRESULT WINAPI SysMouseA_SetDataFormat(
436 LPDIRECTINPUTDEVICE32A this,LPCDIDATAFORMAT df
439 LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
441 TRACE(dinput,"(this=%p,%p)\n",this,df);
443 TRACE(dinput,"(df.dwSize=%ld)\n",df->dwSize);
444 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
445 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
446 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
447 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
449 for (i=0;i<df->dwNumObjs;i++) {
452 if (df->rgodf[i].pguid)
453 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
455 strcpy(xbuf,"<no guid>");
456 TRACE(dinput,"df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
457 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
458 TRACE(dinput,"dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
459 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
462 /* Check size of data format to prevent crashes if the applications
463 sends a smaller buffer */
464 if (df->dwDataSize != sizeof(struct DIMOUSESTATE)) {
465 FIXME(dinput, "non-standard mouse configuration not supported yet.");
466 return DIERR_INVALIDPARAM;
469 /* For the moment, ignore these fields and return always as if
470 c_dfDIMouse was passed as format... */
471 if (df->dwFlags == DIDF_ABSAXIS)
476 /* We need to get the initial "previous" position to be able
480 /* Get the mouse position */
481 EVENT_QueryPointer(&rx, &ry, NULL);
483 /* Fill the initial mouse state structure */
491 /******************************************************************************
492 * GetDeviceState : returns the "state" of the mouse.
494 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
497 static HRESULT WINAPI SysMouseA_GetDeviceState(
498 LPDIRECTINPUTDEVICE32A this,DWORD len,LPVOID ptr
501 struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
502 LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
504 TRACE(dinput,"(this=%p,0x%08lx,%p): \n",this,len,ptr);
506 /* Check if the buffer is big enough */
507 if (len < sizeof(struct DIMOUSESTATE)) {
508 FIXME(dinput, "unsupported state structure.");
509 return DIERR_INVALIDPARAM;
512 /* Get the mouse position */
513 EVENT_QueryPointer(&rx, &ry, &state);
514 TRACE(dinput,"(X:%d - Y:%d)\n", rx, ry);
516 /* Fill the mouse state structure */
517 if (mthis->absolute) {
521 mstate->lX = rx - mthis->prevX;
522 mstate->lY = ry - mthis->prevY;
523 /* Fill the previous positions */
528 mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00);
529 mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00);
530 mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00);
531 mstate->rgbButtons[3] = 0x00;
538 static IDirectInputDeviceA_VTable SysKeyboardAvt={
539 IDirectInputDeviceA_QueryInterface,
541 IDirectInputDeviceA_Release,
545 SysKeyboardA_SetProperty,
546 SysKeyboardA_Acquire,
547 SysKeyboardA_Unacquire,
548 SysKeyboardA_GetDeviceState,
549 SysKeyboardA_GetDeviceData,
550 IDirectInputDeviceA_SetDataFormat,
551 IDirectInputDeviceA_SetEventNotification,
552 IDirectInputDeviceA_SetCooperativeLevel,
559 static IDirectInputDeviceA_VTable SysMouseAvt={
560 IDirectInputDeviceA_QueryInterface,
562 IDirectInputDeviceA_Release,
566 IDirectInputDeviceA_SetProperty,
567 IDirectInputDeviceA_Acquire,
568 IDirectInputDeviceA_Unacquire,
569 SysMouseA_GetDeviceState,
570 IDirectInputDeviceA_GetDeviceData,
571 SysMouseA_SetDataFormat,
572 IDirectInputDeviceA_SetEventNotification,
573 IDirectInputDeviceA_SetCooperativeLevel,