push aea352fc3df615e3f4b48daf6f897ea93ad1fffd
[wine/hacks.git] / dlls / dinput / mouse.c
blob3c80e7e47f859640896a6b1ca3d2d0ee135881b1
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 /* FIXME: This is ugly and not thread safe :/ */
72 static IDirectInputDevice8A* current_lock = NULL;
74 static const GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
75 0x9e573ed8,
76 0x7734,
77 0x11d2,
78 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
81 static void fill_mouse_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version) {
82 DWORD dwSize;
83 DIDEVICEINSTANCEA ddi;
85 dwSize = lpddi->dwSize;
87 TRACE("%d %p\n", dwSize, lpddi);
89 memset(lpddi, 0, dwSize);
90 memset(&ddi, 0, sizeof(ddi));
92 ddi.dwSize = dwSize;
93 ddi.guidInstance = GUID_SysMouse;/* DInput's GUID */
94 ddi.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
95 if (version >= 0x0800)
96 ddi.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8);
97 else
98 ddi.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8);
99 strcpy(ddi.tszInstanceName, "Mouse");
100 strcpy(ddi.tszProductName, "Wine Mouse");
102 memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
105 static void fill_mouse_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version) {
106 DWORD dwSize;
107 DIDEVICEINSTANCEW ddi;
109 dwSize = lpddi->dwSize;
111 TRACE("%d %p\n", dwSize, lpddi);
113 memset(lpddi, 0, dwSize);
114 memset(&ddi, 0, sizeof(ddi));
116 ddi.dwSize = dwSize;
117 ddi.guidInstance = GUID_SysMouse;/* DInput's GUID */
118 ddi.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
119 if (version >= 0x0800)
120 ddi.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8);
121 else
122 ddi.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8);
123 MultiByteToWideChar(CP_ACP, 0, "Mouse", -1, ddi.tszInstanceName, MAX_PATH);
124 MultiByteToWideChar(CP_ACP, 0, "Wine Mouse", -1, ddi.tszProductName, MAX_PATH);
126 memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
129 static BOOL mousedev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
131 if (id != 0)
132 return FALSE;
134 if ((dwDevType == 0) ||
135 ((dwDevType == DIDEVTYPE_MOUSE) && (version < 0x0800)) ||
136 (((dwDevType == DI8DEVCLASS_POINTER) || (dwDevType == DI8DEVTYPE_MOUSE)) && (version >= 0x0800))) {
137 TRACE("Enumerating the mouse device\n");
139 fill_mouse_dideviceinstanceA(lpddi, version);
141 return TRUE;
144 return FALSE;
147 static BOOL mousedev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
149 if (id != 0)
150 return FALSE;
152 if ((dwDevType == 0) ||
153 ((dwDevType == DIDEVTYPE_MOUSE) && (version < 0x0800)) ||
154 (((dwDevType == DI8DEVCLASS_POINTER) || (dwDevType == DI8DEVTYPE_MOUSE)) && (version >= 0x0800))) {
155 TRACE("Enumerating the mouse device\n");
157 fill_mouse_dideviceinstanceW(lpddi, version);
159 return TRUE;
162 return FALSE;
165 static SysMouseImpl *alloc_device(REFGUID rguid, const void *mvt, IDirectInputImpl *dinput)
167 SysMouseImpl* newDevice;
168 LPDIDATAFORMAT df = NULL;
169 int i;
171 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseImpl));
172 if (!newDevice) return NULL;
173 newDevice->base.lpVtbl = mvt;
174 newDevice->base.ref = 1;
175 newDevice->base.dwCoopLevel = DISCL_NONEXCLUSIVE | DISCL_BACKGROUND;
176 memcpy(&newDevice->base.guid, rguid, sizeof(*rguid));
177 InitializeCriticalSection(&newDevice->base.crit);
178 newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysMouseImpl*->base.crit");
179 newDevice->base.dinput = dinput;
181 /* Create copy of default data format */
182 if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIMouse2.dwSize))) goto failed;
183 memcpy(df, &c_dfDIMouse2, c_dfDIMouse2.dwSize);
184 if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto failed;
185 memcpy(df->rgodf, c_dfDIMouse2.rgodf, df->dwNumObjs * df->dwObjSize);
187 /* Because we don't do any detection yet just modify instance and type */
188 for (i = 0; i < df->dwNumObjs; i++)
189 if (DIDFT_GETTYPE(df->rgodf[i].dwType) & DIDFT_AXIS)
190 df->rgodf[i].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_RELAXIS;
191 else
192 df->rgodf[i].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
194 newDevice->base.data_format.wine_df = df;
195 IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->base.dinput);
196 return newDevice;
198 failed:
199 if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
200 HeapFree(GetProcessHeap(), 0, df);
201 HeapFree(GetProcessHeap(), 0, newDevice);
202 return NULL;
205 static HRESULT mousedev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
207 if ((IsEqualGUID(&GUID_SysMouse,rguid)) || /* Generic Mouse */
208 (IsEqualGUID(&DInput_Wine_Mouse_GUID,rguid))) { /* Wine Mouse */
209 if ((riid == NULL) ||
210 IsEqualGUID(&IID_IDirectInputDeviceA,riid) ||
211 IsEqualGUID(&IID_IDirectInputDevice2A,riid) ||
212 IsEqualGUID(&IID_IDirectInputDevice7A,riid) ||
213 IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
214 *pdev = (IDirectInputDeviceA*) alloc_device(rguid, &SysMouseAvt, dinput);
215 TRACE("Creating a Mouse device (%p)\n", *pdev);
216 if (!*pdev) return DIERR_OUTOFMEMORY;
217 return DI_OK;
218 } else
219 return DIERR_NOINTERFACE;
222 return DIERR_DEVICENOTREG;
225 static HRESULT mousedev_create_deviceW(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEW* pdev)
227 if ((IsEqualGUID(&GUID_SysMouse,rguid)) || /* Generic Mouse */
228 (IsEqualGUID(&DInput_Wine_Mouse_GUID,rguid))) { /* Wine Mouse */
229 if ((riid == NULL) ||
230 IsEqualGUID(&IID_IDirectInputDeviceW,riid) ||
231 IsEqualGUID(&IID_IDirectInputDevice2W,riid) ||
232 IsEqualGUID(&IID_IDirectInputDevice7W,riid) ||
233 IsEqualGUID(&IID_IDirectInputDevice8W,riid)) {
234 *pdev = (IDirectInputDeviceW*) alloc_device(rguid, &SysMouseWvt, dinput);
235 TRACE("Creating a Mouse device (%p)\n", *pdev);
236 if (!*pdev) return DIERR_OUTOFMEMORY;
237 return DI_OK;
238 } else
239 return DIERR_NOINTERFACE;
242 return DIERR_DEVICENOTREG;
245 const struct dinput_device mouse_device = {
246 "Wine mouse driver",
247 mousedev_enum_deviceA,
248 mousedev_enum_deviceW,
249 mousedev_create_deviceA,
250 mousedev_create_deviceW
253 /******************************************************************************
254 * SysMouseA (DInput Mouse support)
257 /* low-level mouse hook */
258 static LRESULT CALLBACK dinput_mouse_hook( int code, WPARAM wparam, LPARAM lparam )
260 MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam;
261 SysMouseImpl* This = (SysMouseImpl*) current_lock;
262 DWORD dwCoop;
263 int wdata = 0, inst_id = -1;
265 if (code != HC_ACTION) return CallNextHookEx( 0, code, wparam, lparam );
267 EnterCriticalSection(&This->base.crit);
268 dwCoop = This->base.dwCoopLevel;
270 switch(wparam) {
271 case WM_MOUSEMOVE:
273 POINT pt, pt1;
275 GetCursorPos(&pt);
276 This->m_state.lX += pt.x = hook->pt.x - pt.x;
277 This->m_state.lY += pt.y = hook->pt.y - pt.y;
279 if (This->base.data_format.user_df->dwFlags & DIDF_ABSAXIS)
281 pt1.x = This->m_state.lX;
282 pt1.y = This->m_state.lY;
283 } else
284 pt1 = pt;
286 if (pt.x)
287 queue_event((LPDIRECTINPUTDEVICE8A)This, id_to_offset(&This->base.data_format,
288 DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS),
289 pt1.x, hook->time, This->base.dinput->evsequence);
290 if (pt.y)
292 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS;
293 wdata = pt1.y;
296 This->need_warp = (pt.x || pt.y) && dwCoop & DISCL_EXCLUSIVE;
297 break;
299 case WM_MOUSEWHEEL:
300 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_Z_AXIS_INSTANCE) | DIDFT_RELAXIS;
301 This->m_state.lZ += wdata = (short)HIWORD(hook->mouseData);
302 break;
303 case WM_LBUTTONDOWN:
304 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 0) | DIDFT_PSHBUTTON;
305 This->m_state.rgbButtons[0] = wdata = 0x80;
306 break;
307 case WM_LBUTTONUP:
308 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 0) | DIDFT_PSHBUTTON;
309 This->m_state.rgbButtons[0] = wdata = 0x00;
310 break;
311 case WM_RBUTTONDOWN:
312 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 1) | DIDFT_PSHBUTTON;
313 This->m_state.rgbButtons[1] = wdata = 0x80;
314 break;
315 case WM_RBUTTONUP:
316 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 1) | DIDFT_PSHBUTTON;
317 This->m_state.rgbButtons[1] = wdata = 0x00;
318 break;
319 case WM_MBUTTONDOWN:
320 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 2) | DIDFT_PSHBUTTON;
321 This->m_state.rgbButtons[2] = wdata = 0x80;
322 break;
323 case WM_MBUTTONUP:
324 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 2) | DIDFT_PSHBUTTON;
325 This->m_state.rgbButtons[2] = wdata = 0x00;
326 break;
327 case WM_XBUTTONDOWN:
328 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 2 + HIWORD(hook->mouseData)) | DIDFT_PSHBUTTON;
329 This->m_state.rgbButtons[2 + HIWORD(hook->mouseData)] = wdata = 0x80;
330 break;
331 case WM_XBUTTONUP:
332 inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + 2 + HIWORD(hook->mouseData)) | DIDFT_PSHBUTTON;
333 This->m_state.rgbButtons[2 + HIWORD(hook->mouseData)] = wdata = 0x00;
334 break;
337 if (TRACE_ON(dinput))
339 int i;
341 TRACE("msg %lx @ (%d %d): (X: %d Y: %d Z: %d", wparam, hook->pt.x, hook->pt.y,
342 This->m_state.lX, This->m_state.lY, This->m_state.lZ);
343 for (i = 0; i < 5; i++) TRACE(" B%d: %02x", i, This->m_state.rgbButtons[i]);
344 TRACE(")\n");
346 if (inst_id != -1)
347 queue_event((LPDIRECTINPUTDEVICE8A)This, id_to_offset(&This->base.data_format, inst_id),
348 wdata, hook->time, This->base.dinput->evsequence++);
350 LeaveCriticalSection(&This->base.crit);
352 /* Ignore message */
353 if (dwCoop & DISCL_EXCLUSIVE) return 1;
355 /* Pass the events down to previous handlers (e.g. win32 input) */
356 return CallNextHookEx( 0, code, wparam, lparam );
359 static BOOL dinput_window_check(SysMouseImpl* This) {
360 RECT rect;
361 DWORD centerX, centerY;
363 /* make sure the window hasn't moved */
364 if(!GetWindowRect(This->base.win, &rect))
365 return FALSE;
366 centerX = (rect.right - rect.left) / 2;
367 centerY = (rect.bottom - rect.top ) / 2;
368 if (This->win_centerX != centerX || This->win_centerY != centerY) {
369 This->win_centerX = centerX;
370 This->win_centerY = centerY;
372 This->mapped_center.x = This->win_centerX;
373 This->mapped_center.y = This->win_centerY;
374 MapWindowPoints(This->base.win, HWND_DESKTOP, &This->mapped_center, 1);
375 return TRUE;
379 /******************************************************************************
380 * Acquire : gets exclusive control of the mouse
382 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
384 SysMouseImpl *This = (SysMouseImpl *)iface;
385 RECT rect;
386 POINT point;
387 HRESULT res;
389 TRACE("(this=%p)\n",This);
391 if ((res = IDirectInputDevice2AImpl_Acquire(iface)) != DI_OK) return res;
393 /* Store (in a global variable) the current lock */
394 current_lock = (IDirectInputDevice8A*)This;
396 /* Init the mouse state */
397 GetCursorPos( &point );
398 if (This->base.data_format.user_df->dwFlags & DIDF_ABSAXIS)
400 This->m_state.lX = point.x;
401 This->m_state.lY = point.y;
402 } else {
403 This->m_state.lX = 0;
404 This->m_state.lY = 0;
405 This->org_coords = point;
407 This->m_state.lZ = 0;
408 This->m_state.rgbButtons[0] = GetKeyState(VK_LBUTTON) & 0x80;
409 This->m_state.rgbButtons[1] = GetKeyState(VK_RBUTTON) & 0x80;
410 This->m_state.rgbButtons[2] = GetKeyState(VK_MBUTTON) & 0x80;
412 /* Install our mouse hook */
413 if (This->base.dwCoopLevel & DISCL_EXCLUSIVE)
414 ShowCursor(FALSE); /* hide cursor */
415 set_dinput_hook(WH_MOUSE_LL, dinput_mouse_hook);
417 /* Get the window dimension and find the center */
418 GetWindowRect(This->base.win, &rect);
419 This->win_centerX = (rect.right - rect.left) / 2;
420 This->win_centerY = (rect.bottom - rect.top ) / 2;
422 /* Warp the mouse to the center of the window */
423 if (This->base.dwCoopLevel & DISCL_EXCLUSIVE)
425 This->mapped_center.x = This->win_centerX;
426 This->mapped_center.y = This->win_centerY;
427 MapWindowPoints(This->base.win, HWND_DESKTOP, &This->mapped_center, 1);
428 TRACE("Warping mouse to %d - %d\n", This->mapped_center.x, This->mapped_center.y);
429 SetCursorPos( This->mapped_center.x, This->mapped_center.y );
430 This->last_warped = GetCurrentTime();
432 This->need_warp = FALSE;
435 return DI_OK;
438 /******************************************************************************
439 * Unacquire : frees the mouse
441 static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
443 SysMouseImpl *This = (SysMouseImpl *)iface;
444 HRESULT res;
446 TRACE("(this=%p)\n",This);
448 if ((res = IDirectInputDevice2AImpl_Unacquire(iface)) != DI_OK) return res;
450 set_dinput_hook(WH_MOUSE_LL, NULL);
451 if (This->base.dwCoopLevel & DISCL_EXCLUSIVE)
452 ShowCursor(TRUE); /* show cursor */
454 /* No more locks */
455 if (current_lock == (IDirectInputDevice8A*) This)
456 current_lock = NULL;
457 else
458 ERR("this(%p) != current_lock(%p)\n", This, current_lock);
460 /* And put the mouse cursor back where it was at acquire time */
461 if (This->base.dwCoopLevel & DISCL_EXCLUSIVE)
463 TRACE(" warping mouse back to (%d , %d)\n", This->org_coords.x, This->org_coords.y);
464 SetCursorPos(This->org_coords.x, This->org_coords.y);
467 return DI_OK;
470 /******************************************************************************
471 * GetDeviceState : returns the "state" of the mouse.
473 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
474 * supported.
476 static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
477 LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr
479 SysMouseImpl *This = (SysMouseImpl *)iface;
481 if(This->base.acquired == 0) return DIERR_NOTACQUIRED;
483 TRACE("(this=%p,0x%08x,%p):\n", This, len, ptr);
484 TRACE("(X: %d - Y: %d - Z: %d L: %02x M: %02x R: %02x)\n",
485 This->m_state.lX, This->m_state.lY, This->m_state.lZ,
486 This->m_state.rgbButtons[0], This->m_state.rgbButtons[2], This->m_state.rgbButtons[1]);
488 EnterCriticalSection(&This->base.crit);
489 /* Copy the current mouse state */
490 fill_DataFormat(ptr, &(This->m_state), &This->base.data_format);
492 /* Initialize the buffer when in relative mode */
493 if (!(This->base.data_format.user_df->dwFlags & DIDF_ABSAXIS))
495 This->m_state.lX = 0;
496 This->m_state.lY = 0;
497 This->m_state.lZ = 0;
499 LeaveCriticalSection(&This->base.crit);
501 /* Check if we need to do a mouse warping */
502 if (This->need_warp && (GetCurrentTime() - This->last_warped > 10))
504 if(!dinput_window_check(This))
505 return DIERR_GENERIC;
506 TRACE("Warping mouse to %d - %d\n", This->mapped_center.x, This->mapped_center.y);
507 SetCursorPos( This->mapped_center.x, This->mapped_center.y );
508 This->last_warped = GetCurrentTime();
510 This->need_warp = FALSE;
513 return DI_OK;
516 /******************************************************************************
517 * GetDeviceData : gets buffered input data.
519 static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface,
520 DWORD dodsize, LPDIDEVICEOBJECTDATA dod, LPDWORD entries, DWORD flags)
522 SysMouseImpl *This = (SysMouseImpl *)iface;
523 HRESULT res;
525 res = IDirectInputDevice2AImpl_GetDeviceData(iface, dodsize, dod, entries, flags);
526 if (FAILED(res)) return res;
528 /* Check if we need to do a mouse warping */
529 if (This->need_warp && (GetCurrentTime() - This->last_warped > 10))
531 if(!dinput_window_check(This))
532 return DIERR_GENERIC;
533 TRACE("Warping mouse to %d - %d\n", This->mapped_center.x, This->mapped_center.y);
534 SetCursorPos( This->mapped_center.x, This->mapped_center.y );
535 This->last_warped = GetCurrentTime();
537 This->need_warp = FALSE;
539 return res;
542 /******************************************************************************
543 * GetProperty : get input device properties
545 static HRESULT WINAPI SysMouseAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface,
546 REFGUID rguid,
547 LPDIPROPHEADER pdiph)
549 SysMouseImpl *This = (SysMouseImpl *)iface;
551 TRACE("(%p) %s,%p\n", This, debugstr_guid(rguid), pdiph);
552 _dump_DIPROPHEADER(pdiph);
554 if (!HIWORD(rguid)) {
555 switch (LOWORD(rguid)) {
556 case (DWORD) DIPROP_GRANULARITY: {
557 LPDIPROPDWORD pr = (LPDIPROPDWORD) pdiph;
559 /* We'll just assume that the app asks about the Z axis */
560 pr->dwData = WHEEL_DELTA;
562 break;
565 case (DWORD) DIPROP_RANGE: {
566 LPDIPROPRANGE pr = (LPDIPROPRANGE) pdiph;
568 if ((pdiph->dwHow == DIPH_BYID) &&
569 ((pdiph->dwObj == (DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS)) ||
570 (pdiph->dwObj == (DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS)))) {
571 /* Querying the range of either the X or the Y axis. As I do
572 not know the range, do as if the range were
573 unrestricted...*/
574 pr->lMin = DIPROPRANGE_NOMIN;
575 pr->lMax = DIPROPRANGE_NOMAX;
578 break;
581 default:
582 return IDirectInputDevice2AImpl_GetProperty(iface, rguid, pdiph);
586 return DI_OK;
589 /******************************************************************************
590 * GetCapabilities : get the device capablitites
592 static HRESULT WINAPI SysMouseAImpl_GetCapabilities(
593 LPDIRECTINPUTDEVICE8A iface,
594 LPDIDEVCAPS lpDIDevCaps)
596 SysMouseImpl *This = (SysMouseImpl *)iface;
597 DIDEVCAPS devcaps;
599 TRACE("(this=%p,%p)\n",This,lpDIDevCaps);
601 if ((lpDIDevCaps->dwSize != sizeof(DIDEVCAPS)) && (lpDIDevCaps->dwSize != sizeof(DIDEVCAPS_DX3))) {
602 WARN("invalid parameter\n");
603 return DIERR_INVALIDPARAM;
606 devcaps.dwSize = lpDIDevCaps->dwSize;
607 devcaps.dwFlags = DIDC_ATTACHED;
608 if (This->base.dinput->dwVersion >= 0x0800)
609 devcaps.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8);
610 else
611 devcaps.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8);
612 devcaps.dwAxes = 3;
613 devcaps.dwButtons = 8;
614 devcaps.dwPOVs = 0;
615 devcaps.dwFFSamplePeriod = 0;
616 devcaps.dwFFMinTimeResolution = 0;
617 devcaps.dwFirmwareRevision = 100;
618 devcaps.dwHardwareRevision = 100;
619 devcaps.dwFFDriverVersion = 0;
621 memcpy(lpDIDevCaps, &devcaps, lpDIDevCaps->dwSize);
623 return DI_OK;
626 /******************************************************************************
627 * GetObjectInfo : get information about a device object such as a button
628 * or axis
630 static HRESULT WINAPI SysMouseWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
631 LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow)
633 static const WCHAR x_axisW[] = {'X','-','A','x','i','s',0};
634 static const WCHAR y_axisW[] = {'Y','-','A','x','i','s',0};
635 static const WCHAR wheelW[] = {'W','h','e','e','l',0};
636 static const WCHAR buttonW[] = {'B','u','t','t','o','n',' ','%','d',0};
637 HRESULT res;
639 res = IDirectInputDevice2WImpl_GetObjectInfo(iface, pdidoi, dwObj, dwHow);
640 if (res != DI_OK) return res;
642 if (IsEqualGUID(&pdidoi->guidType, &GUID_XAxis)) strcpyW(pdidoi->tszName, x_axisW);
643 else if (IsEqualGUID(&pdidoi->guidType, &GUID_YAxis)) strcpyW(pdidoi->tszName, y_axisW);
644 else if (IsEqualGUID(&pdidoi->guidType, &GUID_ZAxis)) strcpyW(pdidoi->tszName, wheelW);
645 else if (pdidoi->dwType & DIDFT_BUTTON)
646 wsprintfW(pdidoi->tszName, buttonW, DIDFT_GETINSTANCE(pdidoi->dwType) - 3);
648 _dump_OBJECTINSTANCEW(pdidoi);
649 return res;
652 static HRESULT WINAPI SysMouseAImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8A iface,
653 LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow)
655 HRESULT res;
656 DIDEVICEOBJECTINSTANCEW didoiW;
657 DWORD dwSize = pdidoi->dwSize;
659 didoiW.dwSize = sizeof(didoiW);
660 res = SysMouseWImpl_GetObjectInfo((LPDIRECTINPUTDEVICE8W)iface, &didoiW, dwObj, dwHow);
661 if (res != DI_OK) return res;
663 memset(pdidoi, 0, pdidoi->dwSize);
664 memcpy(pdidoi, &didoiW, FIELD_OFFSET(DIDEVICEOBJECTINSTANCEW, tszName));
665 pdidoi->dwSize = dwSize;
666 WideCharToMultiByte(CP_ACP, 0, didoiW.tszName, -1, pdidoi->tszName,
667 sizeof(pdidoi->tszName), NULL, NULL);
669 return res;
672 /******************************************************************************
673 * GetDeviceInfo : get information about a device's identity
675 static HRESULT WINAPI SysMouseAImpl_GetDeviceInfo(
676 LPDIRECTINPUTDEVICE8A iface,
677 LPDIDEVICEINSTANCEA pdidi)
679 SysMouseImpl *This = (SysMouseImpl *)iface;
680 TRACE("(this=%p,%p)\n", This, pdidi);
682 if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) {
683 WARN(" dinput3 not supporte yet...\n");
684 return DI_OK;
687 fill_mouse_dideviceinstanceA(pdidi, This->base.dinput->dwVersion);
689 return DI_OK;
692 static HRESULT WINAPI SysMouseWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW pdidi)
694 SysMouseImpl *This = (SysMouseImpl *)iface;
695 TRACE("(this=%p,%p)\n", This, pdidi);
697 if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) {
698 WARN(" dinput3 not supporte yet...\n");
699 return DI_OK;
702 fill_mouse_dideviceinstanceW(pdidi, This->base.dinput->dwVersion);
704 return DI_OK;
708 static const IDirectInputDevice8AVtbl SysMouseAvt =
710 IDirectInputDevice2AImpl_QueryInterface,
711 IDirectInputDevice2AImpl_AddRef,
712 IDirectInputDevice2AImpl_Release,
713 SysMouseAImpl_GetCapabilities,
714 IDirectInputDevice2AImpl_EnumObjects,
715 SysMouseAImpl_GetProperty,
716 IDirectInputDevice2AImpl_SetProperty,
717 SysMouseAImpl_Acquire,
718 SysMouseAImpl_Unacquire,
719 SysMouseAImpl_GetDeviceState,
720 SysMouseAImpl_GetDeviceData,
721 IDirectInputDevice2AImpl_SetDataFormat,
722 IDirectInputDevice2AImpl_SetEventNotification,
723 IDirectInputDevice2AImpl_SetCooperativeLevel,
724 SysMouseAImpl_GetObjectInfo,
725 SysMouseAImpl_GetDeviceInfo,
726 IDirectInputDevice2AImpl_RunControlPanel,
727 IDirectInputDevice2AImpl_Initialize,
728 IDirectInputDevice2AImpl_CreateEffect,
729 IDirectInputDevice2AImpl_EnumEffects,
730 IDirectInputDevice2AImpl_GetEffectInfo,
731 IDirectInputDevice2AImpl_GetForceFeedbackState,
732 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
733 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
734 IDirectInputDevice2AImpl_Escape,
735 IDirectInputDevice2AImpl_Poll,
736 IDirectInputDevice2AImpl_SendDeviceData,
737 IDirectInputDevice7AImpl_EnumEffectsInFile,
738 IDirectInputDevice7AImpl_WriteEffectToFile,
739 IDirectInputDevice8AImpl_BuildActionMap,
740 IDirectInputDevice8AImpl_SetActionMap,
741 IDirectInputDevice8AImpl_GetImageInfo
744 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
745 # define XCAST(fun) (typeof(SysMouseWvt.fun))
746 #else
747 # define XCAST(fun) (void*)
748 #endif
750 static const IDirectInputDevice8WVtbl SysMouseWvt =
752 IDirectInputDevice2WImpl_QueryInterface,
753 XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
754 XCAST(Release)IDirectInputDevice2AImpl_Release,
755 XCAST(GetCapabilities)SysMouseAImpl_GetCapabilities,
756 IDirectInputDevice2WImpl_EnumObjects,
757 XCAST(GetProperty)SysMouseAImpl_GetProperty,
758 XCAST(SetProperty)IDirectInputDevice2AImpl_SetProperty,
759 XCAST(Acquire)SysMouseAImpl_Acquire,
760 XCAST(Unacquire)SysMouseAImpl_Unacquire,
761 XCAST(GetDeviceState)SysMouseAImpl_GetDeviceState,
762 XCAST(GetDeviceData)SysMouseAImpl_GetDeviceData,
763 XCAST(SetDataFormat)IDirectInputDevice2AImpl_SetDataFormat,
764 XCAST(SetEventNotification)IDirectInputDevice2AImpl_SetEventNotification,
765 XCAST(SetCooperativeLevel)IDirectInputDevice2AImpl_SetCooperativeLevel,
766 SysMouseWImpl_GetObjectInfo,
767 SysMouseWImpl_GetDeviceInfo,
768 XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel,
769 XCAST(Initialize)IDirectInputDevice2AImpl_Initialize,
770 XCAST(CreateEffect)IDirectInputDevice2AImpl_CreateEffect,
771 IDirectInputDevice2WImpl_EnumEffects,
772 IDirectInputDevice2WImpl_GetEffectInfo,
773 XCAST(GetForceFeedbackState)IDirectInputDevice2AImpl_GetForceFeedbackState,
774 XCAST(SendForceFeedbackCommand)IDirectInputDevice2AImpl_SendForceFeedbackCommand,
775 XCAST(EnumCreatedEffectObjects)IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
776 XCAST(Escape)IDirectInputDevice2AImpl_Escape,
777 XCAST(Poll)IDirectInputDevice2AImpl_Poll,
778 XCAST(SendDeviceData)IDirectInputDevice2AImpl_SendDeviceData,
779 IDirectInputDevice7WImpl_EnumEffectsInFile,
780 IDirectInputDevice7WImpl_WriteEffectToFile,
781 IDirectInputDevice8WImpl_BuildActionMap,
782 IDirectInputDevice8WImpl_SetActionMap,
783 IDirectInputDevice8WImpl_GetImageInfo
785 #undef XCAST