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

Last change on this file since 3163 was 3163, checked in by mike, 25 years ago

Fixed Dinput

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