CURSORICON_IconToCursor: inconsistent Lock/Unlock
[wine/dcerpc.git] / windows / dinput.c
blob3165bfa37c12544b1fbe9a814832d6e2605ee960
1 /* DirectInput
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
6 */
7 /* Status:
9 * - Tomb Raider 2 Demo:
10 * Playable using keyboard only.
11 * - WingCommander Prophecy Demo:
12 * Doesn't get Input Focus.
14 * - Fallout : works great in X and DGA mode
16 * FIXME: The keyboard handling needs to (and will) be merged into keyboard.c
17 * (The current implementation is currently only a proof of concept and
18 * an utter mess.)
21 #include "config.h"
22 #include <stdio.h>
23 #include <string.h>
24 #include <time.h>
25 #include <unistd.h>
26 #include <assert.h>
27 #ifdef HAVE_SYS_SIGNAL_H
28 # include <sys/signal.h>
29 #endif
30 #include <sys/time.h>
31 #include <sys/fcntl.h>
32 #include <sys/ioctl.h>
33 #include <errno.h>
34 #ifdef HAVE_SYS_ERRNO_H
35 # include <sys/errno.h>
36 #endif
37 #ifdef HAVE_LINUX_JOYSTICK_H
38 # include <linux/joystick.h>
39 # define JOYDEV "/dev/js0"
40 #endif
41 #include "wine/obj_base.h"
42 #include "debugtools.h"
43 #include "dinput.h"
44 #include "display.h"
45 #include "input.h"
46 #include "keyboard.h"
47 #include "message.h"
48 #include "mouse.h"
49 #include "sysmetrics.h"
50 #include "winbase.h"
51 #include "winerror.h"
52 #include "windef.h"
53 #include "wingdi.h"
54 #include "winuser.h"
56 DEFAULT_DEBUG_CHANNEL(dinput)
58 /* Wine mouse driver object instances */
59 #define WINE_MOUSE_X_AXIS_INSTANCE 0x0001
60 #define WINE_MOUSE_Y_AXIS_INSTANCE 0x0002
61 #define WINE_MOUSE_L_BUTTON_INSTANCE 0x0004
62 #define WINE_MOUSE_R_BUTTON_INSTANCE 0x0008
63 #define WINE_MOUSE_M_BUTTON_INSTANCE 0x0010
65 /* Wine joystick driver object instances */
66 #define WINE_JOYSTICK_AXIS_BASE 0
67 #define WINE_JOYSTICK_BUTTON_BASE 8
69 extern BYTE InputKeyStateTable[256];
70 extern int min_keycode, max_keycode;
71 extern WORD keyc2vkey[256];
73 /* Routines to do DataFormat / WineFormat conversions */
74 typedef struct {
75 int size;
76 int offset_in;
77 int offset_out;
78 int value;
79 } DataTransform;
81 typedef struct {
82 int size;
83 int internal_format_size;
84 DataTransform *dt;
85 } DataFormat;
87 /* ------------------------------- */
88 /* Wine mouse internal data format */
89 /* ------------------------------- */
91 /* Constants used to access the offset array */
92 #define WINE_MOUSE_X_POSITION 0
93 #define WINE_MOUSE_Y_POSITION 1
94 #define WINE_MOUSE_L_POSITION 2
95 #define WINE_MOUSE_R_POSITION 3
96 #define WINE_MOUSE_M_POSITION 4
98 typedef struct {
99 LONG lX;
100 LONG lY;
101 BYTE rgbButtons[4];
102 } Wine_InternalMouseData;
104 #define WINE_INTERNALMOUSE_NUM_OBJS 5
106 static DIOBJECTDATAFORMAT Wine_InternalMouseObjectFormat[WINE_INTERNALMOUSE_NUM_OBJS] = {
107 { &GUID_XAxis, FIELD_OFFSET(Wine_InternalMouseData, lX),
108 DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS, 0 },
109 { &GUID_YAxis, FIELD_OFFSET(Wine_InternalMouseData, lY),
110 DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS, 0 },
111 { &GUID_Button, (FIELD_OFFSET(Wine_InternalMouseData, rgbButtons)) + 0,
112 DIDFT_MAKEINSTANCE(WINE_MOUSE_L_BUTTON_INSTANCE) | DIDFT_PSHBUTTON, 0 },
113 { &GUID_Button, (FIELD_OFFSET(Wine_InternalMouseData, rgbButtons)) + 1,
114 DIDFT_MAKEINSTANCE(WINE_MOUSE_R_BUTTON_INSTANCE) | DIDFT_PSHBUTTON, 0 },
115 { &GUID_Button, (FIELD_OFFSET(Wine_InternalMouseData, rgbButtons)) + 2,
116 DIDFT_MAKEINSTANCE(WINE_MOUSE_M_BUTTON_INSTANCE) | DIDFT_PSHBUTTON, 0 }
119 static DIDATAFORMAT Wine_InternalMouseFormat = {
120 0, /* dwSize - unused */
121 0, /* dwObjsize - unused */
122 0, /* dwFlags - unused */
123 sizeof(Wine_InternalMouseData),
124 WINE_INTERNALMOUSE_NUM_OBJS, /* dwNumObjs */
125 Wine_InternalMouseObjectFormat
128 static ICOM_VTABLE(IDirectInputA) ddiavt;
129 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt;
130 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt;
132 typedef struct IDirectInputAImpl IDirectInputAImpl;
133 typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
134 typedef struct SysKeyboardAImpl SysKeyboardAImpl;
135 typedef struct SysMouseAImpl SysMouseAImpl;
137 struct IDirectInputDevice2AImpl
139 ICOM_VFIELD(IDirectInputDevice2A);
140 DWORD ref;
141 GUID guid;
144 struct SysKeyboardAImpl
146 /* IDirectInputDevice2AImpl */
147 ICOM_VFIELD(IDirectInputDevice2A);
148 DWORD ref;
149 GUID guid;
150 /* SysKeyboardAImpl */
151 BYTE keystate[256];
152 KEYBOARD_CONFIG initial_config;
153 int acquired;
156 #ifdef HAVE_LINUX_22_JOYSTICK_API
157 typedef struct JoystickAImpl JoystickAImpl;
158 static ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt;
159 struct JoystickAImpl
161 /* IDirectInputDevice2AImpl */
162 ICOM_VFIELD(IDirectInputDevice2A);
163 DWORD ref;
164 GUID guid;
166 /* joystick private */
167 int joyfd;
168 LPDIDATAFORMAT df;
169 HANDLE hEvent;
170 LONG lMin,lMax,deadzone;
171 LPDIDEVICEOBJECTDATA data_queue;
172 int queue_pos, queue_len;
173 DIJOYSTATE js;
175 #endif
177 struct SysMouseAImpl
179 /* IDirectInputDevice2AImpl */
180 ICOM_VFIELD(IDirectInputDevice2A);
181 DWORD ref;
182 GUID guid;
184 /* The current data format and the conversion between internal
185 and external data formats */
186 LPDIDATAFORMAT df;
187 DataFormat *wine_df;
188 int offset_array[5];
190 /* SysMouseAImpl */
191 BYTE absolute;
192 /* Previous position for relative moves */
193 LONG prevX, prevY;
194 LPMOUSE_EVENT_PROC prev_handler;
195 HWND win;
196 DWORD win_centerX, win_centerY;
197 LPDIDEVICEOBJECTDATA data_queue;
198 int queue_pos, queue_len;
199 int need_warp;
200 int acquired;
201 HANDLE hEvent;
202 CRITICAL_SECTION crit;
204 /* This is for mouse reporting. */
205 Wine_InternalMouseData m_state;
208 static int evsequence=0;
211 /* UIDs for Wine "drivers".
212 When enumerating each device supporting DInput, they have two UIDs :
213 - the 'windows' UID
214 - a vendor UID */
215 #ifdef HAVE_LINUX_22_JOYSTICK_API
216 static GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
217 0x9e573ed9,
218 0x7734,
219 0x11d2,
220 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
222 #endif
223 static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
224 0x9e573ed8,
225 0x7734,
226 0x11d2,
227 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
229 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
230 0x0ab8648a,
231 0x7735,
232 0x11d2,
233 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
236 /* FIXME: This is ugly and not thread safe :/ */
237 static IDirectInputDevice2A* current_lock = NULL;
239 /******************************************************************************
240 * Various debugging tools
242 static void _dump_cooperativelevel(DWORD dwFlags) {
243 int i;
244 const struct {
245 DWORD mask;
246 char *name;
247 } flags[] = {
248 #define FE(x) { x, #x},
249 FE(DISCL_BACKGROUND)
250 FE(DISCL_EXCLUSIVE)
251 FE(DISCL_FOREGROUND)
252 FE(DISCL_NONEXCLUSIVE)
253 #undef FE
255 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
256 if (flags[i].mask & dwFlags)
257 DPRINTF("%s ",flags[i].name);
258 DPRINTF("\n");
261 static void _dump_EnumObjects_flags(DWORD dwFlags) {
262 int i;
263 const struct {
264 DWORD mask;
265 char *name;
266 } flags[] = {
267 #define FE(x) { x, #x},
268 FE(DIDFT_ABSAXIS)
269 FE(DIDFT_ALL)
270 FE(DIDFT_AXIS)
271 FE(DIDFT_BUTTON)
272 FE(DIDFT_COLLECTION)
273 FE(DIDFT_FFACTUATOR)
274 FE(DIDFT_FFEFFECTTRIGGER)
275 FE(DIDFT_NOCOLLECTION)
276 FE(DIDFT_NODATA)
277 FE(DIDFT_OUTPUT)
278 FE(DIDFT_POV)
279 FE(DIDFT_PSHBUTTON)
280 FE(DIDFT_RELAXIS)
281 FE(DIDFT_TGLBUTTON)
282 #undef FE
284 if (dwFlags == DIDFT_ALL) {
285 DPRINTF("DIDFT_ALL");
286 return;
288 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
289 if (flags[i].mask & dwFlags)
290 DPRINTF("%s ",flags[i].name);
291 if (dwFlags & DIDFT_INSTANCEMASK)
292 DPRINTF("Instance(%04lx) ", dwFlags >> 8);
295 static void _dump_DIPROPHEADER(DIPROPHEADER *diph) {
296 DPRINTF(" - dwObj = 0x%08lx\n", diph->dwObj);
297 DPRINTF(" - dwHow = %s\n",
298 ((diph->dwHow == DIPH_DEVICE) ? "DIPH_DEVICE" :
299 ((diph->dwHow == DIPH_BYOFFSET) ? "DIPH_BYOFFSET" :
300 ((diph->dwHow == DIPH_BYID)) ? "DIPH_BYID" : "unknown")));
303 static void _dump_OBJECTINSTANCE(DIDEVICEOBJECTINSTANCE *ddoi) {
304 if (TRACE_ON(dinput)) {
305 DPRINTF(" - enumerating : 0x%08lx - %2ld - 0x%08lx - %s\n",
306 ddoi->guidType.Data1, ddoi->dwOfs, ddoi->dwType, ddoi->tszName);
310 struct IDirectInputAImpl
312 ICOM_VFIELD(IDirectInputA);
313 DWORD ref;
316 /* Conversion between internal data buffer and external data buffer */
317 static void fill_DataFormat(void *out, void *in, DataFormat *df) {
318 int i;
319 char *in_c = (char *) in;
320 char *out_c = (char *) out;
322 if (df->dt == NULL) {
323 /* This means that the app uses Wine's internal data format */
324 memcpy(out, in, df->internal_format_size);
325 } else {
326 for (i = 0; i < df->size; i++) {
327 if (df->dt[i].offset_in >= 0) {
328 switch (df->dt[i].size) {
329 case 1:
330 TRACE("Copying (c) to %d from %d (value %d)\n",
331 df->dt[i].offset_out, df->dt[i].offset_in, *((char *) (in_c + df->dt[i].offset_in)));
332 *((char *) (out_c + df->dt[i].offset_out)) = *((char *) (in_c + df->dt[i].offset_in));
333 break;
335 case 2:
336 TRACE("Copying (s) to %d from %d (value %d)\n",
337 df->dt[i].offset_out, df->dt[i].offset_in, *((short *) (in_c + df->dt[i].offset_in)));
338 *((short *) (out_c + df->dt[i].offset_out)) = *((short *) (in_c + df->dt[i].offset_in));
339 break;
341 case 4:
342 TRACE("Copying (i) to %d from %d (value %d)\n",
343 df->dt[i].offset_out, df->dt[i].offset_in, *((int *) (in_c + df->dt[i].offset_in)));
344 *((int *) (out_c + df->dt[i].offset_out)) = *((int *) (in_c + df->dt[i].offset_in));
345 break;
347 default:
348 memcpy((out_c + df->dt[i].offset_out), (in_c + df->dt[i].offset_in), df->dt[i].size);
350 } else {
351 switch (df->dt[i].size) {
352 case 1:
353 TRACE("Copying (c) to %d default value %d\n",
354 df->dt[i].offset_out, df->dt[i].value);
355 *((char *) (out_c + df->dt[i].offset_out)) = (char) df->dt[i].value;
356 break;
358 case 2:
359 TRACE("Copying (s) to %d default value %d\n",
360 df->dt[i].offset_out, df->dt[i].value);
361 *((short *) (out_c + df->dt[i].offset_out)) = (short) df->dt[i].value;
362 break;
364 case 4:
365 TRACE("Copying (i) to %d default value %d\n",
366 df->dt[i].offset_out, df->dt[i].value);
367 *((int *) (out_c + df->dt[i].offset_out)) = (int) df->dt[i].value;
368 break;
370 default:
371 memset((out_c + df->dt[i].offset_out), df->dt[i].size, 0);
378 static DataFormat *create_DataFormat(DIDATAFORMAT *wine_format, DIDATAFORMAT *asked_format, int *offset) {
379 DataFormat *ret;
380 DataTransform *dt;
381 int i, j;
382 int same = 1;
383 int *done;
384 int index = 0;
386 ret = (DataFormat *) HeapAlloc(GetProcessHeap(), 0, sizeof(DataFormat));
388 done = (int *) HeapAlloc(GetProcessHeap(), 0, sizeof(int) * asked_format->dwNumObjs);
389 memset(done, 0, sizeof(int) * asked_format->dwNumObjs);
391 dt = (DataTransform *) HeapAlloc(GetProcessHeap(), 0, asked_format->dwNumObjs * sizeof(DataTransform));
393 TRACE("Creating DataTransorm : \n");
395 for (i = 0; i < wine_format->dwNumObjs; i++) {
396 offset[i] = -1;
398 for (j = 0; j < asked_format->dwNumObjs; j++) {
399 if (done[j] == 1)
400 continue;
402 if (((asked_format->rgodf[j].pguid == NULL) || (IsEqualGUID(wine_format->rgodf[i].pguid, asked_format->rgodf[j].pguid)))
404 (wine_format->rgodf[i].dwType & asked_format->rgodf[j].dwType)) {
406 done[j] = 1;
408 TRACE("Matching : \n");
409 TRACE(" - Asked (%d) : %s - Ofs = %3ld - (Type = 0x%02x | Instance = %04x)\n",
410 j, debugstr_guid(asked_format->rgodf[j].pguid),
411 asked_format->rgodf[j].dwOfs,
412 DIDFT_GETTYPE(asked_format->rgodf[j].dwType), DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType));
414 TRACE(" - Wine (%d) : %s - Ofs = %3ld - (Type = 0x%02x | Instance = %04x)\n",
415 j, debugstr_guid(wine_format->rgodf[i].pguid),
416 wine_format->rgodf[i].dwOfs,
417 DIDFT_GETTYPE(wine_format->rgodf[i].dwType), DIDFT_GETINSTANCE(wine_format->rgodf[i].dwType));
419 if (wine_format->rgodf[i].dwType & DIDFT_BUTTON)
420 dt[index].size = sizeof(BYTE);
421 else
422 dt[index].size = sizeof(DWORD);
423 dt[index].offset_in = wine_format ->rgodf[i].dwOfs;
424 dt[index].offset_out = asked_format->rgodf[j].dwOfs;
425 dt[index].value = 0;
426 index++;
428 if (wine_format->rgodf[i].dwOfs != asked_format->rgodf[j].dwOfs)
429 same = 0;
431 offset[i] = asked_format->rgodf[j].dwOfs;
432 break;
436 if (j == asked_format->dwNumObjs)
437 same = 0;
440 TRACE("Setting to default value :\n");
441 for (j = 0; j < asked_format->dwNumObjs; j++) {
442 if (done[j] == 0) {
443 TRACE(" - Asked (%d) : %s - Ofs = %3ld - (Type = 0x%02x | Instance = %04x)\n",
444 j, debugstr_guid(asked_format->rgodf[j].pguid),
445 asked_format->rgodf[j].dwOfs,
446 DIDFT_GETTYPE(asked_format->rgodf[j].dwType), DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType));
449 if (asked_format->rgodf[j].dwType & DIDFT_BUTTON)
450 dt[index].size = sizeof(BYTE);
451 else
452 dt[index].size = sizeof(DWORD);
453 dt[index].offset_in = -1;
454 dt[index].offset_out = asked_format->rgodf[j].dwOfs;
455 dt[index].value = 0;
456 index++;
458 same = 0;
462 ret->internal_format_size = wine_format->dwDataSize;
463 ret->size = index;
464 if (same) {
465 ret->dt = NULL;
466 HeapFree(GetProcessHeap(), 0, dt);
467 } else {
468 ret->dt = dt;
471 HeapFree(GetProcessHeap(), 0, done);
473 return ret;
476 /******************************************************************************
477 * DirectInputCreate32A
479 HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
481 IDirectInputAImpl* This;
482 TRACE("(0x%08lx,%04lx,%p,%p)\n",
483 (DWORD)hinst,dwVersion,ppDI,punkOuter
485 This = (IDirectInputAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputAImpl));
486 This->ref = 1;
487 ICOM_VTBL(This) = &ddiavt;
488 *ppDI=(IDirectInputA*)This;
489 return 0;
491 /******************************************************************************
492 * IDirectInputA_EnumDevices
494 static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
495 LPDIRECTINPUTA iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
496 LPVOID pvRef, DWORD dwFlags
499 ICOM_THIS(IDirectInputAImpl,iface);
500 DIDEVICEINSTANCEA devInstance;
501 int ret;
503 TRACE("(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
505 devInstance.dwSize = sizeof(DIDEVICEINSTANCEA);
506 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
507 /* Return keyboard */
508 devInstance.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
509 devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
510 devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
511 strcpy(devInstance.tszInstanceName, "Keyboard");
512 strcpy(devInstance.tszProductName, "Wine Keyboard");
514 ret = lpCallback(&devInstance, pvRef);
515 TRACE("Keyboard registered\n");
516 if (ret == DIENUM_STOP)
517 return 0;
520 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_MOUSE)) {
521 /* Return mouse */
522 devInstance.guidInstance = GUID_SysMouse;/* DInput's GUID */
523 devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
524 devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
525 strcpy(devInstance.tszInstanceName, "Mouse");
526 strcpy(devInstance.tszProductName, "Wine Mouse");
528 ret = lpCallback(&devInstance, pvRef);
529 TRACE("Mouse registered\n");
530 if (ret == DIENUM_STOP)
531 return 0;
533 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_JOYSTICK)) {
534 /* check whether we have a joystick */
535 #ifdef HAVE_LINUX_22_JOYSTICK_API
536 if ( (access(JOYDEV,O_RDONLY)!=-1) ||
537 (errno!=ENODEV && errno!=ENOENT)
539 /* Return joystick */
540 devInstance.guidInstance = GUID_Joystick;
541 devInstance.guidProduct = DInput_Wine_Joystick_GUID;
542 /* we only support traditional joysticks for now */
543 devInstance.dwDevType = DIDEVTYPE_JOYSTICK | DIDEVTYPEJOYSTICK_TRADITIONAL;
544 strcpy(devInstance.tszInstanceName, "Joystick");
545 /* ioctl JSIOCGNAME(len) */
546 strcpy(devInstance.tszProductName, "Wine Joystick");
548 ret = lpCallback(&devInstance,pvRef);
549 TRACE("Joystick registered\n");
550 if (ret == DIENUM_STOP)
551 return 0;
553 #endif
555 return 0;
558 static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUTA iface)
560 ICOM_THIS(IDirectInputAImpl,iface);
561 return ++(This->ref);
564 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
566 ICOM_THIS(IDirectInputAImpl,iface);
567 if (!(--This->ref)) {
568 HeapFree(GetProcessHeap(),0,This);
569 return 0;
571 return This->ref;
574 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
575 LPDIRECTINPUTA iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
576 LPUNKNOWN punk
578 ICOM_THIS(IDirectInputAImpl,iface);
580 TRACE("(this=%p,%s,%p,%p)\n",This,debugstr_guid(rguid),pdev,punk);
581 if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) || /* Generic Keyboard */
582 (IsEqualGUID(&DInput_Wine_Keyboard_GUID,rguid))) { /* Wine Keyboard */
583 SysKeyboardAImpl* newDevice;
584 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
585 newDevice->ref = 1;
586 ICOM_VTBL(newDevice) = &SysKeyboardAvt;
587 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
588 memset(newDevice->keystate,0,256);
589 *pdev=(IDirectInputDeviceA*)newDevice;
591 TRACE("Creating a Keyboard device (%p)\n", newDevice);
592 return DI_OK;
594 if ((IsEqualGUID(&GUID_SysMouse,rguid)) || /* Generic Mouse */
595 (IsEqualGUID(&DInput_Wine_Mouse_GUID,rguid))) { /* Wine Mouse */
596 SysMouseAImpl* newDevice;
597 int offset_array[5] = {
598 FIELD_OFFSET(Wine_InternalMouseData, lX),
599 FIELD_OFFSET(Wine_InternalMouseData, lY),
600 FIELD_OFFSET(Wine_InternalMouseData, rgbButtons) + 0,
601 FIELD_OFFSET(Wine_InternalMouseData, rgbButtons) + 1,
602 FIELD_OFFSET(Wine_InternalMouseData, rgbButtons) + 2
605 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
606 newDevice->ref = 1;
607 ICOM_VTBL(newDevice) = &SysMouseAvt;
608 InitializeCriticalSection(&(newDevice->crit));
609 MakeCriticalSectionGlobal(&(newDevice->crit));
610 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
611 *pdev=(IDirectInputDeviceA*)newDevice;
613 /* Per default, Wine uses its internal data format */
614 newDevice->df = &Wine_InternalMouseFormat;
615 memcpy(newDevice->offset_array, offset_array, 5 * sizeof(int));
616 newDevice->wine_df = (DataFormat *) HeapAlloc(GetProcessHeap(), 0, sizeof(DataFormat));
617 newDevice->wine_df->size = 0;
618 newDevice->wine_df->internal_format_size = Wine_InternalMouseFormat.dwDataSize;
619 newDevice->wine_df->dt = NULL;
621 TRACE("Creating a Mouse device (%p)\n", newDevice);
622 return DI_OK;
624 #ifdef HAVE_LINUX_22_JOYSTICK_API
625 if ((IsEqualGUID(&GUID_Joystick,rguid)) ||
626 (IsEqualGUID(&DInput_Wine_Joystick_GUID,rguid))) {
627 JoystickAImpl* newDevice;
628 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickAImpl));
629 newDevice->ref = 1;
630 ICOM_VTBL(newDevice) = &JoystickAvt;
631 newDevice->joyfd = -1;
632 newDevice->lMin = -32768;
633 newDevice->lMax = +32767;
634 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
635 *pdev=(IDirectInputDeviceA*)newDevice;
637 TRACE("Creating a Joystick device (%p)\n", newDevice);
638 return DI_OK;
640 #endif
641 return E_FAIL;
644 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
645 LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj
647 ICOM_THIS(IDirectInputAImpl,iface);
649 TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
650 if (IsEqualGUID(&IID_IUnknown,riid)) {
651 IDirectInputA_AddRef(iface);
652 *ppobj = This;
653 return 0;
655 if (IsEqualGUID(&IID_IDirectInputA,riid)) {
656 IDirectInputA_AddRef(iface);
657 *ppobj = This;
658 return 0;
660 TRACE("Unsupported interface !\n");
661 return E_FAIL;
664 static HRESULT WINAPI IDirectInputAImpl_Initialize(
665 LPDIRECTINPUTA iface,HINSTANCE hinst,DWORD x
667 return DIERR_ALREADYINITIALIZED;
670 static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
671 REFGUID rguid) {
672 ICOM_THIS(IDirectInputAImpl,iface);
674 FIXME("(%p)->(%s): stub\n",This,debugstr_guid(rguid));
676 return DI_OK;
679 static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUTA iface,
680 HWND hwndOwner,
681 DWORD dwFlags) {
682 ICOM_THIS(IDirectInputAImpl,iface);
683 FIXME("(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
685 return DI_OK;
688 static ICOM_VTABLE(IDirectInputA) ddiavt =
690 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
691 IDirectInputAImpl_QueryInterface,
692 IDirectInputAImpl_AddRef,
693 IDirectInputAImpl_Release,
694 IDirectInputAImpl_CreateDevice,
695 IDirectInputAImpl_EnumDevices,
696 IDirectInputAImpl_GetDeviceStatus,
697 IDirectInputAImpl_RunControlPanel,
698 IDirectInputAImpl_Initialize
701 /******************************************************************************
702 * IDirectInputDeviceA
705 static HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
706 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
709 int i;
710 TRACE(dinput,"(this=%p,%p)\n",This,df);
712 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
713 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
714 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
715 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
716 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
718 for (i=0;i<df->dwNumObjs;i++) {
719 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,debugstr_guid(df->rgodf[i].pguid));
720 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
721 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
722 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
725 return 0;
728 static HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
729 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
731 ICOM_THIS(IDirectInputDevice2AImpl,iface);
732 TRACE("(this=%p,0x%08lx,0x%08lx)\n",This,(DWORD)hwnd,dwflags);
733 if (TRACE_ON(dinput))
734 _dump_cooperativelevel(dwflags);
735 return 0;
738 static HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
739 LPDIRECTINPUTDEVICE2A iface,HANDLE hnd
741 ICOM_THIS(IDirectInputDevice2AImpl,iface);
742 FIXME("(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
743 return 0;
746 static ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE2A iface)
748 ICOM_THIS(IDirectInputDevice2AImpl,iface);
749 This->ref--;
750 if (This->ref)
751 return This->ref;
752 HeapFree(GetProcessHeap(),0,This);
753 return 0;
756 static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
757 LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
760 ICOM_THIS(SysKeyboardAImpl,iface);
762 TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
763 TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
764 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
765 if (!HIWORD(rguid)) {
766 switch ((DWORD)rguid) {
767 case (DWORD) DIPROP_BUFFERSIZE: {
768 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
770 TRACE("(buffersize=%ld)\n",pd->dwData);
771 break;
773 default:
774 WARN("Unknown type %ld\n",(DWORD)rguid);
775 break;
778 return 0;
781 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
782 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
785 return KEYBOARD_Driver->pGetDIState(len, ptr)?DI_OK:E_FAIL;
788 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
789 LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
790 LPDWORD entries,DWORD flags
793 ICOM_THIS(SysKeyboardAImpl,iface);
794 HRESULT ret;
795 int i;
797 TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
798 This,dodsize,dod,entries,entries?*entries:0,flags);
800 ret=KEYBOARD_Driver->pGetDIData(
801 This->keystate, dodsize, dod, entries, flags)?DI_OK:E_FAIL;
802 for (i=0;i<*entries;i++) {
803 dod[i].dwTimeStamp = GetTickCount();
804 dod[i].dwSequence = evsequence++;
806 return ret;
809 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
811 ICOM_THIS(SysKeyboardAImpl,iface);
813 TRACE("(this=%p)\n",This);
815 if (This->acquired == 0) {
816 KEYBOARD_CONFIG no_auto;
818 /* Save the original config */
819 KEYBOARD_Driver->pGetKeyboardConfig(&(This->initial_config));
821 /* Now, remove auto-repeat */
822 no_auto.auto_repeat = FALSE;
823 KEYBOARD_Driver->pSetKeyboardConfig(&no_auto, WINE_KEYBOARD_CONFIG_AUTO_REPEAT);
825 This->acquired = 1;
828 return DI_OK;
831 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
833 ICOM_THIS(SysKeyboardAImpl,iface);
834 TRACE("(this=%p)\n",This);
836 if (This->acquired == 1) {
837 /* Restore the original configuration */
838 KEYBOARD_Driver->pSetKeyboardConfig(&(This->initial_config), 0xFFFFFFFF);
839 This->acquired = 0;
840 } else {
841 ERR("Unacquiring a not-acquired device !!!\n");
844 return DI_OK;
847 /******************************************************************************
848 * GetCapabilities : get the device capablitites
850 static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(
851 LPDIRECTINPUTDEVICE2A iface,
852 LPDIDEVCAPS lpDIDevCaps)
854 ICOM_THIS(SysMouseAImpl,iface);
856 TRACE("(this=%p,%p)\n",This,lpDIDevCaps);
858 if (lpDIDevCaps->dwSize == sizeof(DIDEVCAPS)) {
859 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
860 lpDIDevCaps->dwDevType = DIDEVTYPE_KEYBOARD;
861 lpDIDevCaps->dwAxes = 0;
862 lpDIDevCaps->dwButtons = 0;
863 lpDIDevCaps->dwPOVs = 0;
864 lpDIDevCaps->dwFFSamplePeriod = 0;
865 lpDIDevCaps->dwFFMinTimeResolution = 0;
866 lpDIDevCaps->dwFirmwareRevision = 100;
867 lpDIDevCaps->dwHardwareRevision = 100;
868 lpDIDevCaps->dwFFDriverVersion = 0;
869 } else {
870 /* DirectX 3.0 */
871 FIXME("DirectX 3.0 not supported....\n");
874 return DI_OK;
877 static HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
878 LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
881 ICOM_THIS(IDirectInputDevice2AImpl,iface);
883 TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
884 if (IsEqualGUID(&IID_IUnknown,riid)) {
885 IDirectInputDevice2_AddRef(iface);
886 *ppobj = This;
887 return 0;
889 if (IsEqualGUID(&IID_IDirectInputDeviceA,riid)) {
890 IDirectInputDevice2_AddRef(iface);
891 *ppobj = This;
892 return 0;
894 if (IsEqualGUID(&IID_IDirectInputDevice2A,riid)) {
895 IDirectInputDevice2_AddRef(iface);
896 *ppobj = This;
897 return 0;
899 TRACE("Unsupported interface !\n");
900 return E_FAIL;
903 static ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
904 LPDIRECTINPUTDEVICE2A iface)
906 ICOM_THIS(IDirectInputDevice2AImpl,iface);
907 return ++This->ref;
910 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
911 LPDIRECTINPUTDEVICE2A iface,
912 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
913 LPVOID lpvRef,
914 DWORD dwFlags)
916 FIXME("(this=%p,%p,%p,%08lx): stub!\n", iface, lpCallback, lpvRef, dwFlags);
917 if (TRACE_ON(dinput)) {
918 DPRINTF(" - flags = ");
919 _dump_EnumObjects_flags(dwFlags);
920 DPRINTF("\n");
923 return DI_OK;
926 static HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
927 LPDIRECTINPUTDEVICE2A iface,
928 REFGUID rguid,
929 LPDIPROPHEADER pdiph)
931 FIXME("(this=%p,%s,%p): stub!\n",
932 iface, debugstr_guid(rguid), pdiph);
934 if (TRACE_ON(dinput))
935 _dump_DIPROPHEADER(pdiph);
937 return DI_OK;
940 static HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
941 LPDIRECTINPUTDEVICE2A iface,
942 LPDIDEVICEOBJECTINSTANCEA pdidoi,
943 DWORD dwObj,
944 DWORD dwHow)
946 FIXME("(this=%p,%p,%ld,0x%08lx): stub!\n",
947 iface, pdidoi, dwObj, dwHow);
949 return DI_OK;
952 static HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
953 LPDIRECTINPUTDEVICE2A iface,
954 LPDIDEVICEINSTANCEA pdidi)
956 FIXME("(this=%p,%p): stub!\n",
957 iface, pdidi);
959 return DI_OK;
962 static HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
963 LPDIRECTINPUTDEVICE2A iface,
964 HWND hwndOwner,
965 DWORD dwFlags)
967 FIXME("(this=%p,0x%08x,0x%08lx): stub!\n",
968 iface, hwndOwner, dwFlags);
970 return DI_OK;
973 static HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
974 LPDIRECTINPUTDEVICE2A iface,
975 HINSTANCE hinst,
976 DWORD dwVersion,
977 REFGUID rguid)
979 FIXME("(this=%p,%d,%ld,%s): stub!\n",
980 iface, hinst, dwVersion, debugstr_guid(rguid));
981 return DI_OK;
984 /******************************************************************************
985 * IDirectInputDevice2A
988 static HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
989 LPDIRECTINPUTDEVICE2A iface,
990 REFGUID rguid,
991 LPCDIEFFECT lpeff,
992 LPDIRECTINPUTEFFECT *ppdef,
993 LPUNKNOWN pUnkOuter)
995 FIXME("(this=%p,%s,%p,%p,%p): stub!\n",
996 iface, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter);
997 return DI_OK;
1000 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
1001 LPDIRECTINPUTDEVICE2A iface,
1002 LPDIENUMEFFECTSCALLBACKA lpCallback,
1003 LPVOID lpvRef,
1004 DWORD dwFlags)
1006 FIXME("(this=%p,%p,%p,0x%08lx): stub!\n",
1007 iface, lpCallback, lpvRef, dwFlags);
1009 if (lpCallback)
1010 lpCallback(NULL, lpvRef);
1011 return DI_OK;
1014 static HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
1015 LPDIRECTINPUTDEVICE2A iface,
1016 LPDIEFFECTINFOA lpdei,
1017 REFGUID rguid)
1019 FIXME("(this=%p,%p,%s): stub!\n",
1020 iface, lpdei, debugstr_guid(rguid));
1021 return DI_OK;
1024 static HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
1025 LPDIRECTINPUTDEVICE2A iface,
1026 LPDWORD pdwOut)
1028 FIXME("(this=%p,%p): stub!\n",
1029 iface, pdwOut);
1030 return DI_OK;
1033 static HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
1034 LPDIRECTINPUTDEVICE2A iface,
1035 DWORD dwFlags)
1037 FIXME("(this=%p,0x%08lx): stub!\n",
1038 iface, dwFlags);
1039 return DI_OK;
1042 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
1043 LPDIRECTINPUTDEVICE2A iface,
1044 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
1045 LPVOID lpvRef,
1046 DWORD dwFlags)
1048 FIXME("(this=%p,%p,%p,0x%08lx): stub!\n",
1049 iface, lpCallback, lpvRef, dwFlags);
1050 if (lpCallback)
1051 lpCallback(NULL, lpvRef);
1052 return DI_OK;
1055 static HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
1056 LPDIRECTINPUTDEVICE2A iface,
1057 LPDIEFFESCAPE lpDIEEsc)
1059 FIXME("(this=%p,%p): stub!\n",
1060 iface, lpDIEEsc);
1061 return DI_OK;
1064 static HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
1065 LPDIRECTINPUTDEVICE2A iface)
1067 FIXME("(this=%p): stub!\n",
1068 iface);
1069 return DI_OK;
1072 static HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
1073 LPDIRECTINPUTDEVICE2A iface,
1074 DWORD cbObjectData,
1075 LPDIDEVICEOBJECTDATA rgdod,
1076 LPDWORD pdwInOut,
1077 DWORD dwFlags)
1079 FIXME("(this=%p,0x%08lx,%p,%p,0x%08lx): stub!\n",
1080 iface, cbObjectData, rgdod, pdwInOut, dwFlags);
1082 return DI_OK;
1085 /******************************************************************************
1086 * SysMouseA (DInput Mouse support)
1089 /******************************************************************************
1090 * Release : release the mouse buffer.
1092 static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
1094 ICOM_THIS(SysMouseAImpl,iface);
1096 This->ref--;
1097 if (This->ref)
1098 return This->ref;
1100 /* Free the data queue */
1101 if (This->data_queue != NULL)
1102 HeapFree(GetProcessHeap(),0,This->data_queue);
1104 /* Install the previous event handler (in case of releasing an aquired
1105 mouse device) */
1106 if (This->prev_handler != NULL)
1107 MOUSE_Enable(This->prev_handler);
1108 DeleteCriticalSection(&(This->crit));
1110 /* Free the DataFormat */
1111 if (This->df != &(Wine_InternalMouseFormat)) {
1112 HeapFree(GetProcessHeap(), 0, This->df->rgodf);
1113 HeapFree(GetProcessHeap(), 0, This->df);
1116 HeapFree(GetProcessHeap(),0,This);
1117 return 0;
1121 /******************************************************************************
1122 * SetCooperativeLevel : store the window in which we will do our
1123 * grabbing.
1125 static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
1126 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
1129 ICOM_THIS(SysMouseAImpl,iface);
1131 TRACE("(this=%p,0x%08lx,0x%08lx)\n",This,(DWORD)hwnd,dwflags);
1133 if (TRACE_ON(dinput))
1134 _dump_cooperativelevel(dwflags);
1136 /* Store the window which asks for the mouse */
1137 This->win = hwnd;
1139 return 0;
1143 /******************************************************************************
1144 * SetDataFormat : the application can choose the format of the data
1145 * the device driver sends back with GetDeviceState.
1147 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
1148 * in absolute and relative mode.
1150 static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
1151 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
1154 ICOM_THIS(SysMouseAImpl,iface);
1155 int i;
1157 TRACE("(this=%p,%p)\n",This,df);
1159 TRACE("(df.dwSize=%ld)\n",df->dwSize);
1160 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
1161 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
1162 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
1163 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
1165 for (i=0;i<df->dwNumObjs;i++) {
1167 TRACE("df.rgodf[%d].guid %s (%p)\n",i, debugstr_guid(df->rgodf[i].pguid), df->rgodf[i].pguid);
1168 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
1169 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
1170 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
1173 /* Check if the mouse is in absolute or relative mode */
1174 if (df->dwFlags == DIDF_ABSAXIS)
1175 This->absolute = 1;
1176 else if (df->dwFlags == DIDF_RELAXIS)
1177 This->absolute = 0;
1178 else
1179 ERR("Neither absolute nor relative flag set.");
1181 /* Store the new data format */
1182 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize);
1183 memcpy(This->df, df, df->dwSize);
1184 This->df->rgodf = HeapAlloc(GetProcessHeap(),0,df->dwNumObjs*df->dwObjSize);
1185 memcpy(This->df->rgodf,df->rgodf,df->dwNumObjs*df->dwObjSize);
1187 /* Prepare all the data-conversion filters */
1188 This->wine_df = create_DataFormat(&(Wine_InternalMouseFormat), df, This->offset_array);
1190 return 0;
1193 #define GEN_EVENT(offset,data,xtime,seq) \
1195 if ((offset >= 0) && (This->queue_pos < This->queue_len)) { \
1196 This->data_queue[This->queue_pos].dwOfs = offset; \
1197 This->data_queue[This->queue_pos].dwData = data; \
1198 This->data_queue[This->queue_pos].dwTimeStamp = xtime; \
1199 This->data_queue[This->queue_pos].dwSequence = seq; \
1200 This->queue_pos++; \
1205 /* Our private mouse event handler */
1206 static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
1207 DWORD cButtons, DWORD dwExtraInfo )
1209 DWORD posX, posY, keyState, xtime, extra;
1210 SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
1212 EnterCriticalSection(&(This->crit));
1213 /* Mouse moved -> send event if asked */
1214 if (This->hEvent)
1215 SetEvent(This->hEvent);
1217 if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
1218 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
1219 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
1220 keyState = wme->keyState;
1221 xtime = wme->time;
1222 extra = (DWORD)wme->hWnd;
1224 if ((dwFlags & MOUSEEVENTF_MOVE) &&
1225 (dwFlags & MOUSEEVENTF_ABSOLUTE)) {
1226 posX = (dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
1227 posY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
1228 } else {
1229 posX = This->prevX;
1230 posY = This->prevY;
1232 } else {
1233 ERR("Mouse event not supported...\n");
1234 LeaveCriticalSection(&(This->crit));
1235 return ;
1238 TRACE(" %ld %ld ", posX, posY);
1240 if ( dwFlags & MOUSEEVENTF_MOVE ) {
1241 if (This->absolute) {
1242 if (posX != This->prevX)
1243 GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], posX, xtime, 0);
1244 if (posY != This->prevY)
1245 GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], posY, xtime, 0);
1246 } else {
1247 /* Relative mouse input : the real fun starts here... */
1248 if (This->need_warp) {
1249 if (posX != This->prevX)
1250 GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], posX - This->prevX, xtime, evsequence++);
1251 if (posY != This->prevY)
1252 GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], posY - This->prevY, xtime, evsequence++);
1253 } else {
1254 /* This is the first time the event handler has been called after a
1255 GetData of GetState. */
1256 if (posX != This->win_centerX) {
1257 GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], posX - This->win_centerX, xtime, evsequence++);
1258 This->need_warp = 1;
1261 if (posY != This->win_centerY) {
1262 GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], posY - This->win_centerY, xtime, evsequence++);
1263 This->need_warp = 1;
1268 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
1269 if (TRACE_ON(dinput))
1270 DPRINTF(" LD ");
1272 GEN_EVENT(This->offset_array[WINE_MOUSE_L_POSITION], 0xFF, xtime, evsequence++);
1273 This->m_state.rgbButtons[0] = 0xFF;
1275 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
1276 if (TRACE_ON(dinput))
1277 DPRINTF(" LU ");
1279 GEN_EVENT(This->offset_array[WINE_MOUSE_L_POSITION], 0x00, xtime, evsequence++);
1280 This->m_state.rgbButtons[0] = 0x00;
1282 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
1283 if (TRACE_ON(dinput))
1284 DPRINTF(" RD ");
1286 GEN_EVENT(This->offset_array[WINE_MOUSE_R_POSITION], 0xFF, xtime, evsequence++);
1287 This->m_state.rgbButtons[1] = 0xFF;
1289 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
1290 if (TRACE_ON(dinput))
1291 DPRINTF(" RU ");
1293 GEN_EVENT(This->offset_array[WINE_MOUSE_R_POSITION], 0x00, xtime, evsequence++);
1294 This->m_state.rgbButtons[1] = 0x00;
1296 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
1297 if (TRACE_ON(dinput))
1298 DPRINTF(" MD ");
1300 GEN_EVENT(This->offset_array[WINE_MOUSE_M_POSITION], 0xFF, xtime, evsequence++);
1301 This->m_state.rgbButtons[2] = 0xFF;
1303 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
1304 if (TRACE_ON(dinput))
1305 DPRINTF(" MU ");
1307 GEN_EVENT(This->offset_array[WINE_MOUSE_M_POSITION], 0x00, xtime, evsequence++);
1308 This->m_state.rgbButtons[2] = 0x00;
1310 if (TRACE_ON(dinput))
1311 DPRINTF("\n");
1313 This->prevX = posX;
1314 This->prevY = posY;
1316 if (This->absolute) {
1317 This->m_state.lX = posX;
1318 This->m_state.lY = posY;
1319 } else {
1320 This->m_state.lX = posX - This->win_centerX;
1321 This->m_state.lY = posY - This->win_centerY;
1324 LeaveCriticalSection(&(This->crit));
1329 /******************************************************************************
1330 * Acquire : gets exclusive control of the mouse
1332 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1334 ICOM_THIS(SysMouseAImpl,iface);
1335 RECT rect;
1337 TRACE("(this=%p)\n",This);
1339 if (This->acquired == 0) {
1340 POINT point;
1342 /* This stores the current mouse handler. */
1343 This->prev_handler = mouse_event;
1345 /* Store (in a global variable) the current lock */
1346 current_lock = (IDirectInputDevice2A*)This;
1348 /* Init the mouse state */
1349 This->m_state.lX = PosX;
1350 This->m_state.lY = PosY;
1351 This->m_state.rgbButtons[0] = (MouseButtonsStates[0] ? 0xFF : 0x00);
1352 This->m_state.rgbButtons[1] = (MouseButtonsStates[1] ? 0xFF : 0x00);
1353 This->m_state.rgbButtons[2] = (MouseButtonsStates[2] ? 0xFF : 0x00);
1355 /* Install our own mouse event handler */
1356 MOUSE_Enable(dinput_mouse_event);
1358 /* Get the window dimension and find the center */
1359 GetWindowRect(This->win, &rect);
1360 This->win_centerX = (rect.right - rect.left) / 2;
1361 This->win_centerY = (rect.bottom - rect.top ) / 2;
1363 /* Warp the mouse to the center of the window */
1364 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1365 point.x = This->win_centerX;
1366 point.y = This->win_centerY;
1367 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1368 DISPLAY_MoveCursor(point.x, point.y);
1370 This->acquired = 1;
1372 return 0;
1375 /******************************************************************************
1376 * Unacquire : frees the mouse
1378 static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1380 ICOM_THIS(SysMouseAImpl,iface);
1382 TRACE("(this=%p)\n",This);
1384 /* Reinstall previous mouse event handler */
1385 MOUSE_Enable(This->prev_handler);
1386 This->prev_handler = NULL;
1388 /* No more locks */
1389 current_lock = NULL;
1391 /* Unacquire device */
1392 This->acquired = 0;
1394 return 0;
1397 /******************************************************************************
1398 * GetDeviceState : returns the "state" of the mouse.
1400 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
1401 * supported.
1403 static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
1404 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1406 ICOM_THIS(SysMouseAImpl,iface);
1408 EnterCriticalSection(&(This->crit));
1409 TRACE("(this=%p,0x%08lx,%p): \n",This,len,ptr);
1411 /* Copy the current mouse state */
1412 fill_DataFormat(ptr, &(This->m_state), This->wine_df);
1414 /* Check if we need to do a mouse warping */
1415 if (This->need_warp) {
1416 POINT point;
1418 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1419 point.x = This->win_centerX;
1420 point.y = This->win_centerY;
1421 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1422 DISPLAY_MoveCursor(point.x, point.y);
1424 This->need_warp = 0;
1427 LeaveCriticalSection(&(This->crit));
1429 TRACE("(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
1430 This->m_state.lX, This->m_state.lY,
1431 This->m_state.rgbButtons[0], This->m_state.rgbButtons[2], This->m_state.rgbButtons[1]);
1433 return 0;
1436 /******************************************************************************
1437 * GetDeviceState : gets buffered input data.
1439 static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1440 DWORD dodsize,
1441 LPDIDEVICEOBJECTDATA dod,
1442 LPDWORD entries,
1443 DWORD flags
1445 ICOM_THIS(SysMouseAImpl,iface);
1447 EnterCriticalSection(&(This->crit));
1448 TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
1450 if (flags & DIGDD_PEEK)
1451 FIXME("DIGDD_PEEK\n");
1453 if (dod == NULL) {
1454 *entries = This->queue_pos;
1455 This->queue_pos = 0;
1456 } else {
1457 /* Check for buffer overflow */
1458 if (This->queue_pos > *entries) {
1459 WARN("Buffer overflow not handled properly yet...\n");
1460 This->queue_pos = *entries;
1462 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1463 ERR("Wrong structure size !\n");
1464 LeaveCriticalSection(&(This->crit));
1465 return DIERR_INVALIDPARAM;
1468 if (This->queue_pos)
1469 TRACE("Application retrieving %d event(s).\n", This->queue_pos);
1471 /* Copy the buffered data into the application queue */
1472 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1473 *entries = This->queue_pos;
1475 /* Reset the event queue */
1476 This->queue_pos = 0;
1478 LeaveCriticalSection(&(This->crit));
1480 #if 0 /* FIXME: seems to create motion events, which fire back at us. */
1481 /* Check if we need to do a mouse warping */
1482 if (This->need_warp) {
1483 POINT point;
1485 TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1486 point.x = This->win_centerX;
1487 point.y = This->win_centerY;
1488 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1490 DISPLAY_MoveCursor(point.x, point.y);
1492 This->need_warp = 0;
1494 #endif
1495 return 0;
1498 /******************************************************************************
1499 * SetProperty : change input device properties
1501 static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1502 REFGUID rguid,
1503 LPCDIPROPHEADER ph)
1505 ICOM_THIS(SysMouseAImpl,iface);
1507 TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
1509 if (!HIWORD(rguid)) {
1510 switch ((DWORD)rguid) {
1511 case (DWORD) DIPROP_BUFFERSIZE: {
1512 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1514 TRACE("buffersize = %ld\n",pd->dwData);
1516 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1517 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1518 This->queue_pos = 0;
1519 This->queue_len = pd->dwData;
1520 break;
1522 default:
1523 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
1524 break;
1528 return 0;
1531 /******************************************************************************
1532 * GetProperty : get input device properties
1534 static HRESULT WINAPI SysMouseAImpl_GetProperty(LPDIRECTINPUTDEVICE2A iface,
1535 REFGUID rguid,
1536 LPDIPROPHEADER pdiph)
1538 ICOM_THIS(SysMouseAImpl,iface);
1540 TRACE("(this=%p,%s,%p): stub!\n",
1541 iface, debugstr_guid(rguid), pdiph);
1543 if (TRACE_ON(dinput))
1544 _dump_DIPROPHEADER(pdiph);
1546 if (!HIWORD(rguid)) {
1547 switch ((DWORD)rguid) {
1548 case (DWORD) DIPROP_BUFFERSIZE: {
1549 LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
1551 TRACE(" return buffersize = %d\n",This->queue_len);
1552 pd->dwData = This->queue_len;
1553 break;
1556 case (DWORD) DIPROP_RANGE: {
1557 LPDIPROPRANGE pr = (LPDIPROPRANGE) pdiph;
1559 if ((pdiph->dwHow == DIPH_BYID) &&
1560 ((pdiph->dwObj == (DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS)) ||
1561 (pdiph->dwObj == (DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS)))) {
1562 /* Querying the range of either the X or the Y axis. As I do
1563 not know the range, do as if the range where
1564 unrestricted...*/
1565 pr->lMin = DIPROPRANGE_NOMIN;
1566 pr->lMax = DIPROPRANGE_NOMAX;
1569 break;
1572 default:
1573 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
1574 break;
1579 return DI_OK;
1584 /******************************************************************************
1585 * SetEventNotification : specifies event to be sent on state change
1587 static HRESULT WINAPI SysMouseAImpl_SetEventNotification(LPDIRECTINPUTDEVICE2A iface,
1588 HANDLE hnd) {
1589 ICOM_THIS(SysMouseAImpl,iface);
1591 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1593 This->hEvent = hnd;
1595 return DI_OK;
1598 /******************************************************************************
1599 * GetCapabilities : get the device capablitites
1601 static HRESULT WINAPI SysMouseAImpl_GetCapabilities(
1602 LPDIRECTINPUTDEVICE2A iface,
1603 LPDIDEVCAPS lpDIDevCaps)
1605 ICOM_THIS(SysMouseAImpl,iface);
1607 TRACE("(this=%p,%p)\n",This,lpDIDevCaps);
1609 if (lpDIDevCaps->dwSize == sizeof(DIDEVCAPS)) {
1610 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
1611 lpDIDevCaps->dwDevType = DIDEVTYPE_MOUSE;
1612 lpDIDevCaps->dwAxes = 2;
1613 lpDIDevCaps->dwButtons = 3;
1614 lpDIDevCaps->dwPOVs = 0;
1615 lpDIDevCaps->dwFFSamplePeriod = 0;
1616 lpDIDevCaps->dwFFMinTimeResolution = 0;
1617 lpDIDevCaps->dwFirmwareRevision = 100;
1618 lpDIDevCaps->dwHardwareRevision = 100;
1619 lpDIDevCaps->dwFFDriverVersion = 0;
1620 } else {
1621 /* DirectX 3.0 */
1622 FIXME("DirectX 3.0 not supported....\n");
1625 return DI_OK;
1629 /******************************************************************************
1630 * EnumObjects : enumerate the different buttons and axis...
1632 static HRESULT WINAPI SysMouseAImpl_EnumObjects(
1633 LPDIRECTINPUTDEVICE2A iface,
1634 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
1635 LPVOID lpvRef,
1636 DWORD dwFlags)
1638 ICOM_THIS(SysMouseAImpl,iface);
1639 DIDEVICEOBJECTINSTANCE ddoi;
1641 TRACE("(this=%p,%p,%p,%08lx)\n", This, lpCallback, lpvRef, dwFlags);
1642 if (TRACE_ON(dinput)) {
1643 DPRINTF(" - flags = ");
1644 _dump_EnumObjects_flags(dwFlags);
1645 DPRINTF("\n");
1648 /* Only the fields till dwFFMaxForce are relevant */
1649 ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCE, dwFFMaxForce);
1651 /* In a mouse, we have : two relative axis and three buttons */
1652 if ((dwFlags == DIDFT_ALL) ||
1653 (dwFlags & DIDFT_AXIS)) {
1654 /* X axis */
1655 ddoi.guidType = GUID_XAxis;
1656 ddoi.dwOfs = This->offset_array[WINE_MOUSE_X_POSITION];
1657 ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS;
1658 strcpy(ddoi.tszName, "X-Axis");
1659 _dump_OBJECTINSTANCE(&ddoi);
1660 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1662 /* Y axis */
1663 ddoi.guidType = GUID_YAxis;
1664 ddoi.dwOfs = This->offset_array[WINE_MOUSE_Y_POSITION];
1665 ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS;
1666 strcpy(ddoi.tszName, "Y-Axis");
1667 _dump_OBJECTINSTANCE(&ddoi);
1668 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1671 if ((dwFlags == DIDFT_ALL) ||
1672 (dwFlags & DIDFT_BUTTON)) {
1673 ddoi.guidType = GUID_Button;
1675 /* Left button */
1676 ddoi.dwOfs = This->offset_array[WINE_MOUSE_L_POSITION];
1677 ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_L_BUTTON_INSTANCE) | DIDFT_PSHBUTTON;
1678 strcpy(ddoi.tszName, "Left-Button");
1679 _dump_OBJECTINSTANCE(&ddoi);
1680 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1682 /* Right button */
1683 ddoi.dwOfs = This->offset_array[WINE_MOUSE_R_POSITION];
1684 ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_R_BUTTON_INSTANCE) | DIDFT_PSHBUTTON;
1685 strcpy(ddoi.tszName, "Right-Button");
1686 _dump_OBJECTINSTANCE(&ddoi);
1687 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1689 /* Middle button */
1690 ddoi.dwOfs = This->offset_array[WINE_MOUSE_M_POSITION];
1691 ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_M_BUTTON_INSTANCE) | DIDFT_PSHBUTTON;
1692 strcpy(ddoi.tszName, "Middle-Button");
1693 _dump_OBJECTINSTANCE(&ddoi);
1694 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1697 return DI_OK;
1702 #ifdef HAVE_LINUX_22_JOYSTICK_API
1703 /******************************************************************************
1704 * Joystick
1706 static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
1708 ICOM_THIS(JoystickAImpl,iface);
1710 This->ref--;
1711 if (This->ref)
1712 return This->ref;
1714 /* Free the data queue */
1715 if (This->data_queue != NULL)
1716 HeapFree(GetProcessHeap(),0,This->data_queue);
1718 /* Free the DataFormat */
1719 HeapFree(GetProcessHeap(), 0, This->df);
1721 HeapFree(GetProcessHeap(),0,This);
1722 return 0;
1725 /******************************************************************************
1726 * SetDataFormat : the application can choose the format of the data
1727 * the device driver sends back with GetDeviceState.
1729 static HRESULT WINAPI JoystickAImpl_SetDataFormat(
1730 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
1733 ICOM_THIS(JoystickAImpl,iface);
1734 int i;
1736 TRACE("(this=%p,%p)\n",This,df);
1738 TRACE("(df.dwSize=%ld)\n",df->dwSize);
1739 TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
1740 TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
1741 TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
1742 TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
1744 for (i=0;i<df->dwNumObjs;i++) {
1745 TRACE("df.rgodf[%d].guid %s (%p)\n",i,debugstr_guid(df->rgodf[i].pguid), df->rgodf[i].pguid);
1746 TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
1747 TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
1748 TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
1751 /* Store the new data format */
1752 This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize);
1753 memcpy(This->df, df, df->dwSize);
1754 This->df->rgodf = HeapAlloc(GetProcessHeap(),0,df->dwNumObjs*df->dwObjSize);
1755 memcpy(This->df->rgodf,df->rgodf,df->dwNumObjs*df->dwObjSize);
1757 return 0;
1760 /******************************************************************************
1761 * Acquire : gets exclusive control of the joystick
1763 static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1765 ICOM_THIS(JoystickAImpl,iface);
1767 TRACE("(this=%p)\n",This);
1768 if (This->joyfd!=-1)
1769 return 0;
1770 This->joyfd=open(JOYDEV,O_RDONLY);
1771 if (This->joyfd==-1)
1772 return DIERR_NOTFOUND;
1773 return 0;
1776 /******************************************************************************
1777 * Unacquire : frees the joystick
1779 static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1781 ICOM_THIS(JoystickAImpl,iface);
1783 TRACE("(this=%p)\n",This);
1784 if (This->joyfd!=-1) {
1785 close(This->joyfd);
1786 This->joyfd = -1;
1788 return 0;
1791 #define map_axis(val) ((val+32768)*(This->lMax-This->lMin)/65536+This->lMin)
1793 static void joy_polldev(JoystickAImpl *This) {
1794 struct timeval tv;
1795 fd_set readfds;
1796 struct js_event jse;
1798 if (This->joyfd==-1)
1799 return;
1800 while (1) {
1801 memset(&tv,0,sizeof(tv));
1802 FD_ZERO(&readfds);FD_SET(This->joyfd,&readfds);
1803 if (1>select(This->joyfd+1,&readfds,NULL,NULL,&tv))
1804 return;
1805 /* we have one event, so we can read */
1806 if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
1807 return;
1809 TRACE("js_event: type 0x%x, number %d, value %d\n",jse.type,jse.number,jse.value);
1810 if (jse.type & JS_EVENT_BUTTON) {
1811 GEN_EVENT(DIJOFS_BUTTON(jse.number),jse.value?0x80:0x00,jse.time,evsequence++);
1812 This->js.rgbButtons[jse.number] = jse.value?0x80:0x00;
1814 if (jse.type & JS_EVENT_AXIS) {
1815 switch (jse.number) {
1816 case 0:
1817 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1818 This->js.lX = map_axis(jse.value);
1819 break;
1820 case 1:
1821 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1822 This->js.lY = map_axis(jse.value);
1823 break;
1824 case 2:
1825 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1826 This->js.lZ = map_axis(jse.value);
1827 break;
1828 default:
1829 FIXME("more then 3 axes (%d) not handled!\n",jse.number);
1830 break;
1836 /******************************************************************************
1837 * GetDeviceState : returns the "state" of the joystick.
1840 static HRESULT WINAPI JoystickAImpl_GetDeviceState(
1841 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1843 ICOM_THIS(JoystickAImpl,iface);
1845 joy_polldev(This);
1846 TRACE("(this=%p,0x%08lx,%p)\n",This,len,ptr);
1847 if (len != sizeof(DIJOYSTATE)) {
1848 FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len);
1850 memcpy(ptr,&(This->js),len);
1851 This->queue_pos = 0;
1852 return 0;
1855 /******************************************************************************
1856 * GetDeviceState : gets buffered input data.
1858 static HRESULT WINAPI JoystickAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1859 DWORD dodsize,
1860 LPDIDEVICEOBJECTDATA dod,
1861 LPDWORD entries,
1862 DWORD flags
1864 ICOM_THIS(JoystickAImpl,iface);
1866 FIXME("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx),STUB!\n",This,dodsize,*entries,flags);
1868 joy_polldev(This);
1869 if (flags & DIGDD_PEEK)
1870 FIXME("DIGDD_PEEK\n");
1872 if (dod == NULL) {
1873 } else {
1875 return 0;
1878 /******************************************************************************
1879 * SetProperty : change input device properties
1881 static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1882 REFGUID rguid,
1883 LPCDIPROPHEADER ph)
1885 ICOM_THIS(JoystickAImpl,iface);
1887 FIXME("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
1888 FIXME("ph.dwSize = %ld, ph.dwHeaderSize =%ld, ph.dwObj = %ld, ph.dwHow= %ld\n",ph->dwSize, ph->dwHeaderSize,ph->dwObj,ph->dwHow);
1890 if (!HIWORD(rguid)) {
1891 switch ((DWORD)rguid) {
1892 case (DWORD) DIPROP_BUFFERSIZE: {
1893 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1895 FIXME("buffersize = %ld\n",pd->dwData);
1896 break;
1898 case (DWORD)DIPROP_RANGE: {
1899 LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph;
1901 FIXME("proprange(%ld,%ld)\n",pr->lMin,pr->lMax);
1902 This->lMin = pr->lMin;
1903 This->lMax = pr->lMax;
1904 break;
1906 case (DWORD)DIPROP_DEADZONE: {
1907 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1909 FIXME("deadzone(%ld)\n",pd->dwData);
1910 This->deadzone = pd->dwData;
1911 break;
1913 default:
1914 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
1915 break;
1918 return 0;
1921 /******************************************************************************
1922 * SetEventNotification : specifies event to be sent on state change
1924 static HRESULT WINAPI JoystickAImpl_SetEventNotification(
1925 LPDIRECTINPUTDEVICE2A iface, HANDLE hnd
1927 ICOM_THIS(JoystickAImpl,iface);
1929 TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1930 This->hEvent = hnd;
1931 return DI_OK;
1934 static HRESULT WINAPI JoystickAImpl_GetCapabilities(
1935 LPDIRECTINPUTDEVICE2A iface,
1936 LPDIDEVCAPS lpDIDevCaps)
1938 ICOM_THIS(JoystickAImpl,iface);
1939 BYTE axes,buttons;
1940 int xfd = This->joyfd;
1942 TRACE("%p->(%p)\n",iface,lpDIDevCaps);
1943 if (xfd==-1)
1944 xfd = open(JOYDEV,O_RDONLY);
1945 lpDIDevCaps->dwFlags = DIDC_ATTACHED;
1946 lpDIDevCaps->dwDevType = DIDEVTYPE_JOYSTICK;
1947 #ifdef JSIOCGAXES
1948 if (-1==ioctl(xfd,JSIOCGAXES,&axes))
1949 axes = 2;
1950 lpDIDevCaps->dwAxes = axes;
1951 #endif
1952 #ifdef JSIOCGBUTTONS
1953 if (-1==ioctl(xfd,JSIOCGAXES,&buttons))
1954 buttons = 2;
1955 lpDIDevCaps->dwButtons = buttons;
1956 #endif
1957 if (xfd!=This->joyfd)
1958 close(xfd);
1959 return DI_OK;
1961 static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE2A iface) {
1962 ICOM_THIS(JoystickAImpl,iface);
1963 TRACE("(),stub!\n");
1965 joy_polldev(This);
1966 return DI_OK;
1969 /******************************************************************************
1970 * EnumObjects : enumerate the different buttons and axis...
1972 static HRESULT WINAPI JoystickAImpl_EnumObjects(
1973 LPDIRECTINPUTDEVICE2A iface,
1974 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
1975 LPVOID lpvRef,
1976 DWORD dwFlags)
1978 ICOM_THIS(JoystickAImpl,iface);
1979 DIDEVICEOBJECTINSTANCE ddoi;
1980 int xfd = This->joyfd;
1982 TRACE("(this=%p,%p,%p,%08lx)\n", This, lpCallback, lpvRef, dwFlags);
1983 if (TRACE_ON(dinput)) {
1984 DPRINTF(" - flags = ");
1985 _dump_EnumObjects_flags(dwFlags);
1986 DPRINTF("\n");
1989 /* Only the fields till dwFFMaxForce are relevant */
1990 ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCE, dwFFMaxForce);
1992 /* For the joystick, do as is done in the GetCapabilities function */
1993 if ((dwFlags == DIDFT_ALL) ||
1994 (dwFlags & DIDFT_AXIS)) {
1995 BYTE axes, i;
1997 #ifdef JSIOCGAXES
1998 if (-1==ioctl(xfd,JSIOCGAXES,&axes))
1999 axes = 2;
2000 #endif
2002 for (i = 0; i < axes; i++) {
2003 switch (i) {
2004 case 0:
2005 ddoi.guidType = GUID_XAxis;
2006 ddoi.dwOfs = DIJOFS_X;
2007 break;
2008 case 1:
2009 ddoi.guidType = GUID_YAxis;
2010 ddoi.dwOfs = DIJOFS_Y;
2011 break;
2012 case 2:
2013 ddoi.guidType = GUID_ZAxis;
2014 ddoi.dwOfs = DIJOFS_Z;
2015 break;
2016 default:
2017 ddoi.guidType = GUID_Unknown;
2018 ddoi.dwOfs = DIJOFS_Z + (i - 2) * sizeof(LONG);
2020 ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << i) << WINE_JOYSTICK_AXIS_BASE) | DIDFT_ABSAXIS;
2021 sprintf(ddoi.tszName, "%d-Axis", i);
2022 _dump_OBJECTINSTANCE(&ddoi);
2023 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
2027 if ((dwFlags == DIDFT_ALL) ||
2028 (dwFlags & DIDFT_BUTTON)) {
2029 BYTE buttons, i;
2031 #ifdef JSIOCGBUTTONS
2032 if (-1==ioctl(xfd,JSIOCGAXES,&buttons))
2033 buttons = 2;
2034 #endif
2036 /* The DInput SDK says that GUID_Button is only for mouse buttons but well... */
2037 ddoi.guidType = GUID_Button;
2039 for (i = 0; i < buttons; i++) {
2040 ddoi.dwOfs = DIJOFS_BUTTON(i);
2041 ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << i) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON;
2042 sprintf(ddoi.tszName, "%d-Button", i);
2043 _dump_OBJECTINSTANCE(&ddoi);
2044 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
2048 if (xfd!=This->joyfd)
2049 close(xfd);
2051 return DI_OK;
2054 /******************************************************************************
2055 * GetProperty : get input device properties
2057 static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE2A iface,
2058 REFGUID rguid,
2059 LPDIPROPHEADER pdiph)
2061 ICOM_THIS(JoystickAImpl,iface);
2063 TRACE("(this=%p,%s,%p): stub!\n",
2064 iface, debugstr_guid(rguid), pdiph);
2066 if (TRACE_ON(dinput))
2067 _dump_DIPROPHEADER(pdiph);
2069 if (!HIWORD(rguid)) {
2070 switch ((DWORD)rguid) {
2071 case (DWORD) DIPROP_BUFFERSIZE: {
2072 LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
2074 TRACE(" return buffersize = %d\n",This->queue_len);
2075 pd->dwData = This->queue_len;
2076 break;
2079 case (DWORD) DIPROP_RANGE: {
2080 LPDIPROPRANGE pr = (LPDIPROPRANGE) pdiph;
2082 if ((pdiph->dwHow == DIPH_BYID) &&
2083 (pdiph->dwObj & DIDFT_ABSAXIS)) {
2084 /* The app is querying the current range of the axis : return the lMin and lMax values */
2085 pr->lMin = This->lMin;
2086 pr->lMax = This->lMax;
2089 break;
2092 default:
2093 FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
2094 break;
2099 return DI_OK;
2102 #endif
2104 /****************************************************************************/
2105 /****************************************************************************/
2107 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt =
2109 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2110 IDirectInputDevice2AImpl_QueryInterface,
2111 IDirectInputDevice2AImpl_AddRef,
2112 IDirectInputDevice2AImpl_Release,
2113 SysKeyboardAImpl_GetCapabilities,
2114 IDirectInputDevice2AImpl_EnumObjects,
2115 IDirectInputDevice2AImpl_GetProperty,
2116 SysKeyboardAImpl_SetProperty,
2117 SysKeyboardAImpl_Acquire,
2118 SysKeyboardAImpl_Unacquire,
2119 SysKeyboardAImpl_GetDeviceState,
2120 SysKeyboardAImpl_GetDeviceData,
2121 IDirectInputDevice2AImpl_SetDataFormat,
2122 IDirectInputDevice2AImpl_SetEventNotification,
2123 IDirectInputDevice2AImpl_SetCooperativeLevel,
2124 IDirectInputDevice2AImpl_GetObjectInfo,
2125 IDirectInputDevice2AImpl_GetDeviceInfo,
2126 IDirectInputDevice2AImpl_RunControlPanel,
2127 IDirectInputDevice2AImpl_Initialize,
2128 IDirectInputDevice2AImpl_CreateEffect,
2129 IDirectInputDevice2AImpl_EnumEffects,
2130 IDirectInputDevice2AImpl_GetEffectInfo,
2131 IDirectInputDevice2AImpl_GetForceFeedbackState,
2132 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
2133 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
2134 IDirectInputDevice2AImpl_Escape,
2135 IDirectInputDevice2AImpl_Poll,
2136 IDirectInputDevice2AImpl_SendDeviceData,
2139 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt =
2141 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2142 IDirectInputDevice2AImpl_QueryInterface,
2143 IDirectInputDevice2AImpl_AddRef,
2144 SysMouseAImpl_Release,
2145 SysMouseAImpl_GetCapabilities,
2146 SysMouseAImpl_EnumObjects,
2147 SysMouseAImpl_GetProperty,
2148 SysMouseAImpl_SetProperty,
2149 SysMouseAImpl_Acquire,
2150 SysMouseAImpl_Unacquire,
2151 SysMouseAImpl_GetDeviceState,
2152 SysMouseAImpl_GetDeviceData,
2153 SysMouseAImpl_SetDataFormat,
2154 SysMouseAImpl_SetEventNotification,
2155 SysMouseAImpl_SetCooperativeLevel,
2156 IDirectInputDevice2AImpl_GetObjectInfo,
2157 IDirectInputDevice2AImpl_GetDeviceInfo,
2158 IDirectInputDevice2AImpl_RunControlPanel,
2159 IDirectInputDevice2AImpl_Initialize,
2160 IDirectInputDevice2AImpl_CreateEffect,
2161 IDirectInputDevice2AImpl_EnumEffects,
2162 IDirectInputDevice2AImpl_GetEffectInfo,
2163 IDirectInputDevice2AImpl_GetForceFeedbackState,
2164 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
2165 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
2166 IDirectInputDevice2AImpl_Escape,
2167 IDirectInputDevice2AImpl_Poll,
2168 IDirectInputDevice2AImpl_SendDeviceData,
2171 #ifdef HAVE_LINUX_22_JOYSTICK_API
2172 static ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt =
2174 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2175 IDirectInputDevice2AImpl_QueryInterface,
2176 IDirectInputDevice2AImpl_AddRef,
2177 JoystickAImpl_Release,
2178 JoystickAImpl_GetCapabilities,
2179 JoystickAImpl_EnumObjects,
2180 JoystickAImpl_GetProperty,
2181 JoystickAImpl_SetProperty,
2182 JoystickAImpl_Acquire,
2183 JoystickAImpl_Unacquire,
2184 JoystickAImpl_GetDeviceState,
2185 JoystickAImpl_GetDeviceData,
2186 JoystickAImpl_SetDataFormat,
2187 JoystickAImpl_SetEventNotification,
2188 IDirectInputDevice2AImpl_SetCooperativeLevel,
2189 IDirectInputDevice2AImpl_GetObjectInfo,
2190 IDirectInputDevice2AImpl_GetDeviceInfo,
2191 IDirectInputDevice2AImpl_RunControlPanel,
2192 IDirectInputDevice2AImpl_Initialize,
2193 IDirectInputDevice2AImpl_CreateEffect,
2194 IDirectInputDevice2AImpl_EnumEffects,
2195 IDirectInputDevice2AImpl_GetEffectInfo,
2196 IDirectInputDevice2AImpl_GetForceFeedbackState,
2197 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
2198 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
2199 IDirectInputDevice2AImpl_Escape,
2200 JoystickAImpl_Poll,
2201 IDirectInputDevice2AImpl_SendDeviceData,
2203 #endif