[DINPUT_WINETEST] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / modules / rostests / winetests / dinput / mouse.c
1 /*
2 * Copyright (c) 2005 Robert Reif
3 * Copyright (c) 2006 Vitaliy Margolen
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #define DIRECTINPUT_VERSION 0x0700
21
22 #define COBJMACROS
23 #include <windows.h>
24
25 #include <math.h>
26 #include <stdlib.h>
27
28 #include "wine/test.h"
29 #include "windef.h"
30 #include "wingdi.h"
31 #include "dinput.h"
32
33 static const HRESULT SetCoop_null_window[16] = {
34 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG,
35 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG,
36 E_INVALIDARG, E_HANDLE, S_OK, E_INVALIDARG,
37 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG};
38
39 static const HRESULT SetCoop_real_window[16] = {
40 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG,
41 E_INVALIDARG, S_OK, S_OK, E_INVALIDARG,
42 E_INVALIDARG, E_NOTIMPL, S_OK, E_INVALIDARG,
43 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG};
44
45 static const HRESULT SetCoop_child_window[16] = {
46 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG,
47 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG,
48 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG,
49 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG};
50
51 static void test_set_coop(IDirectInputA *pDI, HWND hwnd)
52 {
53 HRESULT hr;
54 IDirectInputDeviceA *pMouse = NULL;
55 int i;
56 HWND child;
57
58 hr = IDirectInput_CreateDevice(pDI, &GUID_SysMouse, &pMouse, NULL);
59 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
60 if (FAILED(hr)) return;
61
62 for (i=0; i<16; i++)
63 {
64 hr = IDirectInputDevice_SetCooperativeLevel(pMouse, NULL, i);
65 ok(hr == SetCoop_null_window[i], "SetCooperativeLevel(NULL, %d): %08x\n", i, hr);
66 }
67 for (i=0; i<16; i++)
68 {
69 hr = IDirectInputDevice_SetCooperativeLevel(pMouse, hwnd, i);
70 ok(hr == SetCoop_real_window[i], "SetCooperativeLevel(hwnd, %d): %08x\n", i, hr);
71 }
72
73 child = CreateWindowA("static", "Title", WS_CHILD | WS_VISIBLE, 10, 10, 50, 50, hwnd, NULL,
74 NULL, NULL);
75 ok(child != NULL, "err: %d\n", GetLastError());
76
77 for (i=0; i<16; i++)
78 {
79 hr = IDirectInputDevice_SetCooperativeLevel(pMouse, child, i);
80 ok(hr == SetCoop_child_window[i], "SetCooperativeLevel(child, %d): %08x\n", i, hr);
81 }
82
83 DestroyWindow(child);
84 if (pMouse) IUnknown_Release(pMouse);
85 }
86
87 static void test_acquire(IDirectInputA *pDI, HWND hwnd)
88 {
89 HRESULT hr;
90 IDirectInputDeviceA *pMouse = NULL;
91 DIMOUSESTATE m_state;
92 HWND hwnd2;
93 DIPROPDWORD di_op;
94 DIDEVICEOBJECTDATA mouse_state;
95 DWORD cnt;
96 int i;
97
98 if (! SetForegroundWindow(hwnd))
99 {
100 skip("Not running as foreground app, skipping acquire tests\n");
101 return;
102 }
103
104 hr = IDirectInput_CreateDevice(pDI, &GUID_SysMouse, &pMouse, NULL);
105 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
106 if (FAILED(hr)) return;
107
108 hr = IDirectInputDevice_SetCooperativeLevel(pMouse, hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
109 ok(hr == S_OK, "SetCooperativeLevel: %08x\n", hr);
110
111 memset(&di_op, 0, sizeof(di_op));
112 di_op.dwData = 5;
113 di_op.diph.dwHow = DIPH_DEVICE;
114 di_op.diph.dwSize = sizeof(DIPROPDWORD);
115 di_op.diph.dwHeaderSize = sizeof(DIPROPHEADER);
116 hr = IDirectInputDevice_SetProperty(pMouse, DIPROP_BUFFERSIZE, (LPCDIPROPHEADER)&di_op);
117 ok(hr == S_OK, "SetProperty() failed: %08x\n", hr);
118
119 hr = IDirectInputDevice_SetDataFormat(pMouse, &c_dfDIMouse);
120 ok(SUCCEEDED(hr), "IDirectInputDevice_SetDataFormat() failed: %08x\n", hr);
121 hr = IDirectInputDevice_Unacquire(pMouse);
122 ok(hr == S_FALSE, "IDirectInputDevice_Unacquire() should have failed: %08x\n", hr);
123 hr = IDirectInputDevice_Acquire(pMouse);
124 ok(SUCCEEDED(hr), "IDirectInputDevice_Acquire() failed: %08x\n", hr);
125 hr = IDirectInputDevice_Acquire(pMouse);
126 ok(hr == S_FALSE, "IDirectInputDevice_Acquire() should have failed: %08x\n", hr);
127
128 /* Foreground coop level requires window to have focus */
129 /* Create a temporary window, this should make dinput
130 * lose mouse input */
131 hwnd2 = CreateWindowA("static", "Temporary", WS_VISIBLE, 10, 210, 200, 200, NULL, NULL, NULL,
132 NULL);
133 ok(hwnd2 != NULL, "CreateWindowA failed with %u\n", GetLastError());
134
135 hr = IDirectInputDevice_GetDeviceState(pMouse, sizeof(m_state), &m_state);
136 ok(hr == DIERR_NOTACQUIRED, "GetDeviceState() should have failed: %08x\n", hr);
137
138 hr = IDirectInputDevice_Acquire(pMouse);
139 ok(hr == DIERR_OTHERAPPHASPRIO, "Acquire() should have failed: %08x\n", hr);
140
141 SetActiveWindow( hwnd );
142 hr = IDirectInputDevice_Acquire(pMouse);
143 ok(hr == S_OK, "Acquire() failed: %08x\n", hr);
144
145 if (!winetest_interactive)
146 skip("ROSTESTS-176/CORE-9710: Skipping randomly failing tests\n");
147 else {
148
149 mouse_event(MOUSEEVENTF_MOVE, 10, 10, 0, 0);
150 cnt = 1;
151 hr = IDirectInputDevice_GetDeviceData(pMouse, sizeof(mouse_state), &mouse_state, &cnt, 0);
152 ok(hr == S_OK && cnt > 0, "GetDeviceData() failed: %08x cnt:%d\n", hr, cnt);
153
154 mouse_event(MOUSEEVENTF_MOVE, 10, 10, 0, 0);
155 hr = IDirectInputDevice_Unacquire(pMouse);
156 ok(hr == S_OK, "Failed: %08x\n", hr);
157 cnt = 1;
158 hr = IDirectInputDevice_GetDeviceData(pMouse, sizeof(mouse_state), &mouse_state, &cnt, 0);
159 ok(hr == S_OK && cnt > 0, "GetDeviceData() failed: %08x cnt:%d\n", hr, cnt);
160
161 hr = IDirectInputDevice_Acquire(pMouse);
162 ok(hr == S_OK, "Failed: %08x\n", hr);
163 mouse_event(MOUSEEVENTF_MOVE, 10, 10, 0, 0);
164 hr = IDirectInputDevice_Unacquire(pMouse);
165 ok(hr == S_OK, "Failed: %08x\n", hr);
166
167 hr = IDirectInputDevice_Acquire(pMouse);
168 ok(hr == S_OK, "Failed: %08x\n", hr);
169 cnt = 1;
170 hr = IDirectInputDevice_GetDeviceData(pMouse, sizeof(mouse_state), &mouse_state, &cnt, 0);
171 ok(hr == S_OK && cnt > 0, "GetDeviceData() failed: %08x cnt:%d\n", hr, cnt);
172
173 /* Check for buffer overflow */
174 for (i = 0; i < 6; i++)
175 mouse_event(MOUSEEVENTF_MOVE, 10 + i, 10 + i, 0, 0);
176
177 cnt = 1;
178 hr = IDirectInputDevice_GetDeviceData(pMouse, sizeof(mouse_state), &mouse_state, &cnt, 0);
179 ok(hr == DI_OK, "GetDeviceData() failed: %08x cnt:%d\n", hr, cnt);
180 cnt = 1;
181 hr = IDirectInputDevice_GetDeviceData(pMouse, sizeof(mouse_state), &mouse_state, &cnt, 0);
182 ok(hr == DI_OK && cnt == 1, "GetDeviceData() failed: %08x cnt:%d\n", hr, cnt);
183
184 /* Check for granularity property using BYOFFSET */
185 memset(&di_op, 0, sizeof(di_op));
186 di_op.diph.dwHow = DIPH_BYOFFSET;
187 di_op.diph.dwObj = DIMOFS_Y;
188 di_op.diph.dwSize = sizeof(DIPROPDWORD);
189 di_op.diph.dwHeaderSize = sizeof(DIPROPHEADER);
190 hr = IDirectInputDevice_GetProperty(pMouse, DIPROP_GRANULARITY, &di_op.diph);
191 /* Granularity of Y axis should be 1! */
192 ok(hr == S_OK && di_op.dwData == 1, "GetProperty(): %08x, dwData: %i but should be 1.\n", hr, di_op.dwData);
193
194 /* Check for granularity property using BYID */
195 memset(&di_op, 0, sizeof(di_op));
196 di_op.diph.dwHow = DIPH_BYID;
197 /* WINE_MOUSE_Y_AXIS_INSTANCE := 1 */
198 di_op.diph.dwObj = (DIDFT_MAKEINSTANCE(1) | DIDFT_RELAXIS);
199 di_op.diph.dwSize = sizeof(DIPROPDWORD);
200 di_op.diph.dwHeaderSize = sizeof(DIPROPHEADER);
201 hr = IDirectInputDevice_GetProperty(pMouse, DIPROP_GRANULARITY, &di_op.diph);
202 /* Granularity of Y axis should be 1! */
203 ok(hr == S_OK && di_op.dwData == 1, "GetProperty(): %08x, dwData: %i but should be 1.\n", hr, di_op.dwData);
204 }
205 if (pMouse) IUnknown_Release(pMouse);
206
207 DestroyWindow( hwnd2 );
208 }
209
210 static void test_GetDeviceInfo(IDirectInputA *pDI)
211 {
212 HRESULT hr;
213 IDirectInputDeviceA *pMouse = NULL;
214 DIDEVICEINSTANCEA instA;
215 DIDEVICEINSTANCE_DX3A inst3A;
216
217 hr = IDirectInput_CreateDevice(pDI, &GUID_SysMouse, &pMouse, NULL);
218 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
219 if (FAILED(hr)) return;
220
221 instA.dwSize = sizeof(instA);
222 hr = IDirectInputDevice_GetDeviceInfo(pMouse, &instA);
223 ok(SUCCEEDED(hr), "got %08x\n", hr);
224
225 inst3A.dwSize = sizeof(inst3A);
226 hr = IDirectInputDevice_GetDeviceInfo(pMouse, (DIDEVICEINSTANCEA *)&inst3A);
227 ok(SUCCEEDED(hr), "got %08x\n", hr);
228
229 ok(instA.dwSize != inst3A.dwSize, "got %d, %d \n", instA.dwSize, inst3A.dwSize);
230 ok(IsEqualGUID(&instA.guidInstance, &inst3A.guidInstance), "got %s, %s\n",
231 wine_dbgstr_guid(&instA.guidInstance), wine_dbgstr_guid(&inst3A.guidInstance) );
232 ok(IsEqualGUID(&instA.guidProduct, &inst3A.guidProduct), "got %s, %s\n",
233 wine_dbgstr_guid(&instA.guidProduct), wine_dbgstr_guid(&inst3A.guidProduct) );
234 ok(instA.dwDevType == inst3A.dwDevType, "got %d, %d\n", instA.dwDevType, inst3A.dwDevType);
235
236 IUnknown_Release(pMouse);
237 }
238
239 static BOOL CALLBACK EnumAxes(const DIDEVICEOBJECTINSTANCEA *pdidoi, void *pContext)
240 {
241 if (IsEqualIID(&pdidoi->guidType, &GUID_XAxis) ||
242 IsEqualIID(&pdidoi->guidType, &GUID_YAxis) ||
243 IsEqualIID(&pdidoi->guidType, &GUID_ZAxis))
244 {
245 ok(pdidoi->dwFlags & DIDOI_ASPECTPOSITION, "Missing DIDOI_ASPECTPOSITION, flags are 0x%x\n",
246 pdidoi->dwFlags);
247 }
248 else
249 ok(pdidoi->dwFlags == 0, "Flags are 0x%x\n", pdidoi->dwFlags);
250
251 return DIENUM_CONTINUE;
252 }
253
254 static void test_mouse_EnumObjects(IDirectInputA *pDI)
255 {
256 HRESULT hr;
257 IDirectInputDeviceA *pMouse = NULL;
258
259 hr = IDirectInput_CreateDevice(pDI, &GUID_SysMouse, &pMouse, NULL);
260 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
261 if (FAILED(hr)) return;
262
263 hr = IDirectInputDevice_EnumObjects(pMouse, EnumAxes, NULL, DIDFT_ALL);
264 ok(hr==DI_OK,"IDirectInputDevice_EnumObjects() failed: %08x\n", hr);
265
266 if (pMouse) IUnknown_Release(pMouse);
267 }
268
269 static void mouse_tests(void)
270 {
271 HRESULT hr;
272 IDirectInputA *pDI = NULL;
273 HINSTANCE hInstance = GetModuleHandleW(NULL);
274 HWND hwnd;
275 ULONG ref = 0;
276
277 hr = DirectInputCreateA(hInstance, DIRECTINPUT_VERSION, &pDI, NULL);
278 if (hr == DIERR_OLDDIRECTINPUTVERSION)
279 {
280 skip("Tests require a newer dinput version\n");
281 return;
282 }
283 ok(SUCCEEDED(hr), "DirectInputCreateA() failed: %08x\n", hr);
284 if (FAILED(hr)) return;
285
286 hwnd = CreateWindowA("static", "Title", WS_OVERLAPPEDWINDOW, 10, 10, 200, 200, NULL, NULL,
287 NULL, NULL);
288 ok(hwnd != NULL, "err: %d\n", GetLastError());
289 if (hwnd)
290 {
291 ShowWindow(hwnd, SW_SHOW);
292
293 test_set_coop(pDI, hwnd);
294 test_acquire(pDI, hwnd);
295 test_GetDeviceInfo(pDI);
296 test_mouse_EnumObjects(pDI);
297
298 DestroyWindow(hwnd);
299 }
300 if (pDI) ref = IUnknown_Release(pDI);
301 ok(!ref, "IDirectInput_Release() reference count = %d\n", ref);
302 }
303
304 START_TEST(mouse)
305 {
306 CoInitialize(NULL);
307
308 mouse_tests();
309
310 CoUninitialize();
311 }