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

Last change on this file since 3502 was 3502, checked in by sandervl, 25 years ago

cooperative keyboard capture fix

File size: 54.0 KB
Line 
1/* $Id: dinput.cpp,v 1.6 2000-05-09 18:58:40 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 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 BOOL 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 if(This->win && This->win != wme->hWnd) {
1016 return FALSE;
1017 }
1018
1019 assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
1020 posX = (dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
1021 posY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
1022 } else {
1023 ERR("Mouse event not supported...\n");
1024 LeaveCriticalSection(&(This->crit));
1025 return FALSE;
1026 }
1027
1028 TRACE("DINPUT-SMAI: event %x %ld, %ld", dwFlags, posX, posY);
1029
1030 if ( dwFlags & MOUSEEVENTF_MOVE ) {
1031 if (This->absolute) {
1032 if (posX != This->prevX)
1033 GEN_EVENT(DIMOFS_X, posX, xtime, 0);
1034 if (posY != This->prevY)
1035 GEN_EVENT(DIMOFS_Y, posY, xtime, 0);
1036 } else {
1037 /* Relative mouse input : the real fun starts here... */
1038 if (This->need_warp) {
1039 if (posX != This->prevX)
1040 GEN_EVENT(DIMOFS_X, posX - This->prevX, xtime, evsequence++);
1041 if (posY != This->prevY)
1042 GEN_EVENT(DIMOFS_Y, posY - This->prevY, xtime, evsequence++);
1043 } else {
1044 /* This is the first time the event handler has been called after a
1045 GetData of GetState. */
1046 if (posX != This->win_centerX) {
1047 GEN_EVENT(DIMOFS_X, posX - This->win_centerX, xtime, evsequence++);
1048 This->need_warp = 1;
1049 }
1050
1051 if (posY != This->win_centerY) {
1052 GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, xtime, evsequence++);
1053 This->need_warp = 1;
1054 }
1055 }
1056 }
1057 }
1058 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
1059// if (TRACE_ON(dinput))
1060// DPRINTF(" LD ");
1061
1062 GEN_EVENT(DIMOFS_BUTTON0, 0xFF, xtime, evsequence++);
1063 }
1064 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
1065// if (TRACE_ON(dinput))
1066// DPRINTF(" LU ");
1067
1068 GEN_EVENT(DIMOFS_BUTTON0, 0x00, xtime, evsequence++);
1069 }
1070 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
1071// if (TRACE_ON(dinput))
1072// DPRINTF(" RD ");
1073
1074 GEN_EVENT(DIMOFS_BUTTON1, 0xFF, xtime, evsequence++);
1075 }
1076 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
1077// if (TRACE_ON(dinput))
1078// DPRINTF(" RU ");
1079
1080 GEN_EVENT(DIMOFS_BUTTON1, 0x00, xtime, evsequence++);
1081 }
1082 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
1083// if (TRACE_ON(dinput))
1084// DPRINTF(" MD ");
1085
1086 GEN_EVENT(DIMOFS_BUTTON2, 0xFF, xtime, evsequence++);
1087 }
1088 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
1089// if (TRACE_ON(dinput))
1090// DPRINTF(" MU ");
1091
1092 GEN_EVENT(DIMOFS_BUTTON2, 0x00, xtime, evsequence++);
1093 }
1094// if (TRACE_ON(dinput))
1095// DPRINTF("\n");
1096
1097 This->prevX = posX;
1098 This->prevY = posY;
1099 LeaveCriticalSection(&(This->crit));
1100
1101 return TRUE;
1102}
1103
1104
1105/******************************************************************************
1106 * Acquire : gets exclusive control of the mouse
1107 */
1108static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1109{
1110 ICOM_THIS(SysMouseAImpl,iface);
1111 RECT rect;
1112
1113 TRACE("SysMouseAImpl_Acquire: (this=%p)\n",This);
1114
1115 if (This->acquired == 0) {
1116 POINT point;
1117
1118 /* This stores the current mouse handler. */
1119#ifdef __WIN32OS2__
1120 This->prev_handler = (LPMOUSE_EVENT_PROC)-1;
1121#else
1122 This->prev_handler = mouse_event;
1123#endif
1124
1125 /* Store (in a global variable) the current lock */
1126 current_lock = (IDirectInputDevice2A*)This;
1127
1128 /* Install our own mouse event handler */
1129 MOUSE_Enable(dinput_mouse_event);
1130
1131 /* Get the window dimension and find the center */
1132 GetWindowRect(This->win, &rect);
1133 This->win_centerX = (rect.right - rect.left) / 2;
1134 This->win_centerY = (rect.bottom - rect.top ) / 2;
1135
1136 /* Warp the mouse to the center of the window */
1137 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1138 point.x = This->win_centerX;
1139 point.y = This->win_centerY;
1140 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1141#ifdef __WIN32OS2__
1142 OSLibMoveCursor(point.x, point.y);
1143#else
1144 DISPLAY_MoveCursor(point.x, point.y);
1145#endif
1146
1147 This->acquired = 1;
1148 }
1149 return 0;
1150}
1151
1152/******************************************************************************
1153 * Unacquire : frees the mouse
1154 */
1155static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1156{
1157 ICOM_THIS(SysMouseAImpl,iface);
1158
1159 TRACE("SysMouseAImpl_Unacquire: (this=%p)\n",This);
1160
1161 /* Reinstall previous mouse event handler */
1162 MOUSE_Enable(This->prev_handler);
1163 This->prev_handler = NULL;
1164
1165 /* No more locks */
1166 current_lock = NULL;
1167
1168 /* Unacquire device */
1169 This->acquired = 0;
1170
1171 return 0;
1172}
1173
1174/******************************************************************************
1175 * GetDeviceState : returns the "state" of the mouse.
1176 *
1177 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
1178 * supported.
1179 */
1180static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
1181 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1182) {
1183 ICOM_THIS(SysMouseAImpl,iface);
1184 DWORD rx, ry, state;
1185 struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
1186
1187 TRACE("(this=%p,0x%08lx,%p): \n",This,len,ptr);
1188
1189 /* Check if the buffer is big enough */
1190 if (len < sizeof(struct DIMOUSESTATE)) {
1191 FIXME("unsupported state structure.");
1192 return DIERR_INVALIDPARAM;
1193 }
1194
1195 /* Get the mouse position */
1196#ifdef __WIN32OS2__
1197 OSLibQueryMousePos(&rx, &ry, &state);
1198#else
1199 EVENT_QueryPointer(&rx, &ry, &state);
1200#endif
1201 TRACE("(X:%ld - Y:%ld)\n", rx, ry);
1202
1203 /* Fill the mouse state structure */
1204 if (This->absolute) {
1205 mstate->lX = rx;
1206 mstate->lY = ry;
1207 } else {
1208 mstate->lX = rx - This->win_centerX;
1209 mstate->lY = ry - This->win_centerY;
1210
1211 if ((mstate->lX != 0) || (mstate->lY != 0))
1212 This->need_warp = 1;
1213 }
1214 mstate->lZ = 0;
1215 mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00);
1216 mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00);
1217 mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00);
1218 mstate->rgbButtons[3] = 0x00;
1219
1220 /* Check if we need to do a mouse warping */
1221 if (This->need_warp) {
1222 POINT point;
1223
1224 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1225 point.x = This->win_centerX;
1226 point.y = This->win_centerY;
1227 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1228#ifdef __WIN32OS2__
1229 OSLibMoveCursor(point.x, point.y);
1230#else
1231 DISPLAY_MoveCursor(point.x, point.y);
1232#endif
1233 This->need_warp = 0;
1234 }
1235
1236 TRACE("(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
1237 mstate->lX, mstate->lY,
1238 mstate->rgbButtons[0], mstate->rgbButtons[2], mstate->rgbButtons[1]);
1239
1240 return 0;
1241}
1242
1243/******************************************************************************
1244 * GetDeviceState : gets buffered input data.
1245 */
1246static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1247 DWORD dodsize,
1248 LPDIDEVICEOBJECTDATA dod,
1249 LPDWORD entries,
1250 DWORD flags
1251) {
1252 ICOM_THIS(SysMouseAImpl,iface);
1253
1254 EnterCriticalSection(&(This->crit));
1255 TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
1256
1257 if (flags & DIGDD_PEEK)
1258 FIXME("DIGDD_PEEK\n");
1259
1260 if (dod == NULL) {
1261 *entries = This->queue_pos;
1262 This->queue_pos = 0;
1263 } else {
1264 /* Check for buffer overflow */
1265 if (This->queue_pos > *entries) {
1266 WARN("Buffer overflow not handled properly yet...\n");
1267 This->queue_pos = *entries;
1268 }
1269 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1270 ERR("Wrong structure size !\n");
1271 LeaveCriticalSection(&(This->crit));
1272 return DIERR_INVALIDPARAM;
1273 }
1274
1275 if (This->queue_pos)
1276 TRACE("Application retrieving %d event(s).\n", This->queue_pos);
1277
1278 /* Copy the buffered data into the application queue */
1279 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1280 *entries = This->queue_pos;
1281
1282 /* Reset the event queue */
1283 This->queue_pos = 0;
1284 }
1285 LeaveCriticalSection(&(This->crit));
1286
1287#if 0 /* FIXME: seems to create motion events, which fire back at us. */
1288 /* Check if we need to do a mouse warping */
1289 if (This->need_warp) {
1290 POINT point;
1291
1292 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1293 point.x = This->win_centerX;
1294 point.y = This->win_centerY;
1295 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1296
1297#ifdef __WIN32OS2__
1298 OSLibMoveCursor(point.x, point.y);
1299#else
1300 DISPLAY_MoveCursor(point.x, point.y);
1301#endif
1302
1303 This->need_warp = 0;
1304 }
1305#endif
1306 return 0;
1307}
1308
1309/******************************************************************************
1310 * SetProperty : change input device properties
1311 */
1312static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1313 REFGUID rguid,
1314 LPCDIPROPHEADER ph)
1315{
1316 ICOM_THIS(SysMouseAImpl,iface);
1317 char xbuf[50];
1318
1319 if (HIWORD(rguid))
1320 WINE_StringFromCLSID(rguid,xbuf);
1321 else
1322 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1323
1324 TRACE("(this=%p,%s,%p)\n",This,xbuf,ph);
1325
1326 if (!HIWORD(rguid)) {
1327#ifdef __WIN32OS2__
1328 if(rguid == DIPROP_BUFFERSIZE) {
1329 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1330
1331 TRACE("buffersize = %ld\n",pd->dwData);
1332
1333 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1334 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1335 This->queue_pos = 0;
1336 This->queue_len = pd->dwData;
1337 }
1338 else {
1339 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1340 }
1341#else
1342 switch ((DWORD)rguid) {
1343 case (DWORD) DIPROP_BUFFERSIZE: {
1344 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1345
1346 TRACE("buffersize = %ld\n",pd->dwData);
1347
1348 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1349 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1350 This->queue_pos = 0;
1351 This->queue_len = pd->dwData;
1352 break;
1353 }
1354 default:
1355 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1356 break;
1357 }
1358#endif
1359 }
1360
1361 return 0;
1362}
1363
1364/******************************************************************************
1365 * SetEventNotification : specifies event to be sent on state change
1366 */
1367static HRESULT WINAPI SysMouseAImpl_SetEventNotification(LPDIRECTINPUTDEVICE2A iface,
1368 HANDLE hnd) {
1369 ICOM_THIS(SysMouseAImpl,iface);
1370
1371 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1372
1373 This->hEvent = hnd;
1374
1375 return DI_OK;
1376}
1377
1378#ifdef HAVE_LINUX_22_JOYSTICK_API
1379/******************************************************************************
1380 * Joystick
1381 */
1382static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
1383{
1384 ICOM_THIS(JoystickAImpl,iface);
1385
1386 This->ref--;
1387 if (This->ref)
1388 return This->ref;
1389 HeapFree(GetProcessHeap(),0,This);
1390 return 0;
1391}
1392
1393/******************************************************************************
1394 * SetDataFormat : the application can choose the format of the data
1395 * the device driver sends back with GetDeviceState.
1396 */
1397static HRESULT WINAPI JoystickAImpl_SetDataFormat(
1398 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
1399)
1400{
1401 ICOM_THIS(JoystickAImpl,iface);
1402 int i;
1403
1404 TRACE("(this=%p,%p)\n",This,df);
1405
1406 TRACE("(df.dwSize=%ld)\n",df->dwSize);
1407 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
1408 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
1409 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
1410 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
1411
1412 for (i=0;i<df->dwNumObjs;i++) {
1413 char xbuf[50];
1414
1415 if (df->rgodf[i].pguid)
1416 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
1417 else
1418 strcpy(xbuf,"<no guid>");
1419 TRACE("df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
1420 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
1421 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
1422 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
1423 }
1424 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1425 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1426 return 0;
1427}
1428
1429/******************************************************************************
1430 * Acquire : gets exclusive control of the joystick
1431 */
1432static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1433{
1434 ICOM_THIS(JoystickAImpl,iface);
1435
1436 TRACE("(this=%p)\n",This);
1437 if (This->joyfd!=-1)
1438 return 0;
1439 This->joyfd=open(JOYDEV,O_RDONLY);
1440 if (This->joyfd==-1)
1441 return DIERR_NOTFOUND;
1442 return 0;
1443}
1444
1445/******************************************************************************
1446 * Unacquire : frees the joystick
1447 */
1448static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1449{
1450 ICOM_THIS(JoystickAImpl,iface);
1451
1452 TRACE("(this=%p)\n",This);
1453 if (This->joyfd!=-1) {
1454 close(This->joyfd);
1455 This->joyfd = -1;
1456 }
1457 return 0;
1458}
1459
1460#define map_axis(val) ((val+32768)*(This->lMax-This->lMin)/65536+This->lMin)
1461
1462static void joy_polldev(JoystickAImpl *This) {
1463 struct timeval tv;
1464 fd_set readfds;
1465 struct js_event jse;
1466
1467 if (This->joyfd==-1)
1468 return;
1469 while (1) {
1470 memset(&tv,0,sizeof(tv));
1471 FD_ZERO(&readfds);FD_SET(This->joyfd,&readfds);
1472 if (1>select(This->joyfd+1,&readfds,NULL,NULL,&tv))
1473 return;
1474 /* we have one event, so we can read */
1475 if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
1476 return;
1477 }
1478 TRACE("js_event: type 0x%x, number %d, value %d\n",jse.type,jse.number,jse.value);
1479 if (jse.type & JS_EVENT_BUTTON) {
1480 GEN_EVENT(DIJOFS_BUTTON(jse.number),jse.value?0x80:0x00,jse.time,evsequence++);
1481 This->js.rgbButtons[jse.number] = jse.value?0x80:0x00;
1482 }
1483 if (jse.type & JS_EVENT_AXIS) {
1484 switch (jse.number) {
1485 case 0:
1486 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1487 This->js.lX = map_axis(jse.value);
1488 break;
1489 case 1:
1490 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1491 This->js.lY = map_axis(jse.value);
1492 break;
1493 case 2:
1494 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1495 This->js.lZ = map_axis(jse.value);
1496 break;
1497 default:
1498 FIXME("more then 3 axes (%d) not handled!\n",jse.number);
1499 break;
1500 }
1501 }
1502 }
1503}
1504
1505/******************************************************************************
1506 * GetDeviceState : returns the "state" of the joystick.
1507 *
1508 */
1509static HRESULT WINAPI JoystickAImpl_GetDeviceState(
1510 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1511) {
1512 ICOM_THIS(JoystickAImpl,iface);
1513
1514 joy_polldev(This);
1515 TRACE("(this=%p,0x%08lx,%p)\n",This,len,ptr);
1516 if (len != sizeof(DIJOYSTATE)) {
1517 FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len);
1518 }
1519 memcpy(ptr,&(This->js),len);
1520 This->queue_pos = 0;
1521 return 0;
1522}
1523
1524/******************************************************************************
1525 * GetDeviceState : gets buffered input data.
1526 */
1527static HRESULT WINAPI JoystickAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1528 DWORD dodsize,
1529 LPDIDEVICEOBJECTDATA dod,
1530 LPDWORD entries,
1531 DWORD flags
1532) {
1533 ICOM_THIS(JoystickAImpl,iface);
1534
1535 FIXME("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx),STUB!\n",This,dodsize,*entries,flags);
1536
1537 joy_polldev(This);
1538 if (flags & DIGDD_PEEK)
1539 FIXME("DIGDD_PEEK\n");
1540
1541 if (dod == NULL) {
1542 } else {
1543 }
1544 return 0;
1545}
1546
1547/******************************************************************************
1548 * SetProperty : change input device properties
1549 */
1550static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1551 REFGUID rguid,
1552 LPCDIPROPHEADER ph)
1553{
1554 ICOM_THIS(JoystickAImpl,iface);
1555 char xbuf[50];
1556
1557 if (HIWORD(rguid))
1558 WINE_StringFromCLSID(rguid,xbuf);
1559 else
1560 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1561
1562 FIXME("(this=%p,%s,%p)\n",This,xbuf,ph);
1563 FIXME("ph.dwSize = %ld, ph.dwHeaderSize =%ld, ph.dwObj = %ld, ph.dwHow= %ld\n",ph->dwSize, ph->dwHeaderSize,ph->dwObj,ph->dwHow);
1564
1565 if (!HIWORD(rguid)) {
1566 switch ((DWORD)rguid) {
1567 case (DWORD) DIPROP_BUFFERSIZE: {
1568 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1569
1570 FIXME("buffersize = %ld\n",pd->dwData);
1571 break;
1572 }
1573 case (DWORD)DIPROP_RANGE: {
1574 LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph;
1575
1576 FIXME("proprange(%ld,%ld)\n",pr->lMin,pr->lMax);
1577 This->lMin = pr->lMin;
1578 This->lMax = pr->lMax;
1579 break;
1580 }
1581 case (DWORD)DIPROP_DEADZONE: {
1582 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1583
1584 FIXME("deadzone(%ld)\n",pd->dwData);
1585 This->deadzone = pd->dwData;
1586 break;
1587 }
1588 default:
1589 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1590 break;
1591 }
1592 }
1593 return 0;
1594}
1595
1596/******************************************************************************
1597 * SetEventNotification : specifies event to be sent on state change
1598 */
1599static HRESULT WINAPI JoystickAImpl_SetEventNotification(
1600 LPDIRECTINPUTDEVICE2A iface, HANDLE hnd
1601) {
1602 ICOM_THIS(JoystickAImpl,iface);
1603
1604 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1605 This->hEvent = hnd;
1606 return DI_OK;
1607}
1608
1609static HRESULT WINAPI JoystickAImpl_GetCapabilities(
1610 LPDIRECTINPUTDEVICE2A iface,
1611 LPDIDEVCAPS lpDIDevCaps)
1612{
1613 ICOM_THIS(JoystickAImpl,iface);
1614 BYTE axes,buttons;
1615 int xfd = This->joyfd;
1616
1617 TRACE("%p->(%p)\n",iface,lpDIDevCaps);
1618 if (xfd==-1)
1619 xfd = open(JOYDEV,O_RDONLY);
1620 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
1621 lpDIDevCaps->dwDevType = DIDEVTYPE_JOYSTICK;
1622#ifdef JSIOCGAXES
1623 if (-1==ioctl(xfd,JSIOCGAXES,&axes))
1624 axes = 2;
1625 lpDIDevCaps->dwAxes = axes;
1626#endif
1627#ifdef JSIOCGBUTTONS
1628 if (-1==ioctl(xfd,JSIOCGAXES,&buttons))
1629 buttons = 2;
1630 lpDIDevCaps->dwButtons = buttons;
1631#endif
1632 if (xfd!=This->joyfd)
1633 close(xfd);
1634 return DI_OK;
1635}
1636static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE2A iface) {
1637 ICOM_THIS(JoystickAImpl,iface);
1638 TRACE("(),stub!\n");
1639
1640 joy_polldev(This);
1641 return DI_OK;
1642}
1643#endif
1644
1645/****************************************************************************/
1646/****************************************************************************/
1647
1648ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt =
1649{
1650 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1651 IDirectInputDevice2AImpl_QueryInterface,
1652 IDirectInputDevice2AImpl_AddRef,
1653 SysKeyboardAImpl_Release,
1654 IDirectInputDevice2AImpl_GetCapabilities,
1655 IDirectInputDevice2AImpl_EnumObjects,
1656 IDirectInputDevice2AImpl_GetProperty,
1657 SysKeyboardAImpl_SetProperty,
1658 SysKeyboardAImpl_Acquire,
1659 SysKeyboardAImpl_Unacquire,
1660 SysKeyboardAImpl_GetDeviceState,
1661 SysKeyboardAImpl_GetDeviceData,
1662 IDirectInputDevice2AImpl_SetDataFormat,
1663 IDirectInputDevice2AImpl_SetEventNotification,
1664 IDirectInputDevice2AImpl_SetCooperativeLevel,
1665 IDirectInputDevice2AImpl_GetObjectInfo,
1666 IDirectInputDevice2AImpl_GetDeviceInfo,
1667 IDirectInputDevice2AImpl_RunControlPanel,
1668 IDirectInputDevice2AImpl_Initialize,
1669 IDirectInputDevice2AImpl_CreateEffect,
1670 IDirectInputDevice2AImpl_EnumEffects,
1671 IDirectInputDevice2AImpl_GetEffectInfo,
1672 IDirectInputDevice2AImpl_GetForceFeedbackState,
1673 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1674 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1675 IDirectInputDevice2AImpl_Escape,
1676 IDirectInputDevice2AImpl_Poll,
1677 IDirectInputDevice2AImpl_SendDeviceData,
1678};
1679
1680ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt =
1681{
1682 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1683 IDirectInputDevice2AImpl_QueryInterface,
1684 IDirectInputDevice2AImpl_AddRef,
1685 SysMouseAImpl_Release,
1686 IDirectInputDevice2AImpl_GetCapabilities,
1687 IDirectInputDevice2AImpl_EnumObjects,
1688 IDirectInputDevice2AImpl_GetProperty,
1689 SysMouseAImpl_SetProperty,
1690 SysMouseAImpl_Acquire,
1691 SysMouseAImpl_Unacquire,
1692 SysMouseAImpl_GetDeviceState,
1693 SysMouseAImpl_GetDeviceData,
1694 SysMouseAImpl_SetDataFormat,
1695 SysMouseAImpl_SetEventNotification,
1696 SysMouseAImpl_SetCooperativeLevel,
1697 IDirectInputDevice2AImpl_GetObjectInfo,
1698 IDirectInputDevice2AImpl_GetDeviceInfo,
1699 IDirectInputDevice2AImpl_RunControlPanel,
1700 IDirectInputDevice2AImpl_Initialize,
1701 IDirectInputDevice2AImpl_CreateEffect,
1702 IDirectInputDevice2AImpl_EnumEffects,
1703 IDirectInputDevice2AImpl_GetEffectInfo,
1704 IDirectInputDevice2AImpl_GetForceFeedbackState,
1705 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1706 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1707 IDirectInputDevice2AImpl_Escape,
1708 IDirectInputDevice2AImpl_Poll,
1709 IDirectInputDevice2AImpl_SendDeviceData,
1710};
1711
1712#ifdef HAVE_LINUX_22_JOYSTICK_API
1713ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt =
1714{
1715 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1716 IDirectInputDevice2AImpl_QueryInterface,
1717 IDirectInputDevice2AImpl_AddRef,
1718 JoystickAImpl_Release,
1719 JoystickAImpl_GetCapabilities,
1720 IDirectInputDevice2AImpl_EnumObjects,
1721 IDirectInputDevice2AImpl_GetProperty,
1722 JoystickAImpl_SetProperty,
1723 JoystickAImpl_Acquire,
1724 JoystickAImpl_Unacquire,
1725 JoystickAImpl_GetDeviceState,
1726 JoystickAImpl_GetDeviceData,
1727 JoystickAImpl_SetDataFormat,
1728 JoystickAImpl_SetEventNotification,
1729 IDirectInputDevice2AImpl_SetCooperativeLevel,
1730 IDirectInputDevice2AImpl_GetObjectInfo,
1731 IDirectInputDevice2AImpl_GetDeviceInfo,
1732 IDirectInputDevice2AImpl_RunControlPanel,
1733 IDirectInputDevice2AImpl_Initialize,
1734 IDirectInputDevice2AImpl_CreateEffect,
1735 IDirectInputDevice2AImpl_EnumEffects,
1736 IDirectInputDevice2AImpl_GetEffectInfo,
1737 IDirectInputDevice2AImpl_GetForceFeedbackState,
1738 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1739 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1740 IDirectInputDevice2AImpl_Escape,
1741 JoystickAImpl_Poll,
1742 IDirectInputDevice2AImpl_SendDeviceData,
1743};
1744#endif
Note: See TracBrowser for help on using the repository browser.