push 5b66f3b36e7323272378316c923222b908f6e2d3
[wine/hacks.git] / dlls / dinput / mouse.c
bloba3610573940eaf8297ef3ce1999d59ef28b18a98
1 /* DirectInput Mouse device
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
5 * Copyright 2000-2001 TransGaming Technologies Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <stdarg.h>
26 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "winuser.h"
32 #include "winerror.h"
33 #include "dinput.h"
35 #include "dinput_private.h"
36 #include "device_private.h"
37 #include "wine/debug.h"
38 #include "wine/unicode.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
42 /* Wine mouse driver object instances */
43 #define WINE_MOUSE_X_AXIS_INSTANCE 0
44 #define WINE_MOUSE_Y_AXIS_INSTANCE 1
45 #define WINE_MOUSE_Z_AXIS_INSTANCE 2
46 #define WINE_MOUSE_BUTTONS_INSTANCE 3
48 static const IDirectInputDevice8AVtbl SysMouseAvt;
49 static const IDirectInputDevice8WVtbl SysMouseWvt;
51 typedef struct SysMouseImpl SysMouseImpl;
53 struct SysMouseImpl
55 struct IDirectInputDevice2AImpl base;
57 /* SysMouseAImpl */
58 /* These are used in case of relative -> absolute transitions */
59 POINT org_coords;
60 POINT mapped_center;
61 DWORD win_centerX, win_centerY;
62 /* warping: whether we need to move mouse back to middle once we
63 * reach window borders (for e.g. shooters, "surface movement" games) */
64 BOOL need_warp;
65 DWORD last_warped;
67 /* This is for mouse reporting. */
68 DIMOUSESTATE2 m_state;
71 static void dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam );
73 const GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
74 0x9e573ed8, 0x7734, 0x11d2, {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
77 static void _dump_mouse_state(DIMOUSESTATE2 *m_state)
79 int i;
81 if (!TRACE_ON(dinput)) return;
83 TRACE("(X: %d Y: %d Z: %d", m_state->lX, m_state->lY, m_state->lZ);
84 for (i = 0; i < 5; i++) TRACE(" B%d: %02x", i, m_state->rgbButtons[i]);
85 TRACE(")\n");
88 static void fill_mouse_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version) {
89 DWORD dwSize;
90 DIDEVICEINSTANCEA ddi;
92 dwSize = lpddi->dwSize;
94 TRACE("%d %p\n", dwSize, lpddi);
96 memset(lpddi, 0, dwSize);
97 memset(&ddi, 0, sizeof(ddi));
99 ddi.dwSize = dwSize;
100 ddi.guidInstance = GUID_SysMouse;/* DInput's GUID */
101 ddi.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
102 if (version >= 0x0800)
103 ddi.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8);
104 else
105 ddi.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8);
106 strcpy(ddi.tszInstanceName, "Mouse");
107 strcpy(ddi.tszProductName, "Wine Mouse");
109 memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
112 static void fill_mouse_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version) {
113 DWORD dwSize;
114 DIDEVICEINSTANCEW ddi;
116 dwSize = lpddi->dwSize;
118 TRACE("%d %p\n", dwSize, lpddi);
120 memset(lpddi, 0, dwSize);
121 memset(&ddi, 0, sizeof(ddi));
123 ddi.dwSize = dwSize;
124 ddi.guidInstance = GUID_SysMouse;/* DInput's GUID */
125 ddi.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
126 if (version >= 0x0800)
127 ddi.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8);
128 else
129 ddi.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8);
130 MultiByteToWideChar(CP_ACP, 0, "Mouse", -1, ddi.tszInstanceName, MAX_PATH);
131 MultiByteToWideChar(CP_ACP, 0, "Wine Mouse", -1, ddi.tszProductName, MAX_PATH);
133 memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
136 static BOOL mousedev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
138 if (id != 0)
139 return FALSE;
141 if ((dwDevType == 0) ||
142 ((dwDevType == DIDEVTYPE_MOUSE) && (version < 0x0800)) ||
143 (((dwDevType == DI8DEVCLASS_POINTER) || (dwDevType == DI8DEVTYPE_MOUSE)) && (version >= 0x0800))) {
144 TRACE("Enumerating the mouse device\n");
146 fill_mouse_dideviceinstanceA(lpddi, version);
148 return TRUE;
151 return FALSE;
154 static BOOL mousedev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
156 if (id != 0)
157 return FALSE;
159 if ((dwDevType == 0) ||
160 ((dwDevType == DIDEVTYPE_MOUSE) && (version < 0x0800)) ||
161 (((dwDevType == DI8DEVCLASS_POINTER) || (dwDevType == DI8DEVTYPE_MOUSE)) && (version >= 0x0800))) {
162 TRACE("Enumerating the mouse device\n");
164 fill_mouse_dideviceinstanceW(lpddi, version);
166 return TRUE;
169 return FALSE;
172 static SysMouseImpl *alloc_device(REFGUID rguid, const void *mvt, IDirectInputImpl *dinput)
174 SysMouseImpl* newDevice;
175 LPDIDATAFORMAT df = NULL;
176 unsigned i;
178 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseImpl));
179 if (!newDevice) return NULL;
180 newDevice->base.lpVtbl = mvt;
181 newDevice->base.ref = 1;
182 newDevice->base.dwCoopLevel = DISCL_NONEXCLUSIVE | DISCL_BACKGROUND;
183 newDevice->base.guid = *rguid;
184 InitializeCriticalSection(&newDevice->base.crit);
185 newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysMouseImpl*->base.crit");
186 newDevice->base.dinput = dinput;
187 newDevice->base.event_proc = dinput_mouse_hook;
189 /* Create copy of default data format */
190 if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIMouse2.dwSize))) goto failed;
191 memcpy(df, &c_dfDIMouse2, c_dfDIMouse2.dwSize);
192 if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto failed;
193 memcpy(df->rgodf, c_dfDIMouse2.rgodf, df->dwNumObjs * df->dwObjSize);
195 /* Because we don't do any detection yet just modify instance and type */
196 for (i = 0; i < df->dwNumObjs; i++)
197 if (DIDFT_GETTYPE(df->rgodf[i].dwType) & DIDFT_AXIS)
198 df->rgodf[i].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_RELAXIS;
199 else
200 df->rgodf[i].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
202 newDevice->base.data_format.wine_df = df;
203 IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->base.dinput);
204 return newDevice;
206 failed:
207 if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
208 HeapFree(GetProcessHeap(), 0, df);
209 HeapFree(GetProcessHeap(), 0, newDevice);
210 return NULL;
213 static HRESULT mousedev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
215 if ((IsEqualGUID(&GUID_SysMouse,rguid)) || /* Generic Mouse */
216 (IsEqualGUID(&DInput_Wine_Mouse_GUID,rguid))) { /* Wine Mouse */
217 if ((riid == NULL) ||
218 IsEqualGUID(&IID_IDirectInputDeviceA,riid) ||
219 IsEqualGUID(&IID_IDirectInputDevice2A,riid) ||
220 IsEqualGUID(&IID_IDirectInputDevice7A,riid) ||
221 IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
222 *pdev = (IDirectInputDeviceA*) alloc_device(rguid, &SysMouseAvt, dinput);
223 TRACE("Creating a Mouse device (%p)\n", *pdev);
224 if (!*pdev) return DIERR_OUTOFMEMORY;
225 return DI_OK;
226 } else
227 return DIERR_NOINTERFACE;
230 return DIERR_DEVICENOTREG;
233 static HRESULT mousedev_create_deviceW(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEW* pdev)
235 if ((IsEqualGUID(&GUID_SysMouse,rguid)) || /* Generic Mouse */
236 (IsEqualGUID(&DInput_Wine_Mouse_GUID,rguid))) { /* Wine Mouse */
237 if ((riid == NULL) ||
238 IsEqualGUID(&IID_IDirectInputDeviceW,riid) ||
239 IsEqualGUID(&IID_IDirectInputDevice2W,riid) ||
240 IsEqualGUID(&IID_IDirectInputDevice7W,riid) ||
241 IsEqualGUID(&IID_IDirectInputDevice8W,riid)) {
242 *pdev = (IDirectInputDeviceW*) alloc_device(rguid, &SysMouseWvt, dinput);
243 TRACE("Creating a Mouse device (%p)\n", *pdev);
244 if (!*pdev) return DIERR_OUTOFMEMORY;
245 return DI_OK;
246 } else
247 return DIERR_NOINTERFACE;
250 return DIERR_DEVICENOTREG;
253 const struct dinput_device mouse_device = {
254 "Wine mouse driver",
255 mousedev_enum_deviceA,
256 mousedev_enum_deviceW,
257 mousedev_create_deviceA,
258 mousedev_create_deviceW
261 /******************************************************************************
262 * SysMouseA (DInput Mouse support)
265 /* low-level mouse hook */
266 static void dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam )
268 MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam;
269 SysMouseImpl* This = (SysMouseImpl*) iface;
270 DWORD dwCoop;
271 int wdata = 0, inst_id = -1;
273 TRACE("msg %lx @ (%d %d)\n", wparam, hook->pt.x, hook->pt.y);
275 EnterCriticalSection(&This->base.crit);
276 dwCoop = This->base.dwCoopLevel;
278 switch(wparam) {
279 case WM_MOUSEMOVE:
281 POINT pt, pt1;
283 GetCursorPos(&pt);
284 This->m_state.lX += pt.x = hook->pt.x - pt.x;
285 This->m_state.lY += pt.y = hook->pt.y - pt.y;
287 if (This->base.data_format.user_df->dwFlags & DIDF_ABSAXIS)
289 pt1.x = This->m_state.lX;
290 pt1.y = This->m_state.lY;
291 } else
292 pt1 = pt;
294 if (pt.x)
296 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS;
297 wdata = pt1.x;
299 if (pt.y)
301 /* Already have X, need to queue it */
302 if (inst_id != -1)
303 queue_event((LPDIRECTINPUTDEVICE8A)This, id_to_offset(&This->base.data_format, inst_id),
304 wdata, GetCurrentTime(), This->base.dinput->evsequence);
305 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS;
306 wdata = pt1.y;
309 This->need_warp = (pt.x || pt.y) && dwCoop & DISCL_EXCLUSIVE;
310 break;
312 case WM_MOUSEWHEEL:
313 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_Z_AXIS_INSTANCE) | DIDFT_RELAXIS;
314 This->m_state.lZ += wdata = (short)HIWORD(hook->mouseData);
315 break;
316 case WM_LBUTTONDOWN:
317 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 0) | DIDFT_PSHBUTTON;
318 This->m_state.rgbButtons[0] = wdata = 0x80;
319 break;
320 case WM_LBUTTONUP:
321 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 0) | DIDFT_PSHBUTTON;
322 This->m_state.rgbButtons[0] = wdata = 0x00;
323 break;
324 case WM_RBUTTONDOWN:
325 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 1) | DIDFT_PSHBUTTON;
326 This->m_state.rgbButtons[1] = wdata = 0x80;
327 break;
328 case WM_RBUTTONUP:
329 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 1) | DIDFT_PSHBUTTON;
330 This->m_state.rgbButtons[1] = wdata = 0x00;
331 break;
332 case WM_MBUTTONDOWN:
333 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 2) | DIDFT_PSHBUTTON;
334 This->m_state.rgbButtons[2] = wdata = 0x80;
335 break;
336 case WM_MBUTTONUP:
337 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 2) | DIDFT_PSHBUTTON;
338 This->m_state.rgbButtons[2] = wdata = 0x00;
339 break;
340 case WM_XBUTTONDOWN:
341 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 2 + HIWORD(hook->mouseData)) | DIDFT_PSHBUTTON;
342 This->m_state.rgbButtons[2 + HIWORD(hook->mouseData)] = wdata = 0x80;
343 break;
344 case WM_XBUTTONUP:
345 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 2 + HIWORD(hook->mouseData)) | DIDFT_PSHBUTTON;
346 This->m_state.rgbButtons[2 + HIWORD(hook->mouseData)] = wdata = 0x00;
347 break;
351 if (inst_id != -1)
353 _dump_mouse_state(&This->m_state);
354 queue_event((LPDIRECTINPUTDEVICE8A)This, id_to_offset(&This->base.data_format, inst_id),
355 wdata, GetCurrentTime(), This->base.dinput->evsequence++);
358 LeaveCriticalSection(&This->base.crit);
361 static BOOL dinput_window_check(SysMouseImpl* This) {
362 RECT rect;
363 DWORD centerX, centerY;
365 /* make sure the window hasn't moved */
366 if(!GetWindowRect(This->base.win, &rect))
367 return FALSE;
368 centerX = (rect.right - rect.left) / 2;
369 centerY = (rect.bottom - rect.top ) / 2;
370 if (This->win_centerX != centerX || This->win_centerY != centerY) {
371 This->win_centerX = centerX;
372 This->win_centerY = centerY;
374 This->mapped_center.x = This->win_centerX;
375 This->mapped_center.y = This->win_centerY;
376 MapWindowPoints(This->base.win, HWND_DESKTOP, &This->mapped_center, 1);
377 return TRUE;
381 /******************************************************************************
382 * Acquire : gets exclusive control of the mouse
384 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
386 SysMouseImpl *This = (SysMouseImpl *)iface;
387 RECT rect;
388 POINT point;
389 HRESULT res;
391 TRACE("(this=%p)\n",This);
393 if ((res = IDirectInputDevice2AImpl_Acquire(iface)) != DI_OK) return res;
395 /* Init the mouse state */
396 GetCursorPos( &point );
397 if (This->base.data_format.user_df->dwFlags & DIDF_ABSAXIS)
399 This->m_state.lX = point.x;
400 This->m_state.lY = point.y;
401 } else {
402 This->m_state.lX = 0;
403 This->m_state.lY = 0;
404 This->org_coords = point;
406 This->m_state.lZ = 0;
407 This->m_state.rgbButtons[0] = GetKeyState(VK_LBUTTON) & 0x80;
408 This->m_state.rgbButtons[1] = GetKeyState(VK_RBUTTON) & 0x80;
409 This->m_state.rgbButtons[2] = GetKeyState(VK_MBUTTON) & 0x80;
411 /* Install our mouse hook */
412 if (This->base.dwCoopLevel & DISCL_EXCLUSIVE)
414 RECT rc;
416 ShowCursor(FALSE); /* hide cursor */
417 if (GetWindowRect(This->base.win, &rc))
419 FIXME("Clipping cursor to %s\n", wine_dbgstr_rect( &rc ));
420 ClipCursor(&rc);
422 else
423 ERR("Failed to get RECT: %d\n", GetLastError());
426 /* Get the window dimension and find the center */
427 GetWindowRect(This->base.win, &rect);
428 This->win_centerX = (rect.right - rect.left) / 2;
429 This->win_centerY = (rect.bottom - rect.top ) / 2;
431 /* Warp the mouse to the center of the window */
432 if (This->base.dwCoopLevel & DISCL_EXCLUSIVE)
434 This->mapped_center.x = This->win_centerX;
435 This->mapped_center.y = This->win_centerY;
436 MapWindowPoints(This->base.win, HWND_DESKTOP, &This->mapped_center, 1);
437 TRACE("Warping mouse to %d - %d\n", This->mapped_center.x, This->mapped_center.y);
438 SetCursorPos( This->mapped_center.x, This->mapped_center.y );
439 This->last_warped = GetCurrentTime();
441 This->need_warp = FALSE;
444 return DI_OK;
447 /******************************************************************************
448 * Unacquire : frees the mouse
450 static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
452 SysMouseImpl *This = (SysMouseImpl *)iface;
453 HRESULT res;
455 TRACE("(this=%p)\n",This);
457 if ((res = IDirectInputDevice2AImpl_Unacquire(iface)) != DI_OK) return res;
459 if (This->base.dwCoopLevel & DISCL_EXCLUSIVE)
461 ClipCursor(NULL);
462 ShowCursor(TRUE); /* show cursor */
465 /* And put the mouse cursor back where it was at acquire time */
466 if (This->base.dwCoopLevel & DISCL_EXCLUSIVE)
468 TRACE(" warping mouse back to (%d , %d)\n", This->org_coords.x, This->org_coords.y);
469 SetCursorPos(This->org_coords.x, This->org_coords.y);
472 return DI_OK;
475 /******************************************************************************
476 * GetDeviceState : returns the "state" of the mouse.
478 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
479 * supported.
481 static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
482 LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr
484 SysMouseImpl *This = (SysMouseImpl *)iface;
486 if(This->base.acquired == 0) return DIERR_NOTACQUIRED;
488 TRACE("(this=%p,0x%08x,%p):\n", This, len, ptr);
489 _dump_mouse_state(&This->m_state);
491 EnterCriticalSection(&This->base.crit);
492 /* Copy the current mouse state */
493 fill_DataFormat(ptr, len, &This->m_state, &This->base.data_format);
495 /* Initialize the buffer when in relative mode */
496 if (!(This->base.data_format.user_df->dwFlags & DIDF_ABSAXIS))
498 This->m_state.lX = 0;
499 This->m_state.lY = 0;
500 This->m_state.lZ = 0;
502 LeaveCriticalSection(&This->base.crit);
504 /* Check if we need to do a mouse warping */
505 if (This->need_warp && (GetCurrentTime() - This->last_warped > 10))
507 if(!dinput_window_check(This))
508 return DIERR_GENERIC;
509 TRACE("Warping mouse to %d - %d\n", This->mapped_center.x, This->mapped_center.y);
510 SetCursorPos( This->mapped_center.x, This->mapped_center.y );
511 This->last_warped = GetCurrentTime();
513 This->need_warp = FALSE;
516 return DI_OK;
519 /******************************************************************************
520 * GetDeviceData : gets buffered input data.
522 static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface,
523 DWORD dodsize, LPDIDEVICEOBJECTDATA dod, LPDWORD entries, DWORD flags)
525 SysMouseImpl *This = (SysMouseImpl *)iface;
526 HRESULT res;
528 res = IDirectInputDevice2AImpl_GetDeviceData(iface, dodsize, dod, entries, flags);
529 if (FAILED(res)) return res;
531 /* Check if we need to do a mouse warping */
532 if (This->need_warp && (GetCurrentTime() - This->last_warped > 10))
534 if(!dinput_window_check(This))
535 return DIERR_GENERIC;
536 TRACE("Warping mouse to %d - %d\n", This->mapped_center.x, This->mapped_center.y);
537 SetCursorPos( This->mapped_center.x, This->mapped_center.y );
538 This->last_warped = GetCurrentTime();
540 This->need_warp = FALSE;
542 return res;
545 /******************************************************************************
546 * GetProperty : get input device properties
548 static HRESULT WINAPI SysMouseAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface,
549 REFGUID rguid,
550 LPDIPROPHEADER pdiph)
552 SysMouseImpl *This = (SysMouseImpl *)iface;
554 TRACE("(%p) %s,%p\n", This, debugstr_guid(rguid), pdiph);
555 _dump_DIPROPHEADER(pdiph);
557 if (!HIWORD(rguid)) {
558 switch (LOWORD(rguid)) {
559 case (DWORD) DIPROP_GRANULARITY: {
560 LPDIPROPDWORD pr = (LPDIPROPDWORD) pdiph;
562 /* We'll just assume that the app asks about the Z axis */
563 pr->dwData = WHEEL_DELTA;
565 break;
568 case (DWORD) DIPROP_RANGE: {
569 LPDIPROPRANGE pr = (LPDIPROPRANGE) pdiph;
571 if ((pdiph->dwHow == DIPH_BYID) &&
572 ((pdiph->dwObj == (DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS)) ||
573 (pdiph->dwObj == (DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS)))) {
574 /* Querying the range of either the X or the Y axis. As I do
575 not know the range, do as if the range were
576 unrestricted...*/
577 pr->lMin = DIPROPRANGE_NOMIN;
578 pr->lMax = DIPROPRANGE_NOMAX;
581 break;
584 default:
585 return IDirectInputDevice2AImpl_GetProperty(iface, rguid, pdiph);
589 return DI_OK;
592 /******************************************************************************
593 * GetCapabilities : get the device capabilities
595 static HRESULT WINAPI SysMouseAImpl_GetCapabilities(
596 LPDIRECTINPUTDEVICE8A iface,
597 LPDIDEVCAPS lpDIDevCaps)
599 SysMouseImpl *This = (SysMouseImpl *)iface;
600 DIDEVCAPS devcaps;
602 TRACE("(this=%p,%p)\n",This,lpDIDevCaps);
604 if ((lpDIDevCaps->dwSize != sizeof(DIDEVCAPS)) && (lpDIDevCaps->dwSize != sizeof(DIDEVCAPS_DX3))) {
605 WARN("invalid parameter\n");
606 return DIERR_INVALIDPARAM;
609 devcaps.dwSize = lpDIDevCaps->dwSize;
610 devcaps.dwFlags = DIDC_ATTACHED;
611 if (This->base.dinput->dwVersion >= 0x0800)
612 devcaps.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8);
613 else
614 devcaps.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8);
615 devcaps.dwAxes = 3;
616 devcaps.dwButtons = 8;
617 devcaps.dwPOVs = 0;
618 devcaps.dwFFSamplePeriod = 0;
619 devcaps.dwFFMinTimeResolution = 0;
620 devcaps.dwFirmwareRevision = 100;
621 devcaps.dwHardwareRevision = 100;
622 devcaps.dwFFDriverVersion = 0;
624 memcpy(lpDIDevCaps, &devcaps, lpDIDevCaps->dwSize);
626 return DI_OK;
629 /******************************************************************************
630 * GetObjectInfo : get information about a device object such as a button
631 * or axis
633 static HRESULT WINAPI SysMouseWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
634 LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow)
636 static const WCHAR x_axisW[] = {'X','-','A','x','i','s',0};
637 static const WCHAR y_axisW[] = {'Y','-','A','x','i','s',0};
638 static const WCHAR wheelW[] = {'W','h','e','e','l',0};
639 static const WCHAR buttonW[] = {'B','u','t','t','o','n',' ','%','d',0};
640 HRESULT res;
642 res = IDirectInputDevice2WImpl_GetObjectInfo(iface, pdidoi, dwObj, dwHow);
643 if (res != DI_OK) return res;
645 if (IsEqualGUID(&pdidoi->guidType, &GUID_XAxis)) strcpyW(pdidoi->tszName, x_axisW);
646 else if (IsEqualGUID(&pdidoi->guidType, &GUID_YAxis)) strcpyW(pdidoi->tszName, y_axisW);
647 else if (IsEqualGUID(&pdidoi->guidType, &GUID_ZAxis)) strcpyW(pdidoi->tszName, wheelW);
648 else if (pdidoi->dwType & DIDFT_BUTTON)
649 wsprintfW(pdidoi->tszName, buttonW, DIDFT_GETINSTANCE(pdidoi->dwType) - 3);
651 _dump_OBJECTINSTANCEW(pdidoi);
652 return res;
655 static HRESULT WINAPI SysMouseAImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8A iface,
656 LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow)
658 HRESULT res;
659 DIDEVICEOBJECTINSTANCEW didoiW;
660 DWORD dwSize = pdidoi->dwSize;
662 didoiW.dwSize = sizeof(didoiW);
663 res = SysMouseWImpl_GetObjectInfo((LPDIRECTINPUTDEVICE8W)iface, &didoiW, dwObj, dwHow);
664 if (res != DI_OK) return res;
666 memset(pdidoi, 0, pdidoi->dwSize);
667 memcpy(pdidoi, &didoiW, FIELD_OFFSET(DIDEVICEOBJECTINSTANCEW, tszName));
668 pdidoi->dwSize = dwSize;
669 WideCharToMultiByte(CP_ACP, 0, didoiW.tszName, -1, pdidoi->tszName,
670 sizeof(pdidoi->tszName), NULL, NULL);
672 return res;
675 /******************************************************************************
676 * GetDeviceInfo : get information about a device's identity
678 static HRESULT WINAPI SysMouseAImpl_GetDeviceInfo(
679 LPDIRECTINPUTDEVICE8A iface,
680 LPDIDEVICEINSTANCEA pdidi)
682 SysMouseImpl *This = (SysMouseImpl *)iface;
683 TRACE("(this=%p,%p)\n", This, pdidi);
685 if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) {
686 WARN(" dinput3 not supporte yet...\n");
687 return DI_OK;
690 fill_mouse_dideviceinstanceA(pdidi, This->base.dinput->dwVersion);
692 return DI_OK;
695 static HRESULT WINAPI SysMouseWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW pdidi)
697 SysMouseImpl *This = (SysMouseImpl *)iface;
698 TRACE("(this=%p,%p)\n", This, pdidi);
700 if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) {
701 WARN(" dinput3 not supporte yet...\n");
702 return DI_OK;
705 fill_mouse_dideviceinstanceW(pdidi, This->base.dinput->dwVersion);
707 return DI_OK;
711 static const IDirectInputDevice8AVtbl SysMouseAvt =
713 IDirectInputDevice2AImpl_QueryInterface,
714 IDirectInputDevice2AImpl_AddRef,
715 IDirectInputDevice2AImpl_Release,
716 SysMouseAImpl_GetCapabilities,
717 IDirectInputDevice2AImpl_EnumObjects,
718 SysMouseAImpl_GetProperty,
719 IDirectInputDevice2AImpl_SetProperty,
720 SysMouseAImpl_Acquire,
721 SysMouseAImpl_Unacquire,
722 SysMouseAImpl_GetDeviceState,
723 SysMouseAImpl_GetDeviceData,
724 IDirectInputDevice2AImpl_SetDataFormat,
725 IDirectInputDevice2AImpl_SetEventNotification,
726 IDirectInputDevice2AImpl_SetCooperativeLevel,
727 SysMouseAImpl_GetObjectInfo,
728 SysMouseAImpl_GetDeviceInfo,
729 IDirectInputDevice2AImpl_RunControlPanel,
730 IDirectInputDevice2AImpl_Initialize,
731 IDirectInputDevice2AImpl_CreateEffect,
732 IDirectInputDevice2AImpl_EnumEffects,
733 IDirectInputDevice2AImpl_GetEffectInfo,
734 IDirectInputDevice2AImpl_GetForceFeedbackState,
735 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
736 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
737 IDirectInputDevice2AImpl_Escape,
738 IDirectInputDevice2AImpl_Poll,
739 IDirectInputDevice2AImpl_SendDeviceData,
740 IDirectInputDevice7AImpl_EnumEffectsInFile,
741 IDirectInputDevice7AImpl_WriteEffectToFile,
742 IDirectInputDevice8AImpl_BuildActionMap,
743 IDirectInputDevice8AImpl_SetActionMap,
744 IDirectInputDevice8AImpl_GetImageInfo
747 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
748 # define XCAST(fun) (typeof(SysMouseWvt.fun))
749 #else
750 # define XCAST(fun) (void*)
751 #endif
753 static const IDirectInputDevice8WVtbl SysMouseWvt =
755 IDirectInputDevice2WImpl_QueryInterface,
756 XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
757 XCAST(Release)IDirectInputDevice2AImpl_Release,
758 XCAST(GetCapabilities)SysMouseAImpl_GetCapabilities,
759 IDirectInputDevice2WImpl_EnumObjects,
760 XCAST(GetProperty)SysMouseAImpl_GetProperty,
761 XCAST(SetProperty)IDirectInputDevice2AImpl_SetProperty,
762 XCAST(Acquire)SysMouseAImpl_Acquire,
763 XCAST(Unacquire)SysMouseAImpl_Unacquire,
764 XCAST(GetDeviceState)SysMouseAImpl_GetDeviceState,
765 XCAST(GetDeviceData)SysMouseAImpl_GetDeviceData,
766 XCAST(SetDataFormat)IDirectInputDevice2AImpl_SetDataFormat,
767 XCAST(SetEventNotification)IDirectInputDevice2AImpl_SetEventNotification,
768 XCAST(SetCooperativeLevel)IDirectInputDevice2AImpl_SetCooperativeLevel,
769 SysMouseWImpl_GetObjectInfo,
770 SysMouseWImpl_GetDeviceInfo,
771 XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel,
772 XCAST(Initialize)IDirectInputDevice2AImpl_Initialize,
773 XCAST(CreateEffect)IDirectInputDevice2AImpl_CreateEffect,
774 IDirectInputDevice2WImpl_EnumEffects,
775 IDirectInputDevice2WImpl_GetEffectInfo,
776 XCAST(GetForceFeedbackState)IDirectInputDevice2AImpl_GetForceFeedbackState,
777 XCAST(SendForceFeedbackCommand)IDirectInputDevice2AImpl_SendForceFeedbackCommand,
778 XCAST(EnumCreatedEffectObjects)IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
779 XCAST(Escape)IDirectInputDevice2AImpl_Escape,
780 XCAST(Poll)IDirectInputDevice2AImpl_Poll,
781 XCAST(SendDeviceData)IDirectInputDevice2AImpl_SendDeviceData,
782 IDirectInputDevice7WImpl_EnumEffectsInFile,
783 IDirectInputDevice7WImpl_WriteEffectToFile,
784 IDirectInputDevice8WImpl_BuildActionMap,
785 IDirectInputDevice8WImpl_SetActionMap,
786 IDirectInputDevice8WImpl_GetImageInfo
788 #undef XCAST