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
23 #include "wine/port.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;
55 struct IDirectInputDevice2AImpl base;
58 /* These are used in case of relative -> absolute transitions */
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) */
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)
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]);
88 static void fill_mouse_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version) {
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));
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);
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) {
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));
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);
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)
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);
154 static BOOL mousedev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
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);
172 static SysMouseImpl *alloc_device(REFGUID rguid, const void *mvt, IDirectInputImpl *dinput)
174 SysMouseImpl* newDevice;
175 LPDIDATAFORMAT df = NULL;
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;
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);
207 if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
208 HeapFree(GetProcessHeap(), 0, df);
209 HeapFree(GetProcessHeap(), 0, newDevice);
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;
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;
247 return DIERR_NOINTERFACE;
250 return DIERR_DEVICENOTREG;
253 const struct dinput_device mouse_device = {
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;
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;
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;
296 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS;
301 /* Already have X, need to queue it */
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;
309 This->need_warp = (pt.x || pt.y) && dwCoop & DISCL_EXCLUSIVE;
313 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_Z_AXIS_INSTANCE) | DIDFT_RELAXIS;
314 This->m_state.lZ += wdata = (short)HIWORD(hook->mouseData);
317 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 0) | DIDFT_PSHBUTTON;
318 This->m_state.rgbButtons[0] = wdata = 0x80;
321 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 0) | DIDFT_PSHBUTTON;
322 This->m_state.rgbButtons[0] = wdata = 0x00;
325 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 1) | DIDFT_PSHBUTTON;
326 This->m_state.rgbButtons[1] = wdata = 0x80;
329 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 1) | DIDFT_PSHBUTTON;
330 This->m_state.rgbButtons[1] = wdata = 0x00;
333 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 2) | DIDFT_PSHBUTTON;
334 This->m_state.rgbButtons[2] = wdata = 0x80;
337 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 2) | DIDFT_PSHBUTTON;
338 This->m_state.rgbButtons[2] = wdata = 0x00;
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;
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;
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) {
363 DWORD centerX, centerY;
365 /* make sure the window hasn't moved */
366 if(!GetWindowRect(This->base.win, &rect))
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);
381 /******************************************************************************
382 * Acquire : gets exclusive control of the mouse
384 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
386 SysMouseImpl *This = (SysMouseImpl *)iface;
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;
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)
416 ShowCursor(FALSE); /* hide cursor */
417 if (GetWindowRect(This->base.win, &rc))
419 FIXME("Clipping cursor to %s\n", wine_dbgstr_rect( &rc ));
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;
447 /******************************************************************************
448 * Unacquire : frees the mouse
450 static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
452 SysMouseImpl *This = (SysMouseImpl *)iface;
455 TRACE("(this=%p)\n",This);
457 if ((res = IDirectInputDevice2AImpl_Unacquire(iface)) != DI_OK) return res;
459 if (This->base.dwCoopLevel & DISCL_EXCLUSIVE)
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);
475 /******************************************************************************
476 * GetDeviceState : returns the "state" of the mouse.
478 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
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, &(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;
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;
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;
545 /******************************************************************************
546 * GetProperty : get input device properties
548 static HRESULT WINAPI SysMouseAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface,
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;
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
577 pr->lMin = DIPROPRANGE_NOMIN;
578 pr->lMax = DIPROPRANGE_NOMAX;
585 return IDirectInputDevice2AImpl_GetProperty(iface, rguid, pdiph);
592 /******************************************************************************
593 * GetCapabilities : get the device capabilities
595 static HRESULT WINAPI SysMouseAImpl_GetCapabilities(
596 LPDIRECTINPUTDEVICE8A iface,
597 LPDIDEVCAPS lpDIDevCaps)
599 SysMouseImpl *This = (SysMouseImpl *)iface;
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);
614 devcaps.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8);
616 devcaps.dwButtons = 8;
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);
629 /******************************************************************************
630 * GetObjectInfo : get information about a device object such as a button
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};
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);
655 static HRESULT WINAPI SysMouseAImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8A iface,
656 LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow)
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);
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");
690 fill_mouse_dideviceinstanceA(pdidi, This->base.dinput->dwVersion);
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");
705 fill_mouse_dideviceinstanceW(pdidi, This->base.dinput->dwVersion);
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))
750 # define XCAST(fun) (void*)
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