source: trunk/src/dinput/dinput.cpp@ 2912

Last change on this file since 2912 was 2499, checked in by sandervl, 26 years ago

Michal Necasek's updates

File size: 52.9 KB
Line 
1/* $Id: dinput.cpp,v 1.4 2000-01-22 10:31:06 sandervl Exp $ */
2/* DirectInput
3 *
4 * Copyright 1998 Marcus Meissner
5 * Copyright 1998,1999 Lionel Ulmer
6 *
7 */
8/* Status:
9 *
10 * - Tomb Raider 2 Demo:
11 * Playable using keyboard only.
12 * - WingCommander Prophecy Demo:
13 * Doesn't get Input Focus.
14 *
15 * - Fallout : works great in X and DGA mode
16 *
17 * FIXME: The keyboard handling needs to (and will) be merged into keyboard.c
18 * (The current implementation is currently only a proof of concept and
19 * an utter mess.)
20 */
21#ifdef __WIN32OS2__
22#include <odin.h>
23#include <os2win.h>
24
25#define ICOM_CINTERFACE 1
26#define CINTERFACE
27#endif
28
29#include "config.h"
30#include <string.h>
31#include <time.h>
32//#include <unistd.h>
33#include <assert.h>
34#ifdef HAVE_SYS_SIGNAL_H
35# include <sys/signal.h>
36#endif
37//#include <sys/time.h>
38//#include <sys/fcntl.h>
39//#include <sys/ioctl.h>
40#include <errno.h>
41#ifdef HAVE_SYS_ERRNO_H
42# include <sys/errno.h>
43#endif
44#ifdef HAVE_LINUX_JOYSTICK_H
45# include <linux/joystick.h>
46# define JOYDEV "/dev/js0"
47#endif
48#include "wine/obj_base.h"
49#include "debugtools.h"
50#include "dinput.h"
51#include "display.h"
52//#include "keyboard.h"
53//#include "message.h"
54#include "mouse.h"
55#include "sysmetrics.h"
56#include "winbase.h"
57#include "winerror.h"
58#include "winuser.h"
59
60#ifdef __WIN32OS2__
61#include <heapstring.h>
62#include <misc.h>
63#include "oslibinput.h"
64#endif
65
66DEFAULT_DEBUG_CHANNEL(dinput)
67
68extern VOID WIN32API KEYBOARD_Enable(WNDPROC handler);
69
70extern BYTE InputKeyStateTable[256];
71extern int min_keycode, max_keycode;
72extern WORD keyc2vkey[256];
73
74extern ICOM_VTABLE(IDirectInputA) ddiavt;
75extern ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt;
76extern ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt;
77
78typedef struct IDirectInputAImpl IDirectInputAImpl;
79typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
80typedef struct SysKeyboardAImpl SysKeyboardAImpl;
81typedef struct SysMouseAImpl SysMouseAImpl;
82
83struct IDirectInputDevice2AImpl
84{
85 ICOM_VFIELD(IDirectInputDevice2A);
86 DWORD ref;
87 GUID guid;
88};
89
90struct SysKeyboardAImpl
91{
92 /* IDirectInputDevice2AImpl */
93 ICOM_VFIELD(IDirectInputDevice2A);
94 DWORD ref;
95 GUID guid;
96 /* SysKeyboardAImpl */
97 LPDIDEVICEOBJECTDATA data_queue;
98 int queue_pos, queue_len;
99 CRITICAL_SECTION crit;
100 int acquired;
101 BYTE keystate[256];
102};
103
104#ifdef HAVE_LINUX_22_JOYSTICK_API
105typedef struct JoystickAImpl JoystickAImpl;
106ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt;
107struct JoystickAImpl
108{
109 /* IDirectInputDevice2AImpl */
110 ICOM_VFIELD(IDirectInputDevice2A);
111 DWORD ref;
112 GUID guid;
113
114 /* joystick private */
115 int joyfd;
116 LPDIDATAFORMAT df;
117 HANDLE hEvent;
118 LONG lMin,lMax,deadzone;
119 LPDIDEVICEOBJECTDATA data_queue;
120 int queue_pos, queue_len;
121 DIJOYSTATE js;
122};
123#endif
124
125struct SysMouseAImpl
126{
127 /* IDirectInputDevice2AImpl */
128 ICOM_VFIELD(IDirectInputDevice2A);
129 DWORD ref;
130 GUID guid;
131
132 LPDIDATAFORMAT df;
133 /* SysMouseAImpl */
134 BYTE absolute;
135 /* Previous position for relative moves */
136 LONG prevX, prevY;
137 LPMOUSE_EVENT_PROC prev_handler;
138 HWND win;
139 DWORD win_centerX, win_centerY;
140 LPDIDEVICEOBJECTDATA data_queue;
141 int queue_pos, queue_len;
142 int need_warp;
143 int acquired;
144 HANDLE hEvent;
145 CRITICAL_SECTION crit;
146};
147
148static int evsequence=0;
149
150
151/* UIDs for Wine "drivers".
152 When enumerating each device supporting DInput, they have two UIDs :
153 - the 'windows' UID
154 - a vendor UID */
155#ifdef HAVE_LINUX_22_JOYSTICK_API
156static GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
157 0x9e573ed9,
158 0x7734,
159 0x11d2,
160 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
161};
162#endif
163static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
164 0x9e573ed8,
165 0x7734,
166 0x11d2,
167 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
168};
169static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
170 0x0ab8648a,
171 0x7735,
172 0x11d2,
173 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
174};
175
176/* FIXME: This is ugly and not thread safe :/ */
177static IDirectInputDevice2A* current_lock = NULL;
178static IDirectInputDeviceA* current_keylock = NULL;
179
180/******************************************************************************
181 * Various debugging tools
182 */
183static void _dump_cooperativelevel(DWORD dwFlags) {
184 int i;
185 const struct {
186 DWORD mask;
187 char *name;
188 } flags[] = {
189#define FE(x) { x, #x},
190 FE(DISCL_BACKGROUND)
191 FE(DISCL_EXCLUSIVE)
192 FE(DISCL_FOREGROUND)
193 FE(DISCL_NONEXCLUSIVE)
194 };
195 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
196 if (flags[i].mask & dwFlags)
197 DPRINTF("%s ",flags[i].name);
198 DPRINTF("\n");
199}
200
201struct IDirectInputAImpl
202{
203 ICOM_VFIELD(IDirectInputA);
204 DWORD ref;
205};
206
207/******************************************************************************
208 * DirectInputCreate32A
209 */
210HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
211{
212 IDirectInputAImpl* This;
213 TRACE("(0x%08lx,%04lx,%p,%p)\n",
214 (DWORD)hinst,dwVersion,ppDI,punkOuter
215 );
216 This = (IDirectInputAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputAImpl));
217 This->ref = 1;
218 ICOM_VTBL(This) = &ddiavt;
219 *ppDI=(IDirectInputA*)This;
220 return 0;
221}
222/******************************************************************************
223 * IDirectInputA_EnumDevices
224 */
225static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
226 LPDIRECTINPUTA iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
227 LPVOID pvRef, DWORD dwFlags
228)
229{
230 ICOM_THIS(IDirectInputAImpl,iface);
231 DIDEVICEINSTANCEA devInstance;
232 int ret;
233
234 TRACE("(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
235
236 devInstance.dwSize = sizeof(DIDEVICEINSTANCEA);
237 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
238 /* Return keyboard */
239 devInstance.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
240 devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
241 devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
242 strcpy(devInstance.tszInstanceName, "Keyboard");
243 strcpy(devInstance.tszProductName, "Wine Keyboard");
244
245 ret = lpCallback(&devInstance, pvRef);
246 TRACE("Keyboard registered\n");
247 if (ret == DIENUM_STOP)
248 return 0;
249 }
250
251 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_MOUSE)) {
252 /* Return mouse */
253 devInstance.guidInstance = GUID_SysMouse;/* DInput's GUID */
254 devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
255 devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
256 strcpy(devInstance.tszInstanceName, "Mouse");
257 strcpy(devInstance.tszProductName, "Wine Mouse");
258
259 ret = lpCallback(&devInstance, pvRef);
260 TRACE("Mouse registered\n");
261 if (ret == DIENUM_STOP)
262 return 0;
263 }
264 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_JOYSTICK)) {
265 /* check whether we have a joystick */
266#ifdef HAVE_LINUX_22_JOYSTICK_API
267 if ( (access(JOYDEV,O_RDONLY)!=-1) ||
268 (errno!=ENODEV && errno!=ENOENT)
269 ) {
270 /* Return joystick */
271 devInstance.guidInstance = GUID_Joystick;
272 devInstance.guidProduct = DInput_Wine_Joystick_GUID;
273 /* we only support traditional joysticks for now */
274 devInstance.dwDevType = DIDEVTYPE_JOYSTICK | DIDEVTYPEJOYSTICK_TRADITIONAL;
275 strcpy(devInstance.tszInstanceName, "Joystick");
276 /* ioctl JSIOCGNAME(len) */
277 strcpy(devInstance.tszProductName, "Wine Joystick");
278
279 ret = lpCallback(&devInstance,pvRef);
280 TRACE("Joystick registered\n");
281 if (ret == DIENUM_STOP)
282 return 0;
283 }
284#endif
285 }
286 return 0;
287}
288
289static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUTA iface)
290{
291 ICOM_THIS(IDirectInputAImpl,iface);
292 return ++(This->ref);
293}
294
295static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
296{
297 ICOM_THIS(IDirectInputAImpl,iface);
298 if (!(--This->ref)) {
299 HeapFree(GetProcessHeap(),0,This);
300 return 0;
301 }
302 return This->ref;
303}
304
305static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
306 LPDIRECTINPUTA iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
307 LPUNKNOWN punk
308) {
309 ICOM_THIS(IDirectInputAImpl,iface);
310 char xbuf[50];
311
312 WINE_StringFromCLSID(rguid,xbuf);
313 FIXME("(this=%p,%s,%p,%p): stub\n",This,xbuf,pdev,punk);
314 if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) || /* Generic Keyboard */
315 (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
316 SysKeyboardAImpl* newDevice;
317 newDevice = (SysKeyboardAImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
318 newDevice->ref = 1;
319 ICOM_VTBL(newDevice) = &SysKeyboardAvt;
320 InitializeCriticalSection(&(newDevice->crit));
321 MakeCriticalSectionGlobal(&(newDevice->crit));
322 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
323 memset(newDevice->keystate,0,256);
324 *pdev=(IDirectInputDeviceA*)newDevice;
325 return DI_OK;
326 }
327 if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) || /* Generic Mouse */
328 (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysMouse)))) { /* Wine Mouse */
329 SysMouseAImpl* newDevice;
330 newDevice = (SysMouseAImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
331 newDevice->ref = 1;
332 ICOM_VTBL(newDevice) = &SysMouseAvt;
333 InitializeCriticalSection(&(newDevice->crit));
334 MakeCriticalSectionGlobal(&(newDevice->crit));
335 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
336 *pdev=(IDirectInputDeviceA*)newDevice;
337 return DI_OK;
338 }
339#ifdef HAVE_LINUX_22_JOYSTICK_API
340 if ((!memcmp(&GUID_Joystick,rguid,sizeof(GUID_Joystick))) ||
341 (!memcmp(&DInput_Wine_Joystick_GUID,rguid,sizeof(GUID_Joystick)))) {
342 JoystickAImpl* newDevice;
343 newDevice = (JoystickAImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickAImpl));
344 newDevice->ref = 1;
345 ICOM_VTBL(newDevice) = &JoystickAvt;
346 newDevice->joyfd = -1;
347 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
348 *pdev=(IDirectInputDeviceA*)newDevice;
349 return DI_OK;
350 }
351#endif
352 return E_FAIL;
353}
354
355static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
356 LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj
357) {
358 ICOM_THIS(IDirectInputAImpl,iface);
359 char xbuf[50];
360
361 WINE_StringFromCLSID(riid,xbuf);
362 TRACE("(this=%p,%s,%p)\n",This,xbuf,ppobj);
363 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
364 IDirectInputA_AddRef(iface);
365 *ppobj = This;
366 return 0;
367 }
368 if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
369 IDirectInputA_AddRef(iface);
370 *ppobj = This;
371 return 0;
372 }
373 return E_FAIL;
374}
375
376static HRESULT WINAPI IDirectInputAImpl_Initialize(
377 LPDIRECTINPUTA iface,HINSTANCE hinst,DWORD x
378) {
379 return DIERR_ALREADYINITIALIZED;
380}
381
382static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
383 REFGUID rguid) {
384 ICOM_THIS(IDirectInputAImpl,iface);
385 char xbuf[50];
386
387 WINE_StringFromCLSID(rguid,xbuf);
388 FIXME("(%p)->(%s): stub\n",This,xbuf);
389
390 return DI_OK;
391}
392
393static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUTA iface,
394 HWND hwndOwner,
395 DWORD dwFlags) {
396 ICOM_THIS(IDirectInputAImpl,iface);
397 FIXME("(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
398
399 return DI_OK;
400}
401
402ICOM_VTABLE(IDirectInputA) ddiavt =
403{
404 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
405 IDirectInputAImpl_QueryInterface,
406 IDirectInputAImpl_AddRef,
407 IDirectInputAImpl_Release,
408 IDirectInputAImpl_CreateDevice,
409 IDirectInputAImpl_EnumDevices,
410 IDirectInputAImpl_GetDeviceStatus,
411 IDirectInputAImpl_RunControlPanel,
412 IDirectInputAImpl_Initialize
413};
414
415/******************************************************************************
416 * IDirectInputDeviceA
417 */
418
419static HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
420 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
421) {
422 /*
423 int i;
424 TRACE(dinput,"(this=%p,%p)\n",This,df);
425
426 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
427 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
428 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
429 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
430 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
431
432 for (i=0;i<df->dwNumObjs;i++) {
433 char xbuf[50];
434
435 if (df->rgodf[i].pguid)
436 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
437 else
438 strcpy(xbuf,"<no guid>");
439 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
440 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
441 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
442 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
443 }
444 */
445 return 0;
446}
447
448static HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
449 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
450) {
451 ICOM_THIS(IDirectInputDevice2AImpl,iface);
452 FIXME("(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
453// if (TRACE_ON(dinput))
454// _dump_cooperativelevel(dwflags);
455 return 0;
456}
457
458static HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
459 LPDIRECTINPUTDEVICE2A iface,HANDLE hnd
460) {
461 ICOM_THIS(IDirectInputDevice2AImpl,iface);
462 FIXME("(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
463 return 0;
464}
465
466static ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE2A iface)
467{
468 ICOM_THIS(IDirectInputDevice2AImpl,iface);
469 This->ref--;
470 if (This->ref)
471 return This->ref;
472 HeapFree(GetProcessHeap(),0,This);
473 return 0;
474}
475
476static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
477 LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
478)
479{
480 ICOM_THIS(SysKeyboardAImpl,iface);
481 char xbuf[50];
482
483 if (HIWORD(rguid))
484 WINE_StringFromCLSID(rguid,xbuf);
485 else
486 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
487 TRACE("DINPUT-SKAI: SetProperty (this=%p,%s,%p)\n",This,xbuf,ph);
488 TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
489 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
490 if (!HIWORD(rguid)) {
491#ifdef __WIN32OS2__
492 if(rguid == DIPROP_BUFFERSIZE) {
493 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
494
495 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
496 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
497 This->queue_pos = 0;
498 This->queue_len = pd->dwData;
499
500 TRACE("(buffersize=%ld)\n",pd->dwData);
501 }
502 else WARN("Unknown type %ld\n",(DWORD)rguid);
503
504#else
505 switch ((DWORD)rguid) {
506 case (DWORD) DIPROP_BUFFERSIZE: {
507 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
508
509 TRACE("(buffersize=%ld)\n",pd->dwData);
510 break;
511 }
512 default:
513 WARN("Unknown type %ld\n",(DWORD)rguid);
514 break;
515 }
516#endif
517 }
518 return 0;
519}
520
521static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
522 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
523)
524{
525#ifdef __WIN32OS2__
526 return OSLibGetDIState(len, ptr) ? DI_OK : E_FAIL;
527#else
528 return KEYBOARD_Driver->pGetDIState(len, ptr)?DI_OK:E_FAIL;
529#endif
530}
531
532static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
533 LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
534 LPDWORD entries,DWORD flags
535)
536{
537 ICOM_THIS(SysKeyboardAImpl,iface);
538 HRESULT ret;
539 int i;
540
541 TRACE("DINPUT-SKAI: GetDeviceData (this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
542 This,dodsize,dod,entries,entries?*entries:0,flags);
543
544 EnterCriticalSection(&(This->crit));
545 TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
546
547 if (flags & DIGDD_PEEK)
548 FIXME("DIGDD_PEEK\n");
549
550 if (dod == NULL) {
551 *entries = This->queue_pos;
552 This->queue_pos = 0;
553 } else {
554 /* Check for buffer overflow */
555 if (This->queue_pos > *entries) {
556 WARN("Buffer overflow not handled properly yet...\n");
557 This->queue_pos = *entries;
558 }
559 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
560 ERR("Wrong structure size !\n");
561 LeaveCriticalSection(&(This->crit));
562 return DIERR_INVALIDPARAM;
563 }
564
565 if (This->queue_pos)
566 TRACE("Application retrieving %d event(s).\n", This->queue_pos);
567
568 /* Copy the buffered data into the application queue */
569 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
570 *entries = This->queue_pos;
571
572 /* Reset the event queue */
573 This->queue_pos = 0;
574 }
575 LeaveCriticalSection(&(This->crit));
576 ret = DI_OK;
577
578 return ret;
579}
580
581#define GEN_KEYEVENT(offset,data,xtime,seq) \
582{ \
583 if (This->queue_pos < This->queue_len) { \
584 This->data_queue[This->queue_pos].dwOfs = offset; \
585 This->data_queue[This->queue_pos].dwData = data; \
586 This->data_queue[This->queue_pos].dwTimeStamp = xtime; \
587 This->data_queue[This->queue_pos].dwSequence = seq; \
588 This->queue_pos++; \
589 } \
590}
591
592LRESULT CALLBACK event_keyHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
593 TRACE("DINPUT-SKAI: keyHandler (msg=%x wParam=0x%X, lParam=0x%lX)\n", msg, wParam, lParam);
594
595 SysKeyboardAImpl* This = (SysKeyboardAImpl*) current_keylock;
596
597 // fake a key up transition for typematic repeat
598 if (msg == WM_KEYDOWN)
599 if (lParam & 0x40000000) { // key was down before
600 dprintf(("Repeat\n"));
601 GEN_KEYEVENT((lParam >> 16) & 0xFF, // scancode
602 0, // key up
603 time(NULL), evsequence++);
604 }
605 GEN_KEYEVENT((lParam >> 16) & 0xFF, // scancode
606 (lParam & 0x80000000) ? 0 : 0x80,
607 time(NULL), evsequence++);
608 return TRUE;
609}
610
611static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
612{
613 ICOM_THIS(SysKeyboardAImpl,iface);
614 TRACE("DINPUT-SKAI: Acquire (this=%p)\n",This);
615
616 if (This->acquired == 0) {
617 /* Store (in a global variable) the current lock */
618 current_keylock = (IDirectInputDeviceA*)This;
619
620 /* register the keyboard event callback */
621 KEYBOARD_Enable(event_keyHandler);
622 This->acquired = 1;
623 }
624 return 0;
625}
626
627static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
628{
629 ICOM_THIS(SysKeyboardAImpl,iface);
630 TRACE("DINPUT-SKAI: Unacquire (this=%p)\n",This);
631
632 /* unregister the callback */
633 KEYBOARD_Enable(NULL);
634
635 /* Free the data queue */
636 if (This->data_queue != NULL)
637 HeapFree(GetProcessHeap(),0,This->data_queue);
638
639 /* No more locks */
640 current_keylock = NULL;
641
642 This->acquired = 0;
643 return 0;
644}
645
646static HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
647 LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
648)
649{
650 ICOM_THIS(IDirectInputDevice2AImpl,iface);
651 char xbuf[50];
652
653 WINE_StringFromCLSID(riid,xbuf);
654 TRACE("(this=%p,%s,%p)\n",This,xbuf,ppobj);
655 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
656 IDirectInputDevice2_AddRef(iface);
657 *ppobj = This;
658 return 0;
659 }
660 if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
661 IDirectInputDevice2_AddRef(iface);
662 *ppobj = This;
663 return 0;
664 }
665 if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
666 IDirectInputDevice2_AddRef(iface);
667 *ppobj = This;
668 return 0;
669 }
670 return E_FAIL;
671}
672
673static ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
674 LPDIRECTINPUTDEVICE2A iface)
675{
676 ICOM_THIS(IDirectInputDevice2AImpl,iface);
677 return ++This->ref;
678}
679
680static HRESULT WINAPI IDirectInputDevice2AImpl_GetCapabilities(
681 LPDIRECTINPUTDEVICE2A iface,
682 LPDIDEVCAPS lpDIDevCaps)
683{
684 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
685 FIXME("stub!\n");
686 return DI_OK;
687}
688
689static HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
690 LPDIRECTINPUTDEVICE2A iface,
691 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
692 LPVOID lpvRef,
693 DWORD dwFlags)
694{
695 FIXME("stub!\n");
696#if 0
697 if (lpCallback)
698 lpCallback(NULL, lpvRef);
699#endif
700 return DI_OK;
701}
702
703static HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
704 LPDIRECTINPUTDEVICE2A iface,
705 REFGUID rguid,
706 LPDIPROPHEADER pdiph)
707{
708 FIXME("stub!\n");
709 return DI_OK;
710}
711
712static HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
713 LPDIRECTINPUTDEVICE2A iface,
714 LPDIDEVICEOBJECTINSTANCEA pdidoi,
715 DWORD dwObj,
716 DWORD dwHow)
717{
718 FIXME("stub!\n");
719 return DI_OK;
720}
721
722static HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
723 LPDIRECTINPUTDEVICE2A iface,
724 LPDIDEVICEINSTANCEA pdidi)
725{
726 FIXME("stub!\n");
727 return DI_OK;
728}
729
730static HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
731 LPDIRECTINPUTDEVICE2A iface,
732 HWND hwndOwner,
733 DWORD dwFlags)
734{
735 FIXME("stub!\n");
736 return DI_OK;
737}
738
739static HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
740 LPDIRECTINPUTDEVICE2A iface,
741 HINSTANCE hinst,
742 DWORD dwVersion,
743 REFGUID rguid)
744{
745 FIXME("stub!\n");
746 return DI_OK;
747}
748
749/******************************************************************************
750 * IDirectInputDevice2A
751 */
752
753static HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
754 LPDIRECTINPUTDEVICE2A iface,
755 REFGUID rguid,
756 LPCDIEFFECT lpeff,
757 LPDIRECTINPUTEFFECT *ppdef,
758 LPUNKNOWN pUnkOuter)
759{
760 FIXME("stub!\n");
761 return DI_OK;
762}
763
764static HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
765 LPDIRECTINPUTDEVICE2A iface,
766 LPDIENUMEFFECTSCALLBACKA lpCallback,
767 LPVOID lpvRef,
768 DWORD dwFlags)
769{
770 FIXME("stub!\n");
771 if (lpCallback)
772 lpCallback(NULL, lpvRef);
773 return DI_OK;
774}
775
776static HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
777 LPDIRECTINPUTDEVICE2A iface,
778 LPDIEFFECTINFOA lpdei,
779 REFGUID rguid)
780{
781 FIXME("stub!\n");
782 return DI_OK;
783}
784
785static HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
786 LPDIRECTINPUTDEVICE2A iface,
787 LPDWORD pdwOut)
788{
789 FIXME("stub!\n");
790 return DI_OK;
791}
792
793static HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
794 LPDIRECTINPUTDEVICE2A iface,
795 DWORD dwFlags)
796{
797 FIXME("stub!\n");
798 return DI_OK;
799}
800
801static HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
802 LPDIRECTINPUTDEVICE2A iface,
803 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
804 LPVOID lpvRef,
805 DWORD dwFlags)
806{
807 FIXME("stub!\n");
808 if (lpCallback)
809 lpCallback(NULL, lpvRef);
810 return DI_OK;
811}
812
813static HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
814 LPDIRECTINPUTDEVICE2A iface,
815 LPDIEFFESCAPE lpDIEEsc)
816{
817 FIXME("stub!\n");
818 return DI_OK;
819}
820
821static HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
822 LPDIRECTINPUTDEVICE2A iface)
823{
824 FIXME("stub!\n");
825 return DI_OK;
826}
827
828static HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
829 LPDIRECTINPUTDEVICE2A iface,
830 DWORD cbObjectData,
831 LPDIDEVICEOBJECTDATA rgdod,
832 LPDWORD pdwInOut,
833 DWORD dwFlags)
834{
835 FIXME("stub!\n");
836 return DI_OK;
837}
838
839/******************************************************************************
840 * SysMouseA (DInput Mouse support)
841 */
842
843/******************************************************************************
844 * Release : release the mouse buffer.
845 */
846static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
847{
848 ICOM_THIS(SysMouseAImpl,iface);
849
850 This->ref--;
851 if (This->ref)
852 return This->ref;
853
854 /* Free the data queue */
855 if (This->data_queue != NULL)
856 HeapFree(GetProcessHeap(),0,This->data_queue);
857
858 /* Install the previous event handler (in case of releasing an aquired
859 mouse device) */
860 if (This->prev_handler != NULL)
861 MOUSE_Enable(This->prev_handler);
862 DeleteCriticalSection(&(This->crit));
863
864 HeapFree(GetProcessHeap(),0,This);
865 return 0;
866}
867
868
869/******************************************************************************
870 * SetCooperativeLevel : store the window in which we will do our
871 * grabbing.
872 */
873static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
874 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
875)
876{
877 ICOM_THIS(SysMouseAImpl,iface);
878
879 TRACE("(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
880
881// if (TRACE_ON(dinput))
882// _dump_cooperativelevel(dwflags);
883
884 /* Store the window which asks for the mouse */
885 This->win = hwnd;
886
887 return 0;
888}
889
890
891/******************************************************************************
892 * SetDataFormat : the application can choose the format of the data
893 * the device driver sends back with GetDeviceState.
894 *
895 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
896 * in absolute and relative mode.
897 */
898static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
899 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
900)
901{
902 ICOM_THIS(SysMouseAImpl,iface);
903 int i;
904
905 TRACE("(this=%p,%p)\n",This,df);
906
907 TRACE("(df.dwSize=%ld)\n",df->dwSize);
908 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
909 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
910 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
911 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
912
913 for (i=0;i<df->dwNumObjs;i++) {
914 char xbuf[50];
915
916 if (df->rgodf[i].pguid)
917 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
918 else
919 strcpy(xbuf,"<no guid>");
920 TRACE("df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
921 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
922 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
923 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
924 }
925
926 /* Check size of data format to prevent crashes if the applications
927 sends a smaller buffer */
928 if (df->dwDataSize != sizeof(struct DIMOUSESTATE)) {
929 FIXME("non-standard mouse configuration not supported yet.");
930 return DIERR_INVALIDPARAM;
931 }
932
933 /* For the moment, ignore these fields and return always as if
934 c_dfDIMouse was passed as format... */
935
936 /* Check if the mouse is in absolute or relative mode */
937 if (df->dwFlags == DIDF_ABSAXIS)
938 This->absolute = 1;
939 else if (df->dwFlags == DIDF_RELAXIS)
940 This->absolute = 0;
941 else
942 ERR("Neither absolute nor relative flag set.");
943
944 This->df = (LPCDIDATAFORMAT)HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
945 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
946 return 0;
947}
948
949#define GEN_EVENT(offset,data,xtime,seq) \
950{ \
951 if (This->queue_pos < This->queue_len) { \
952 This->data_queue[This->queue_pos].dwOfs = offset; \
953 This->data_queue[This->queue_pos].dwData = data; \
954 This->data_queue[This->queue_pos].dwTimeStamp = xtime; \
955 This->data_queue[This->queue_pos].dwSequence = seq; \
956 This->queue_pos++; \
957 } \
958}
959
960
961/* Our private mouse event handler */
962static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
963 DWORD cButtons, DWORD dwExtraInfo )
964{
965 DWORD posX, posY, keyState, xtime, extra;
966 SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
967
968 EnterCriticalSection(&(This->crit));
969 /* Mouse moved -> send event if asked */
970 if (This->hEvent)
971 SetEvent(This->hEvent);
972
973 if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
974 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
975 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
976 keyState = wme->keyState;
977 xtime = wme->time;
978 extra = (DWORD)wme->hWnd;
979
980 assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
981 posX = (dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
982 posY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
983 } else {
984 ERR("Mouse event not supported...\n");
985 LeaveCriticalSection(&(This->crit));
986 return ;
987 }
988
989 TRACE(" %ld %ld ", posX, posY);
990
991 if ( dwFlags & MOUSEEVENTF_MOVE ) {
992 if (This->absolute) {
993 if (posX != This->prevX)
994 GEN_EVENT(DIMOFS_X, posX, xtime, 0);
995 if (posY != This->prevY)
996 GEN_EVENT(DIMOFS_Y, posY, xtime, 0);
997 } else {
998 /* Relative mouse input : the real fun starts here... */
999 if (This->need_warp) {
1000 if (posX != This->prevX)
1001 GEN_EVENT(DIMOFS_X, posX - This->prevX, xtime, evsequence++);
1002 if (posY != This->prevY)
1003 GEN_EVENT(DIMOFS_Y, posY - This->prevY, xtime, evsequence++);
1004 } else {
1005 /* This is the first time the event handler has been called after a
1006 GetData of GetState. */
1007 if (posX != This->win_centerX) {
1008 GEN_EVENT(DIMOFS_X, posX - This->win_centerX, xtime, evsequence++);
1009 This->need_warp = 1;
1010 }
1011
1012 if (posY != This->win_centerY) {
1013 GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, xtime, evsequence++);
1014 This->need_warp = 1;
1015 }
1016 }
1017 }
1018 }
1019 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
1020// if (TRACE_ON(dinput))
1021// DPRINTF(" LD ");
1022
1023 GEN_EVENT(DIMOFS_BUTTON0, 0xFF, xtime, evsequence++);
1024 }
1025 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
1026// if (TRACE_ON(dinput))
1027// DPRINTF(" LU ");
1028
1029 GEN_EVENT(DIMOFS_BUTTON0, 0x00, xtime, evsequence++);
1030 }
1031 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
1032// if (TRACE_ON(dinput))
1033// DPRINTF(" RD ");
1034
1035 GEN_EVENT(DIMOFS_BUTTON1, 0xFF, xtime, evsequence++);
1036 }
1037 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
1038// if (TRACE_ON(dinput))
1039// DPRINTF(" RU ");
1040
1041 GEN_EVENT(DIMOFS_BUTTON1, 0x00, xtime, evsequence++);
1042 }
1043 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
1044// if (TRACE_ON(dinput))
1045// DPRINTF(" MD ");
1046
1047 GEN_EVENT(DIMOFS_BUTTON2, 0xFF, xtime, evsequence++);
1048 }
1049 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
1050// if (TRACE_ON(dinput))
1051// DPRINTF(" MU ");
1052
1053 GEN_EVENT(DIMOFS_BUTTON2, 0x00, xtime, evsequence++);
1054 }
1055// if (TRACE_ON(dinput))
1056// DPRINTF("\n");
1057
1058 This->prevX = posX;
1059 This->prevY = posY;
1060 LeaveCriticalSection(&(This->crit));
1061}
1062
1063
1064/******************************************************************************
1065 * Acquire : gets exclusive control of the mouse
1066 */
1067static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1068{
1069 ICOM_THIS(SysMouseAImpl,iface);
1070 RECT rect;
1071
1072 TRACE("(this=%p)\n",This);
1073
1074 if (This->acquired == 0) {
1075 POINT point;
1076
1077 /* This stores the current mouse handler. */
1078#ifdef __WIN32OS2__
1079 This->prev_handler = (LPMOUSE_EVENT_PROC)-1;
1080#else
1081 This->prev_handler = mouse_event;
1082#endif
1083
1084 /* Store (in a global variable) the current lock */
1085 current_lock = (IDirectInputDevice2A*)This;
1086
1087 /* Install our own mouse event handler */
1088 MOUSE_Enable(dinput_mouse_event);
1089
1090 /* Get the window dimension and find the center */
1091 GetWindowRect(This->win, &rect);
1092 This->win_centerX = (rect.right - rect.left) / 2;
1093 This->win_centerY = (rect.bottom - rect.top ) / 2;
1094
1095 /* Warp the mouse to the center of the window */
1096 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1097 point.x = This->win_centerX;
1098 point.y = This->win_centerY;
1099 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1100#ifdef __WIN32OS2__
1101 OSLibMoveCursor(point.x, point.y);
1102#else
1103 DISPLAY_MoveCursor(point.x, point.y);
1104#endif
1105
1106 This->acquired = 1;
1107 }
1108 return 0;
1109}
1110
1111/******************************************************************************
1112 * Unacquire : frees the mouse
1113 */
1114static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1115{
1116 ICOM_THIS(SysMouseAImpl,iface);
1117
1118 TRACE("(this=%p)\n",This);
1119
1120 /* Reinstall previous mouse event handler */
1121 MOUSE_Enable(This->prev_handler);
1122 This->prev_handler = NULL;
1123
1124 /* No more locks */
1125 current_lock = NULL;
1126
1127 /* Unacquire device */
1128 This->acquired = 0;
1129
1130 return 0;
1131}
1132
1133/******************************************************************************
1134 * GetDeviceState : returns the "state" of the mouse.
1135 *
1136 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
1137 * supported.
1138 */
1139static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
1140 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1141) {
1142 ICOM_THIS(SysMouseAImpl,iface);
1143 DWORD rx, ry, state;
1144 struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
1145
1146 TRACE("(this=%p,0x%08lx,%p): \n",This,len,ptr);
1147
1148 /* Check if the buffer is big enough */
1149 if (len < sizeof(struct DIMOUSESTATE)) {
1150 FIXME("unsupported state structure.");
1151 return DIERR_INVALIDPARAM;
1152 }
1153
1154 /* Get the mouse position */
1155#ifdef __WIN32OS2__
1156 OSLibQueryMousePos(&rx, &ry, &state);
1157#else
1158 EVENT_QueryPointer(&rx, &ry, &state);
1159#endif
1160 TRACE("(X:%ld - Y:%ld)\n", rx, ry);
1161
1162 /* Fill the mouse state structure */
1163 if (This->absolute) {
1164 mstate->lX = rx;
1165 mstate->lY = ry;
1166 } else {
1167 mstate->lX = rx - This->win_centerX;
1168 mstate->lY = ry - This->win_centerY;
1169
1170 if ((mstate->lX != 0) || (mstate->lY != 0))
1171 This->need_warp = 1;
1172 }
1173 mstate->lZ = 0;
1174 mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00);
1175 mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00);
1176 mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00);
1177 mstate->rgbButtons[3] = 0x00;
1178
1179 /* Check if we need to do a mouse warping */
1180 if (This->need_warp) {
1181 POINT point;
1182
1183 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1184 point.x = This->win_centerX;
1185 point.y = This->win_centerY;
1186 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1187#ifdef __WIN32OS2__
1188 OSLibMoveCursor(point.x, point.y);
1189#else
1190 DISPLAY_MoveCursor(point.x, point.y);
1191#endif
1192 This->need_warp = 0;
1193 }
1194
1195 TRACE("(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
1196 mstate->lX, mstate->lY,
1197 mstate->rgbButtons[0], mstate->rgbButtons[2], mstate->rgbButtons[1]);
1198
1199 return 0;
1200}
1201
1202/******************************************************************************
1203 * GetDeviceState : gets buffered input data.
1204 */
1205static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1206 DWORD dodsize,
1207 LPDIDEVICEOBJECTDATA dod,
1208 LPDWORD entries,
1209 DWORD flags
1210) {
1211 ICOM_THIS(SysMouseAImpl,iface);
1212
1213 EnterCriticalSection(&(This->crit));
1214 TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
1215
1216 if (flags & DIGDD_PEEK)
1217 FIXME("DIGDD_PEEK\n");
1218
1219 if (dod == NULL) {
1220 *entries = This->queue_pos;
1221 This->queue_pos = 0;
1222 } else {
1223 /* Check for buffer overflow */
1224 if (This->queue_pos > *entries) {
1225 WARN("Buffer overflow not handled properly yet...\n");
1226 This->queue_pos = *entries;
1227 }
1228 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1229 ERR("Wrong structure size !\n");
1230 LeaveCriticalSection(&(This->crit));
1231 return DIERR_INVALIDPARAM;
1232 }
1233
1234 if (This->queue_pos)
1235 TRACE("Application retrieving %d event(s).\n", This->queue_pos);
1236
1237 /* Copy the buffered data into the application queue */
1238 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1239 *entries = This->queue_pos;
1240
1241 /* Reset the event queue */
1242 This->queue_pos = 0;
1243 }
1244 LeaveCriticalSection(&(This->crit));
1245
1246#if 0 /* FIXME: seems to create motion events, which fire back at us. */
1247 /* Check if we need to do a mouse warping */
1248 if (This->need_warp) {
1249 POINT point;
1250
1251 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1252 point.x = This->win_centerX;
1253 point.y = This->win_centerY;
1254 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1255
1256#ifdef __WIN32OS2__
1257 OSLibMoveCursor(point.x, point.y);
1258#else
1259 DISPLAY_MoveCursor(point.x, point.y);
1260#endif
1261
1262 This->need_warp = 0;
1263 }
1264#endif
1265 return 0;
1266}
1267
1268/******************************************************************************
1269 * SetProperty : change input device properties
1270 */
1271static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1272 REFGUID rguid,
1273 LPCDIPROPHEADER ph)
1274{
1275 ICOM_THIS(SysMouseAImpl,iface);
1276 char xbuf[50];
1277
1278 if (HIWORD(rguid))
1279 WINE_StringFromCLSID(rguid,xbuf);
1280 else
1281 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1282
1283 TRACE("(this=%p,%s,%p)\n",This,xbuf,ph);
1284
1285 if (!HIWORD(rguid)) {
1286#ifdef __WIN32OS2__
1287 if(rguid == DIPROP_BUFFERSIZE) {
1288 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1289
1290 TRACE("buffersize = %ld\n",pd->dwData);
1291
1292 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1293 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1294 This->queue_pos = 0;
1295 This->queue_len = pd->dwData;
1296 }
1297 else {
1298 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1299 }
1300#else
1301 switch ((DWORD)rguid) {
1302 case (DWORD) DIPROP_BUFFERSIZE: {
1303 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1304
1305 TRACE("buffersize = %ld\n",pd->dwData);
1306
1307 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1308 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1309 This->queue_pos = 0;
1310 This->queue_len = pd->dwData;
1311 break;
1312 }
1313 default:
1314 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1315 break;
1316 }
1317#endif
1318 }
1319
1320 return 0;
1321}
1322
1323/******************************************************************************
1324 * SetEventNotification : specifies event to be sent on state change
1325 */
1326static HRESULT WINAPI SysMouseAImpl_SetEventNotification(LPDIRECTINPUTDEVICE2A iface,
1327 HANDLE hnd) {
1328 ICOM_THIS(SysMouseAImpl,iface);
1329
1330 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1331
1332 This->hEvent = hnd;
1333
1334 return DI_OK;
1335}
1336
1337#ifdef HAVE_LINUX_22_JOYSTICK_API
1338/******************************************************************************
1339 * Joystick
1340 */
1341static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
1342{
1343 ICOM_THIS(JoystickAImpl,iface);
1344
1345 This->ref--;
1346 if (This->ref)
1347 return This->ref;
1348 HeapFree(GetProcessHeap(),0,This);
1349 return 0;
1350}
1351
1352/******************************************************************************
1353 * SetDataFormat : the application can choose the format of the data
1354 * the device driver sends back with GetDeviceState.
1355 */
1356static HRESULT WINAPI JoystickAImpl_SetDataFormat(
1357 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
1358)
1359{
1360 ICOM_THIS(JoystickAImpl,iface);
1361 int i;
1362
1363 TRACE("(this=%p,%p)\n",This,df);
1364
1365 TRACE("(df.dwSize=%ld)\n",df->dwSize);
1366 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
1367 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
1368 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
1369 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
1370
1371 for (i=0;i<df->dwNumObjs;i++) {
1372 char xbuf[50];
1373
1374 if (df->rgodf[i].pguid)
1375 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
1376 else
1377 strcpy(xbuf,"<no guid>");
1378 TRACE("df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
1379 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
1380 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
1381 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
1382 }
1383 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1384 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1385 return 0;
1386}
1387
1388/******************************************************************************
1389 * Acquire : gets exclusive control of the joystick
1390 */
1391static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1392{
1393 ICOM_THIS(JoystickAImpl,iface);
1394
1395 TRACE("(this=%p)\n",This);
1396 if (This->joyfd!=-1)
1397 return 0;
1398 This->joyfd=open(JOYDEV,O_RDONLY);
1399 if (This->joyfd==-1)
1400 return DIERR_NOTFOUND;
1401 return 0;
1402}
1403
1404/******************************************************************************
1405 * Unacquire : frees the joystick
1406 */
1407static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1408{
1409 ICOM_THIS(JoystickAImpl,iface);
1410
1411 TRACE("(this=%p)\n",This);
1412 if (This->joyfd!=-1) {
1413 close(This->joyfd);
1414 This->joyfd = -1;
1415 }
1416 return 0;
1417}
1418
1419#define map_axis(val) ((val+32768)*(This->lMax-This->lMin)/65536+This->lMin)
1420
1421static void joy_polldev(JoystickAImpl *This) {
1422 struct timeval tv;
1423 fd_set readfds;
1424 struct js_event jse;
1425
1426 if (This->joyfd==-1)
1427 return;
1428 while (1) {
1429 memset(&tv,0,sizeof(tv));
1430 FD_ZERO(&readfds);FD_SET(This->joyfd,&readfds);
1431 if (1>select(This->joyfd+1,&readfds,NULL,NULL,&tv))
1432 return;
1433 /* we have one event, so we can read */
1434 if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
1435 return;
1436 }
1437 TRACE("js_event: type 0x%x, number %d, value %d\n",jse.type,jse.number,jse.value);
1438 if (jse.type & JS_EVENT_BUTTON) {
1439 GEN_EVENT(DIJOFS_BUTTON(jse.number),jse.value?0x80:0x00,jse.time,evsequence++);
1440 This->js.rgbButtons[jse.number] = jse.value?0x80:0x00;
1441 }
1442 if (jse.type & JS_EVENT_AXIS) {
1443 switch (jse.number) {
1444 case 0:
1445 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1446 This->js.lX = map_axis(jse.value);
1447 break;
1448 case 1:
1449 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1450 This->js.lY = map_axis(jse.value);
1451 break;
1452 case 2:
1453 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1454 This->js.lZ = map_axis(jse.value);
1455 break;
1456 default:
1457 FIXME("more then 3 axes (%d) not handled!\n",jse.number);
1458 break;
1459 }
1460 }
1461 }
1462}
1463
1464/******************************************************************************
1465 * GetDeviceState : returns the "state" of the joystick.
1466 *
1467 */
1468static HRESULT WINAPI JoystickAImpl_GetDeviceState(
1469 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1470) {
1471 ICOM_THIS(JoystickAImpl,iface);
1472
1473 joy_polldev(This);
1474 TRACE("(this=%p,0x%08lx,%p)\n",This,len,ptr);
1475 if (len != sizeof(DIJOYSTATE)) {
1476 FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len);
1477 }
1478 memcpy(ptr,&(This->js),len);
1479 This->queue_pos = 0;
1480 return 0;
1481}
1482
1483/******************************************************************************
1484 * GetDeviceState : gets buffered input data.
1485 */
1486static HRESULT WINAPI JoystickAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1487 DWORD dodsize,
1488 LPDIDEVICEOBJECTDATA dod,
1489 LPDWORD entries,
1490 DWORD flags
1491) {
1492 ICOM_THIS(JoystickAImpl,iface);
1493
1494 FIXME("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx),STUB!\n",This,dodsize,*entries,flags);
1495
1496 joy_polldev(This);
1497 if (flags & DIGDD_PEEK)
1498 FIXME("DIGDD_PEEK\n");
1499
1500 if (dod == NULL) {
1501 } else {
1502 }
1503 return 0;
1504}
1505
1506/******************************************************************************
1507 * SetProperty : change input device properties
1508 */
1509static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1510 REFGUID rguid,
1511 LPCDIPROPHEADER ph)
1512{
1513 ICOM_THIS(JoystickAImpl,iface);
1514 char xbuf[50];
1515
1516 if (HIWORD(rguid))
1517 WINE_StringFromCLSID(rguid,xbuf);
1518 else
1519 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1520
1521 FIXME("(this=%p,%s,%p)\n",This,xbuf,ph);
1522 FIXME("ph.dwSize = %ld, ph.dwHeaderSize =%ld, ph.dwObj = %ld, ph.dwHow= %ld\n",ph->dwSize, ph->dwHeaderSize,ph->dwObj,ph->dwHow);
1523
1524 if (!HIWORD(rguid)) {
1525 switch ((DWORD)rguid) {
1526 case (DWORD) DIPROP_BUFFERSIZE: {
1527 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1528
1529 FIXME("buffersize = %ld\n",pd->dwData);
1530 break;
1531 }
1532 case (DWORD)DIPROP_RANGE: {
1533 LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph;
1534
1535 FIXME("proprange(%ld,%ld)\n",pr->lMin,pr->lMax);
1536 This->lMin = pr->lMin;
1537 This->lMax = pr->lMax;
1538 break;
1539 }
1540 case (DWORD)DIPROP_DEADZONE: {
1541 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1542
1543 FIXME("deadzone(%ld)\n",pd->dwData);
1544 This->deadzone = pd->dwData;
1545 break;
1546 }
1547 default:
1548 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1549 break;
1550 }
1551 }
1552 return 0;
1553}
1554
1555/******************************************************************************
1556 * SetEventNotification : specifies event to be sent on state change
1557 */
1558static HRESULT WINAPI JoystickAImpl_SetEventNotification(
1559 LPDIRECTINPUTDEVICE2A iface, HANDLE hnd
1560) {
1561 ICOM_THIS(JoystickAImpl,iface);
1562
1563 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1564 This->hEvent = hnd;
1565 return DI_OK;
1566}
1567
1568static HRESULT WINAPI JoystickAImpl_GetCapabilities(
1569 LPDIRECTINPUTDEVICE2A iface,
1570 LPDIDEVCAPS lpDIDevCaps)
1571{
1572 ICOM_THIS(JoystickAImpl,iface);
1573 BYTE axes,buttons;
1574 int xfd = This->joyfd;
1575
1576 TRACE("%p->(%p)\n",iface,lpDIDevCaps);
1577 if (xfd==-1)
1578 xfd = open(JOYDEV,O_RDONLY);
1579 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
1580 lpDIDevCaps->dwDevType = DIDEVTYPE_JOYSTICK;
1581#ifdef JSIOCGAXES
1582 if (-1==ioctl(xfd,JSIOCGAXES,&axes))
1583 axes = 2;
1584 lpDIDevCaps->dwAxes = axes;
1585#endif
1586#ifdef JSIOCGBUTTONS
1587 if (-1==ioctl(xfd,JSIOCGAXES,&buttons))
1588 buttons = 2;
1589 lpDIDevCaps->dwButtons = buttons;
1590#endif
1591 if (xfd!=This->joyfd)
1592 close(xfd);
1593 return DI_OK;
1594}
1595static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE2A iface) {
1596 ICOM_THIS(JoystickAImpl,iface);
1597 TRACE("(),stub!\n");
1598
1599 joy_polldev(This);
1600 return DI_OK;
1601}
1602#endif
1603
1604/****************************************************************************/
1605/****************************************************************************/
1606
1607ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt =
1608{
1609 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1610 IDirectInputDevice2AImpl_QueryInterface,
1611 IDirectInputDevice2AImpl_AddRef,
1612 IDirectInputDevice2AImpl_Release,
1613 IDirectInputDevice2AImpl_GetCapabilities,
1614 IDirectInputDevice2AImpl_EnumObjects,
1615 IDirectInputDevice2AImpl_GetProperty,
1616 SysKeyboardAImpl_SetProperty,
1617 SysKeyboardAImpl_Acquire,
1618 SysKeyboardAImpl_Unacquire,
1619 SysKeyboardAImpl_GetDeviceState,
1620 SysKeyboardAImpl_GetDeviceData,
1621 IDirectInputDevice2AImpl_SetDataFormat,
1622 IDirectInputDevice2AImpl_SetEventNotification,
1623 IDirectInputDevice2AImpl_SetCooperativeLevel,
1624 IDirectInputDevice2AImpl_GetObjectInfo,
1625 IDirectInputDevice2AImpl_GetDeviceInfo,
1626 IDirectInputDevice2AImpl_RunControlPanel,
1627 IDirectInputDevice2AImpl_Initialize,
1628 IDirectInputDevice2AImpl_CreateEffect,
1629 IDirectInputDevice2AImpl_EnumEffects,
1630 IDirectInputDevice2AImpl_GetEffectInfo,
1631 IDirectInputDevice2AImpl_GetForceFeedbackState,
1632 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1633 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1634 IDirectInputDevice2AImpl_Escape,
1635 IDirectInputDevice2AImpl_Poll,
1636 IDirectInputDevice2AImpl_SendDeviceData,
1637};
1638
1639ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt =
1640{
1641 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1642 IDirectInputDevice2AImpl_QueryInterface,
1643 IDirectInputDevice2AImpl_AddRef,
1644 SysMouseAImpl_Release,
1645 IDirectInputDevice2AImpl_GetCapabilities,
1646 IDirectInputDevice2AImpl_EnumObjects,
1647 IDirectInputDevice2AImpl_GetProperty,
1648 SysMouseAImpl_SetProperty,
1649 SysMouseAImpl_Acquire,
1650 SysMouseAImpl_Unacquire,
1651 SysMouseAImpl_GetDeviceState,
1652 SysMouseAImpl_GetDeviceData,
1653 SysMouseAImpl_SetDataFormat,
1654 SysMouseAImpl_SetEventNotification,
1655 SysMouseAImpl_SetCooperativeLevel,
1656 IDirectInputDevice2AImpl_GetObjectInfo,
1657 IDirectInputDevice2AImpl_GetDeviceInfo,
1658 IDirectInputDevice2AImpl_RunControlPanel,
1659 IDirectInputDevice2AImpl_Initialize,
1660 IDirectInputDevice2AImpl_CreateEffect,
1661 IDirectInputDevice2AImpl_EnumEffects,
1662 IDirectInputDevice2AImpl_GetEffectInfo,
1663 IDirectInputDevice2AImpl_GetForceFeedbackState,
1664 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1665 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1666 IDirectInputDevice2AImpl_Escape,
1667 IDirectInputDevice2AImpl_Poll,
1668 IDirectInputDevice2AImpl_SendDeviceData,
1669};
1670
1671#ifdef HAVE_LINUX_22_JOYSTICK_API
1672ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt =
1673{
1674 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1675 IDirectInputDevice2AImpl_QueryInterface,
1676 IDirectInputDevice2AImpl_AddRef,
1677 JoystickAImpl_Release,
1678 JoystickAImpl_GetCapabilities,
1679 IDirectInputDevice2AImpl_EnumObjects,
1680 IDirectInputDevice2AImpl_GetProperty,
1681 JoystickAImpl_SetProperty,
1682 JoystickAImpl_Acquire,
1683 JoystickAImpl_Unacquire,
1684 JoystickAImpl_GetDeviceState,
1685 JoystickAImpl_GetDeviceData,
1686 JoystickAImpl_SetDataFormat,
1687 JoystickAImpl_SetEventNotification,
1688 IDirectInputDevice2AImpl_SetCooperativeLevel,
1689 IDirectInputDevice2AImpl_GetObjectInfo,
1690 IDirectInputDevice2AImpl_GetDeviceInfo,
1691 IDirectInputDevice2AImpl_RunControlPanel,
1692 IDirectInputDevice2AImpl_Initialize,
1693 IDirectInputDevice2AImpl_CreateEffect,
1694 IDirectInputDevice2AImpl_EnumEffects,
1695 IDirectInputDevice2AImpl_GetEffectInfo,
1696 IDirectInputDevice2AImpl_GetForceFeedbackState,
1697 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1698 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1699 IDirectInputDevice2AImpl_Escape,
1700 JoystickAImpl_Poll,
1701 IDirectInputDevice2AImpl_SendDeviceData,
1702};
1703#endif
Note: See TracBrowser for help on using the repository browser.