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

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

Discard messages received multiple times.

File size: 54.4 KB
Line 
1/* $Id: dinput.cpp,v 1.7 2000-05-29 21:30:17 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 /* messages may arrive mustiple times; we need to check for duplicates */
630 static HWND oldhwnd = NULL;
631 static UINT oldmsg = 0;
632 static WPARAM oldwParam = 0;
633 static LPARAM oldlParam = 0;
634
635 if ((hwnd == oldhwnd) && (msg == oldmsg) && (wParam == oldwParam) && (lParam == oldlParam)) {
636 // we already saw this message
637 return TRUE;
638 }
639 oldhwnd = hwnd; oldmsg = msg; oldwParam = wParam; oldlParam = lParam;
640
641 // fake a key up transition for typematic repeat
642 if (msg == WM_KEYDOWN)
643 if (lParam & 0x40000000) { // key was down before
644 dprintf(("Repeat\n"));
645 GEN_KEYEVENT(scan, // scancode
646 0, // key up
647 time(NULL), evsequence++);
648 }
649
650 GEN_KEYEVENT(scan, // scancode
651 (lParam & 0x80000000) ? 0 : 0x80,
652 time(NULL), evsequence++);
653
654 if (msg == WM_KEYDOWN)
655 This->keystate[scan] = 0x80;
656 else
657 This->keystate[scan] = 0x00;
658
659 return TRUE;
660}
661
662static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
663{
664 ICOM_THIS(SysKeyboardAImpl,iface);
665 TRACE("DINPUT-SKAI: Acquire (this=%p)\n",This);
666
667 if (This->acquired == 0) {
668 /* Store (in a global variable) the current lock */
669 current_keylock = (IDirectInputDeviceA*)This;
670
671 /* register the keyboard event callback */
672 KEYBOARD_Enable(event_keyHandler);
673 This->acquired = 1;
674 }
675 return 0;
676}
677
678static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
679{
680 ICOM_THIS(SysKeyboardAImpl,iface);
681 TRACE("DINPUT-SKAI: Unacquire (this=%p)\n",This);
682
683 /* unregister the callback */
684 KEYBOARD_Enable(NULL);
685
686 /* No more locks */
687 current_keylock = NULL;
688
689 This->acquired = 0;
690 return 0;
691}
692
693static HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
694 LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
695)
696{
697 ICOM_THIS(IDirectInputDevice2AImpl,iface);
698 char xbuf[50];
699
700 WINE_StringFromCLSID(riid,xbuf);
701 TRACE("(this=%p,%s,%p)\n",This,xbuf,ppobj);
702 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
703 IDirectInputDevice2_AddRef(iface);
704 *ppobj = This;
705 return 0;
706 }
707 if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
708 IDirectInputDevice2_AddRef(iface);
709 *ppobj = This;
710 return 0;
711 }
712 if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
713 IDirectInputDevice2_AddRef(iface);
714 *ppobj = This;
715 return 0;
716 }
717 return E_FAIL;
718}
719
720static ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
721 LPDIRECTINPUTDEVICE2A iface)
722{
723 ICOM_THIS(IDirectInputDevice2AImpl,iface);
724 return ++This->ref;
725}
726
727static HRESULT WINAPI IDirectInputDevice2AImpl_GetCapabilities(
728 LPDIRECTINPUTDEVICE2A iface,
729 LPDIDEVCAPS lpDIDevCaps)
730{
731 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
732 FIXME("stub!\n");
733 return DI_OK;
734}
735
736static HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
737 LPDIRECTINPUTDEVICE2A iface,
738 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
739 LPVOID lpvRef,
740 DWORD dwFlags)
741{
742 FIXME("stub!\n");
743#if 0
744 if (lpCallback)
745 lpCallback(NULL, lpvRef);
746#endif
747 return DI_OK;
748}
749
750static HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
751 LPDIRECTINPUTDEVICE2A iface,
752 REFGUID rguid,
753 LPDIPROPHEADER pdiph)
754{
755 FIXME("stub!\n");
756 return DI_OK;
757}
758
759static HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
760 LPDIRECTINPUTDEVICE2A iface,
761 LPDIDEVICEOBJECTINSTANCEA pdidoi,
762 DWORD dwObj,
763 DWORD dwHow)
764{
765 FIXME("stub!\n");
766 return DI_OK;
767}
768
769static HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
770 LPDIRECTINPUTDEVICE2A iface,
771 LPDIDEVICEINSTANCEA pdidi)
772{
773 FIXME("stub!\n");
774 return DI_OK;
775}
776
777static HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
778 LPDIRECTINPUTDEVICE2A iface,
779 HWND hwndOwner,
780 DWORD dwFlags)
781{
782 FIXME("stub!\n");
783 return DI_OK;
784}
785
786static HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
787 LPDIRECTINPUTDEVICE2A iface,
788 HINSTANCE hinst,
789 DWORD dwVersion,
790 REFGUID rguid)
791{
792 FIXME("stub!\n");
793 return DI_OK;
794}
795
796/******************************************************************************
797 * IDirectInputDevice2A
798 */
799
800static HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
801 LPDIRECTINPUTDEVICE2A iface,
802 REFGUID rguid,
803 LPCDIEFFECT lpeff,
804 LPDIRECTINPUTEFFECT *ppdef,
805 LPUNKNOWN pUnkOuter)
806{
807 FIXME("stub!\n");
808 return DI_OK;
809}
810
811static HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
812 LPDIRECTINPUTDEVICE2A iface,
813 LPDIENUMEFFECTSCALLBACKA lpCallback,
814 LPVOID lpvRef,
815 DWORD dwFlags)
816{
817 FIXME("stub!\n");
818 if (lpCallback)
819 lpCallback(NULL, lpvRef);
820 return DI_OK;
821}
822
823static HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
824 LPDIRECTINPUTDEVICE2A iface,
825 LPDIEFFECTINFOA lpdei,
826 REFGUID rguid)
827{
828 FIXME("stub!\n");
829 return DI_OK;
830}
831
832static HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
833 LPDIRECTINPUTDEVICE2A iface,
834 LPDWORD pdwOut)
835{
836 FIXME("stub!\n");
837 return DI_OK;
838}
839
840static HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
841 LPDIRECTINPUTDEVICE2A iface,
842 DWORD dwFlags)
843{
844 FIXME("stub!\n");
845 return DI_OK;
846}
847
848static HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
849 LPDIRECTINPUTDEVICE2A iface,
850 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
851 LPVOID lpvRef,
852 DWORD dwFlags)
853{
854 FIXME("stub!\n");
855 if (lpCallback)
856 lpCallback(NULL, lpvRef);
857 return DI_OK;
858}
859
860static HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
861 LPDIRECTINPUTDEVICE2A iface,
862 LPDIEFFESCAPE lpDIEEsc)
863{
864 FIXME("stub!\n");
865 return DI_OK;
866}
867
868static HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
869 LPDIRECTINPUTDEVICE2A iface)
870{
871 FIXME("stub!\n");
872 return DI_OK;
873}
874
875static HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
876 LPDIRECTINPUTDEVICE2A iface,
877 DWORD cbObjectData,
878 LPDIDEVICEOBJECTDATA rgdod,
879 LPDWORD pdwInOut,
880 DWORD dwFlags)
881{
882 FIXME("stub!\n");
883 return DI_OK;
884}
885
886/******************************************************************************
887 * SysMouseA (DInput Mouse support)
888 */
889
890/******************************************************************************
891 * Release : release the mouse buffer.
892 */
893static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
894{
895 ICOM_THIS(SysMouseAImpl,iface);
896
897 This->ref--;
898 if (This->ref)
899 return This->ref;
900
901 /* Free the data queue */
902 if (This->data_queue != NULL)
903 HeapFree(GetProcessHeap(),0,This->data_queue);
904
905 /* Install the previous event handler (in case of releasing an aquired
906 mouse device) */
907 if (This->prev_handler != NULL)
908 MOUSE_Enable(This->prev_handler);
909 DeleteCriticalSection(&(This->crit));
910
911 HeapFree(GetProcessHeap(),0,This);
912 return 0;
913}
914
915
916/******************************************************************************
917 * SetCooperativeLevel : store the window in which we will do our
918 * grabbing.
919 */
920static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
921 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
922)
923{
924 ICOM_THIS(SysMouseAImpl,iface);
925
926 TRACE("(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
927
928// if (TRACE_ON(dinput))
929// _dump_cooperativelevel(dwflags);
930
931 /* Store the window which asks for the mouse */
932 This->win = hwnd;
933
934 return 0;
935}
936
937
938/******************************************************************************
939 * SetDataFormat : the application can choose the format of the data
940 * the device driver sends back with GetDeviceState.
941 *
942 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
943 * in absolute and relative mode.
944 */
945static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
946 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
947)
948{
949 ICOM_THIS(SysMouseAImpl,iface);
950 int i;
951
952 TRACE("(this=%p,%p)\n",This,df);
953
954 TRACE("(df.dwSize=%ld)\n",df->dwSize);
955 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
956 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
957 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
958 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
959
960 for (i=0;i<df->dwNumObjs;i++) {
961 char xbuf[50];
962
963 if (df->rgodf[i].pguid)
964 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
965 else
966 strcpy(xbuf,"<no guid>");
967 TRACE("df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
968 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
969 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
970 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
971 }
972
973 /* Check size of data format to prevent crashes if the applications
974 sends a smaller buffer */
975 if (df->dwDataSize != sizeof(struct DIMOUSESTATE)) {
976 FIXME("non-standard mouse configuration not supported yet.");
977 return DIERR_INVALIDPARAM;
978 }
979
980 /* For the moment, ignore these fields and return always as if
981 c_dfDIMouse was passed as format... */
982
983 /* Check if the mouse is in absolute or relative mode */
984 if (df->dwFlags == DIDF_ABSAXIS)
985 This->absolute = 1;
986 else if (df->dwFlags == DIDF_RELAXIS)
987 This->absolute = 0;
988 else
989 ERR("Neither absolute nor relative flag set.");
990
991 This->df = (LPCDIDATAFORMAT)HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
992 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
993 return 0;
994}
995
996#define GEN_EVENT(offset,data,xtime,seq) \
997{ \
998 if (This->queue_pos < This->queue_len) { \
999 This->data_queue[This->queue_pos].dwOfs = offset; \
1000 This->data_queue[This->queue_pos].dwData = data; \
1001 This->data_queue[This->queue_pos].dwTimeStamp = xtime; \
1002 This->data_queue[This->queue_pos].dwSequence = seq; \
1003 This->queue_pos++; \
1004 } \
1005}
1006
1007
1008/* Our private mouse event handler */
1009static BOOL WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
1010 DWORD cButtons, DWORD dwExtraInfo )
1011{
1012 DWORD posX, posY, keyState, xtime, extra;
1013 SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
1014
1015 EnterCriticalSection(&(This->crit));
1016 /* Mouse moved -> send event if asked */
1017 if (This->hEvent)
1018 SetEvent(This->hEvent);
1019
1020 if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
1021 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
1022 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
1023 keyState = wme->keyState;
1024 xtime = wme->time;
1025 extra = (DWORD)wme->hWnd;
1026
1027 if(This->win && This->win != wme->hWnd) {
1028 return FALSE;
1029 }
1030
1031 assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
1032 posX = (dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
1033 posY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
1034 } else {
1035 ERR("Mouse event not supported...\n");
1036 LeaveCriticalSection(&(This->crit));
1037 return FALSE;
1038 }
1039
1040 TRACE("DINPUT-SMAI: event %x %ld, %ld", dwFlags, posX, posY);
1041
1042 if ( dwFlags & MOUSEEVENTF_MOVE ) {
1043 if (This->absolute) {
1044 if (posX != This->prevX)
1045 GEN_EVENT(DIMOFS_X, posX, xtime, 0);
1046 if (posY != This->prevY)
1047 GEN_EVENT(DIMOFS_Y, posY, xtime, 0);
1048 } else {
1049 /* Relative mouse input : the real fun starts here... */
1050 if (This->need_warp) {
1051 if (posX != This->prevX)
1052 GEN_EVENT(DIMOFS_X, posX - This->prevX, xtime, evsequence++);
1053 if (posY != This->prevY)
1054 GEN_EVENT(DIMOFS_Y, posY - This->prevY, xtime, evsequence++);
1055 } else {
1056 /* This is the first time the event handler has been called after a
1057 GetData of GetState. */
1058 if (posX != This->win_centerX) {
1059 GEN_EVENT(DIMOFS_X, posX - This->win_centerX, xtime, evsequence++);
1060 This->need_warp = 1;
1061 }
1062
1063 if (posY != This->win_centerY) {
1064 GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, xtime, evsequence++);
1065 This->need_warp = 1;
1066 }
1067 }
1068 }
1069 }
1070 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
1071// if (TRACE_ON(dinput))
1072// DPRINTF(" LD ");
1073
1074 GEN_EVENT(DIMOFS_BUTTON0, 0xFF, xtime, evsequence++);
1075 }
1076 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
1077// if (TRACE_ON(dinput))
1078// DPRINTF(" LU ");
1079
1080 GEN_EVENT(DIMOFS_BUTTON0, 0x00, xtime, evsequence++);
1081 }
1082 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
1083// if (TRACE_ON(dinput))
1084// DPRINTF(" RD ");
1085
1086 GEN_EVENT(DIMOFS_BUTTON1, 0xFF, xtime, evsequence++);
1087 }
1088 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
1089// if (TRACE_ON(dinput))
1090// DPRINTF(" RU ");
1091
1092 GEN_EVENT(DIMOFS_BUTTON1, 0x00, xtime, evsequence++);
1093 }
1094 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
1095// if (TRACE_ON(dinput))
1096// DPRINTF(" MD ");
1097
1098 GEN_EVENT(DIMOFS_BUTTON2, 0xFF, xtime, evsequence++);
1099 }
1100 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
1101// if (TRACE_ON(dinput))
1102// DPRINTF(" MU ");
1103
1104 GEN_EVENT(DIMOFS_BUTTON2, 0x00, xtime, evsequence++);
1105 }
1106// if (TRACE_ON(dinput))
1107// DPRINTF("\n");
1108
1109 This->prevX = posX;
1110 This->prevY = posY;
1111 LeaveCriticalSection(&(This->crit));
1112
1113 return TRUE;
1114}
1115
1116
1117/******************************************************************************
1118 * Acquire : gets exclusive control of the mouse
1119 */
1120static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1121{
1122 ICOM_THIS(SysMouseAImpl,iface);
1123 RECT rect;
1124
1125 TRACE("SysMouseAImpl_Acquire: (this=%p)\n",This);
1126
1127 if (This->acquired == 0) {
1128 POINT point;
1129
1130 /* This stores the current mouse handler. */
1131#ifdef __WIN32OS2__
1132 This->prev_handler = (LPMOUSE_EVENT_PROC)-1;
1133#else
1134 This->prev_handler = mouse_event;
1135#endif
1136
1137 /* Store (in a global variable) the current lock */
1138 current_lock = (IDirectInputDevice2A*)This;
1139
1140 /* Install our own mouse event handler */
1141 MOUSE_Enable(dinput_mouse_event);
1142
1143 /* Get the window dimension and find the center */
1144 GetWindowRect(This->win, &rect);
1145 This->win_centerX = (rect.right - rect.left) / 2;
1146 This->win_centerY = (rect.bottom - rect.top ) / 2;
1147
1148 /* Warp the mouse to the center of the window */
1149 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1150 point.x = This->win_centerX;
1151 point.y = This->win_centerY;
1152 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1153#ifdef __WIN32OS2__
1154 OSLibMoveCursor(point.x, point.y);
1155#else
1156 DISPLAY_MoveCursor(point.x, point.y);
1157#endif
1158
1159 This->acquired = 1;
1160 }
1161 return 0;
1162}
1163
1164/******************************************************************************
1165 * Unacquire : frees the mouse
1166 */
1167static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1168{
1169 ICOM_THIS(SysMouseAImpl,iface);
1170
1171 TRACE("SysMouseAImpl_Unacquire: (this=%p)\n",This);
1172
1173 /* Reinstall previous mouse event handler */
1174 MOUSE_Enable(This->prev_handler);
1175 This->prev_handler = NULL;
1176
1177 /* No more locks */
1178 current_lock = NULL;
1179
1180 /* Unacquire device */
1181 This->acquired = 0;
1182
1183 return 0;
1184}
1185
1186/******************************************************************************
1187 * GetDeviceState : returns the "state" of the mouse.
1188 *
1189 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
1190 * supported.
1191 */
1192static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
1193 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1194) {
1195 ICOM_THIS(SysMouseAImpl,iface);
1196 DWORD rx, ry, state;
1197 struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
1198
1199 TRACE("(this=%p,0x%08lx,%p): \n",This,len,ptr);
1200
1201 /* Check if the buffer is big enough */
1202 if (len < sizeof(struct DIMOUSESTATE)) {
1203 FIXME("unsupported state structure.");
1204 return DIERR_INVALIDPARAM;
1205 }
1206
1207 /* Get the mouse position */
1208#ifdef __WIN32OS2__
1209 OSLibQueryMousePos(&rx, &ry, &state);
1210#else
1211 EVENT_QueryPointer(&rx, &ry, &state);
1212#endif
1213 TRACE("(X:%ld - Y:%ld)\n", rx, ry);
1214
1215 /* Fill the mouse state structure */
1216 if (This->absolute) {
1217 mstate->lX = rx;
1218 mstate->lY = ry;
1219 } else {
1220 mstate->lX = rx - This->win_centerX;
1221 mstate->lY = ry - This->win_centerY;
1222
1223 if ((mstate->lX != 0) || (mstate->lY != 0))
1224 This->need_warp = 1;
1225 }
1226 mstate->lZ = 0;
1227 mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00);
1228 mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00);
1229 mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00);
1230 mstate->rgbButtons[3] = 0x00;
1231
1232 /* Check if we need to do a mouse warping */
1233 if (This->need_warp) {
1234 POINT point;
1235
1236 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1237 point.x = This->win_centerX;
1238 point.y = This->win_centerY;
1239 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1240#ifdef __WIN32OS2__
1241 OSLibMoveCursor(point.x, point.y);
1242#else
1243 DISPLAY_MoveCursor(point.x, point.y);
1244#endif
1245 This->need_warp = 0;
1246 }
1247
1248 TRACE("(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
1249 mstate->lX, mstate->lY,
1250 mstate->rgbButtons[0], mstate->rgbButtons[2], mstate->rgbButtons[1]);
1251
1252 return 0;
1253}
1254
1255/******************************************************************************
1256 * GetDeviceState : gets buffered input data.
1257 */
1258static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1259 DWORD dodsize,
1260 LPDIDEVICEOBJECTDATA dod,
1261 LPDWORD entries,
1262 DWORD flags
1263) {
1264 ICOM_THIS(SysMouseAImpl,iface);
1265
1266 EnterCriticalSection(&(This->crit));
1267 TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
1268
1269 if (flags & DIGDD_PEEK)
1270 FIXME("DIGDD_PEEK\n");
1271
1272 if (dod == NULL) {
1273 *entries = This->queue_pos;
1274 This->queue_pos = 0;
1275 } else {
1276 /* Check for buffer overflow */
1277 if (This->queue_pos > *entries) {
1278 WARN("Buffer overflow not handled properly yet...\n");
1279 This->queue_pos = *entries;
1280 }
1281 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1282 ERR("Wrong structure size !\n");
1283 LeaveCriticalSection(&(This->crit));
1284 return DIERR_INVALIDPARAM;
1285 }
1286
1287 if (This->queue_pos)
1288 TRACE("Application retrieving %d event(s).\n", This->queue_pos);
1289
1290 /* Copy the buffered data into the application queue */
1291 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1292 *entries = This->queue_pos;
1293
1294 /* Reset the event queue */
1295 This->queue_pos = 0;
1296 }
1297 LeaveCriticalSection(&(This->crit));
1298
1299#if 0 /* FIXME: seems to create motion events, which fire back at us. */
1300 /* Check if we need to do a mouse warping */
1301 if (This->need_warp) {
1302 POINT point;
1303
1304 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1305 point.x = This->win_centerX;
1306 point.y = This->win_centerY;
1307 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1308
1309#ifdef __WIN32OS2__
1310 OSLibMoveCursor(point.x, point.y);
1311#else
1312 DISPLAY_MoveCursor(point.x, point.y);
1313#endif
1314
1315 This->need_warp = 0;
1316 }
1317#endif
1318 return 0;
1319}
1320
1321/******************************************************************************
1322 * SetProperty : change input device properties
1323 */
1324static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1325 REFGUID rguid,
1326 LPCDIPROPHEADER ph)
1327{
1328 ICOM_THIS(SysMouseAImpl,iface);
1329 char xbuf[50];
1330
1331 if (HIWORD(rguid))
1332 WINE_StringFromCLSID(rguid,xbuf);
1333 else
1334 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1335
1336 TRACE("(this=%p,%s,%p)\n",This,xbuf,ph);
1337
1338 if (!HIWORD(rguid)) {
1339#ifdef __WIN32OS2__
1340 if(rguid == DIPROP_BUFFERSIZE) {
1341 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1342
1343 TRACE("buffersize = %ld\n",pd->dwData);
1344
1345 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1346 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1347 This->queue_pos = 0;
1348 This->queue_len = pd->dwData;
1349 }
1350 else {
1351 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1352 }
1353#else
1354 switch ((DWORD)rguid) {
1355 case (DWORD) DIPROP_BUFFERSIZE: {
1356 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1357
1358 TRACE("buffersize = %ld\n",pd->dwData);
1359
1360 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1361 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1362 This->queue_pos = 0;
1363 This->queue_len = pd->dwData;
1364 break;
1365 }
1366 default:
1367 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1368 break;
1369 }
1370#endif
1371 }
1372
1373 return 0;
1374}
1375
1376/******************************************************************************
1377 * SetEventNotification : specifies event to be sent on state change
1378 */
1379static HRESULT WINAPI SysMouseAImpl_SetEventNotification(LPDIRECTINPUTDEVICE2A iface,
1380 HANDLE hnd) {
1381 ICOM_THIS(SysMouseAImpl,iface);
1382
1383 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1384
1385 This->hEvent = hnd;
1386
1387 return DI_OK;
1388}
1389
1390#ifdef HAVE_LINUX_22_JOYSTICK_API
1391/******************************************************************************
1392 * Joystick
1393 */
1394static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
1395{
1396 ICOM_THIS(JoystickAImpl,iface);
1397
1398 This->ref--;
1399 if (This->ref)
1400 return This->ref;
1401 HeapFree(GetProcessHeap(),0,This);
1402 return 0;
1403}
1404
1405/******************************************************************************
1406 * SetDataFormat : the application can choose the format of the data
1407 * the device driver sends back with GetDeviceState.
1408 */
1409static HRESULT WINAPI JoystickAImpl_SetDataFormat(
1410 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
1411)
1412{
1413 ICOM_THIS(JoystickAImpl,iface);
1414 int i;
1415
1416 TRACE("(this=%p,%p)\n",This,df);
1417
1418 TRACE("(df.dwSize=%ld)\n",df->dwSize);
1419 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
1420 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
1421 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
1422 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
1423
1424 for (i=0;i<df->dwNumObjs;i++) {
1425 char xbuf[50];
1426
1427 if (df->rgodf[i].pguid)
1428 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
1429 else
1430 strcpy(xbuf,"<no guid>");
1431 TRACE("df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
1432 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
1433 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
1434 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
1435 }
1436 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1437 memcpy(This->df,df,df->dwSize+(df->dwNumObjs*df->dwObjSize));
1438 return 0;
1439}
1440
1441/******************************************************************************
1442 * Acquire : gets exclusive control of the joystick
1443 */
1444static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1445{
1446 ICOM_THIS(JoystickAImpl,iface);
1447
1448 TRACE("(this=%p)\n",This);
1449 if (This->joyfd!=-1)
1450 return 0;
1451 This->joyfd=open(JOYDEV,O_RDONLY);
1452 if (This->joyfd==-1)
1453 return DIERR_NOTFOUND;
1454 return 0;
1455}
1456
1457/******************************************************************************
1458 * Unacquire : frees the joystick
1459 */
1460static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1461{
1462 ICOM_THIS(JoystickAImpl,iface);
1463
1464 TRACE("(this=%p)\n",This);
1465 if (This->joyfd!=-1) {
1466 close(This->joyfd);
1467 This->joyfd = -1;
1468 }
1469 return 0;
1470}
1471
1472#define map_axis(val) ((val+32768)*(This->lMax-This->lMin)/65536+This->lMin)
1473
1474static void joy_polldev(JoystickAImpl *This) {
1475 struct timeval tv;
1476 fd_set readfds;
1477 struct js_event jse;
1478
1479 if (This->joyfd==-1)
1480 return;
1481 while (1) {
1482 memset(&tv,0,sizeof(tv));
1483 FD_ZERO(&readfds);FD_SET(This->joyfd,&readfds);
1484 if (1>select(This->joyfd+1,&readfds,NULL,NULL,&tv))
1485 return;
1486 /* we have one event, so we can read */
1487 if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
1488 return;
1489 }
1490 TRACE("js_event: type 0x%x, number %d, value %d\n",jse.type,jse.number,jse.value);
1491 if (jse.type & JS_EVENT_BUTTON) {
1492 GEN_EVENT(DIJOFS_BUTTON(jse.number),jse.value?0x80:0x00,jse.time,evsequence++);
1493 This->js.rgbButtons[jse.number] = jse.value?0x80:0x00;
1494 }
1495 if (jse.type & JS_EVENT_AXIS) {
1496 switch (jse.number) {
1497 case 0:
1498 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1499 This->js.lX = map_axis(jse.value);
1500 break;
1501 case 1:
1502 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1503 This->js.lY = map_axis(jse.value);
1504 break;
1505 case 2:
1506 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1507 This->js.lZ = map_axis(jse.value);
1508 break;
1509 default:
1510 FIXME("more then 3 axes (%d) not handled!\n",jse.number);
1511 break;
1512 }
1513 }
1514 }
1515}
1516
1517/******************************************************************************
1518 * GetDeviceState : returns the "state" of the joystick.
1519 *
1520 */
1521static HRESULT WINAPI JoystickAImpl_GetDeviceState(
1522 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1523) {
1524 ICOM_THIS(JoystickAImpl,iface);
1525
1526 joy_polldev(This);
1527 TRACE("(this=%p,0x%08lx,%p)\n",This,len,ptr);
1528 if (len != sizeof(DIJOYSTATE)) {
1529 FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len);
1530 }
1531 memcpy(ptr,&(This->js),len);
1532 This->queue_pos = 0;
1533 return 0;
1534}
1535
1536/******************************************************************************
1537 * GetDeviceState : gets buffered input data.
1538 */
1539static HRESULT WINAPI JoystickAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1540 DWORD dodsize,
1541 LPDIDEVICEOBJECTDATA dod,
1542 LPDWORD entries,
1543 DWORD flags
1544) {
1545 ICOM_THIS(JoystickAImpl,iface);
1546
1547 FIXME("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx),STUB!\n",This,dodsize,*entries,flags);
1548
1549 joy_polldev(This);
1550 if (flags & DIGDD_PEEK)
1551 FIXME("DIGDD_PEEK\n");
1552
1553 if (dod == NULL) {
1554 } else {
1555 }
1556 return 0;
1557}
1558
1559/******************************************************************************
1560 * SetProperty : change input device properties
1561 */
1562static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1563 REFGUID rguid,
1564 LPCDIPROPHEADER ph)
1565{
1566 ICOM_THIS(JoystickAImpl,iface);
1567 char xbuf[50];
1568
1569 if (HIWORD(rguid))
1570 WINE_StringFromCLSID(rguid,xbuf);
1571 else
1572 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1573
1574 FIXME("(this=%p,%s,%p)\n",This,xbuf,ph);
1575 FIXME("ph.dwSize = %ld, ph.dwHeaderSize =%ld, ph.dwObj = %ld, ph.dwHow= %ld\n",ph->dwSize, ph->dwHeaderSize,ph->dwObj,ph->dwHow);
1576
1577 if (!HIWORD(rguid)) {
1578 switch ((DWORD)rguid) {
1579 case (DWORD) DIPROP_BUFFERSIZE: {
1580 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1581
1582 FIXME("buffersize = %ld\n",pd->dwData);
1583 break;
1584 }
1585 case (DWORD)DIPROP_RANGE: {
1586 LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph;
1587
1588 FIXME("proprange(%ld,%ld)\n",pr->lMin,pr->lMax);
1589 This->lMin = pr->lMin;
1590 This->lMax = pr->lMax;
1591 break;
1592 }
1593 case (DWORD)DIPROP_DEADZONE: {
1594 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1595
1596 FIXME("deadzone(%ld)\n",pd->dwData);
1597 This->deadzone = pd->dwData;
1598 break;
1599 }
1600 default:
1601 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,xbuf);
1602 break;
1603 }
1604 }
1605 return 0;
1606}
1607
1608/******************************************************************************
1609 * SetEventNotification : specifies event to be sent on state change
1610 */
1611static HRESULT WINAPI JoystickAImpl_SetEventNotification(
1612 LPDIRECTINPUTDEVICE2A iface, HANDLE hnd
1613) {
1614 ICOM_THIS(JoystickAImpl,iface);
1615
1616 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1617 This->hEvent = hnd;
1618 return DI_OK;
1619}
1620
1621static HRESULT WINAPI JoystickAImpl_GetCapabilities(
1622 LPDIRECTINPUTDEVICE2A iface,
1623 LPDIDEVCAPS lpDIDevCaps)
1624{
1625 ICOM_THIS(JoystickAImpl,iface);
1626 BYTE axes,buttons;
1627 int xfd = This->joyfd;
1628
1629 TRACE("%p->(%p)\n",iface,lpDIDevCaps);
1630 if (xfd==-1)
1631 xfd = open(JOYDEV,O_RDONLY);
1632 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
1633 lpDIDevCaps->dwDevType = DIDEVTYPE_JOYSTICK;
1634#ifdef JSIOCGAXES
1635 if (-1==ioctl(xfd,JSIOCGAXES,&axes))
1636 axes = 2;
1637 lpDIDevCaps->dwAxes = axes;
1638#endif
1639#ifdef JSIOCGBUTTONS
1640 if (-1==ioctl(xfd,JSIOCGAXES,&buttons))
1641 buttons = 2;
1642 lpDIDevCaps->dwButtons = buttons;
1643#endif
1644 if (xfd!=This->joyfd)
1645 close(xfd);
1646 return DI_OK;
1647}
1648static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE2A iface) {
1649 ICOM_THIS(JoystickAImpl,iface);
1650 TRACE("(),stub!\n");
1651
1652 joy_polldev(This);
1653 return DI_OK;
1654}
1655#endif
1656
1657/****************************************************************************/
1658/****************************************************************************/
1659
1660ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt =
1661{
1662 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1663 IDirectInputDevice2AImpl_QueryInterface,
1664 IDirectInputDevice2AImpl_AddRef,
1665 SysKeyboardAImpl_Release,
1666 IDirectInputDevice2AImpl_GetCapabilities,
1667 IDirectInputDevice2AImpl_EnumObjects,
1668 IDirectInputDevice2AImpl_GetProperty,
1669 SysKeyboardAImpl_SetProperty,
1670 SysKeyboardAImpl_Acquire,
1671 SysKeyboardAImpl_Unacquire,
1672 SysKeyboardAImpl_GetDeviceState,
1673 SysKeyboardAImpl_GetDeviceData,
1674 IDirectInputDevice2AImpl_SetDataFormat,
1675 IDirectInputDevice2AImpl_SetEventNotification,
1676 IDirectInputDevice2AImpl_SetCooperativeLevel,
1677 IDirectInputDevice2AImpl_GetObjectInfo,
1678 IDirectInputDevice2AImpl_GetDeviceInfo,
1679 IDirectInputDevice2AImpl_RunControlPanel,
1680 IDirectInputDevice2AImpl_Initialize,
1681 IDirectInputDevice2AImpl_CreateEffect,
1682 IDirectInputDevice2AImpl_EnumEffects,
1683 IDirectInputDevice2AImpl_GetEffectInfo,
1684 IDirectInputDevice2AImpl_GetForceFeedbackState,
1685 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1686 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1687 IDirectInputDevice2AImpl_Escape,
1688 IDirectInputDevice2AImpl_Poll,
1689 IDirectInputDevice2AImpl_SendDeviceData,
1690};
1691
1692ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt =
1693{
1694 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1695 IDirectInputDevice2AImpl_QueryInterface,
1696 IDirectInputDevice2AImpl_AddRef,
1697 SysMouseAImpl_Release,
1698 IDirectInputDevice2AImpl_GetCapabilities,
1699 IDirectInputDevice2AImpl_EnumObjects,
1700 IDirectInputDevice2AImpl_GetProperty,
1701 SysMouseAImpl_SetProperty,
1702 SysMouseAImpl_Acquire,
1703 SysMouseAImpl_Unacquire,
1704 SysMouseAImpl_GetDeviceState,
1705 SysMouseAImpl_GetDeviceData,
1706 SysMouseAImpl_SetDataFormat,
1707 SysMouseAImpl_SetEventNotification,
1708 SysMouseAImpl_SetCooperativeLevel,
1709 IDirectInputDevice2AImpl_GetObjectInfo,
1710 IDirectInputDevice2AImpl_GetDeviceInfo,
1711 IDirectInputDevice2AImpl_RunControlPanel,
1712 IDirectInputDevice2AImpl_Initialize,
1713 IDirectInputDevice2AImpl_CreateEffect,
1714 IDirectInputDevice2AImpl_EnumEffects,
1715 IDirectInputDevice2AImpl_GetEffectInfo,
1716 IDirectInputDevice2AImpl_GetForceFeedbackState,
1717 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1718 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1719 IDirectInputDevice2AImpl_Escape,
1720 IDirectInputDevice2AImpl_Poll,
1721 IDirectInputDevice2AImpl_SendDeviceData,
1722};
1723
1724#ifdef HAVE_LINUX_22_JOYSTICK_API
1725ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt =
1726{
1727 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1728 IDirectInputDevice2AImpl_QueryInterface,
1729 IDirectInputDevice2AImpl_AddRef,
1730 JoystickAImpl_Release,
1731 JoystickAImpl_GetCapabilities,
1732 IDirectInputDevice2AImpl_EnumObjects,
1733 IDirectInputDevice2AImpl_GetProperty,
1734 JoystickAImpl_SetProperty,
1735 JoystickAImpl_Acquire,
1736 JoystickAImpl_Unacquire,
1737 JoystickAImpl_GetDeviceState,
1738 JoystickAImpl_GetDeviceData,
1739 JoystickAImpl_SetDataFormat,
1740 JoystickAImpl_SetEventNotification,
1741 IDirectInputDevice2AImpl_SetCooperativeLevel,
1742 IDirectInputDevice2AImpl_GetObjectInfo,
1743 IDirectInputDevice2AImpl_GetDeviceInfo,
1744 IDirectInputDevice2AImpl_RunControlPanel,
1745 IDirectInputDevice2AImpl_Initialize,
1746 IDirectInputDevice2AImpl_CreateEffect,
1747 IDirectInputDevice2AImpl_EnumEffects,
1748 IDirectInputDevice2AImpl_GetEffectInfo,
1749 IDirectInputDevice2AImpl_GetForceFeedbackState,
1750 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1751 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1752 IDirectInputDevice2AImpl_Escape,
1753 JoystickAImpl_Poll,
1754 IDirectInputDevice2AImpl_SendDeviceData,
1755};
1756#endif
Note: See TracBrowser for help on using the repository browser.