2 * Unit tests for joystick APIs
4 * Copyright 2014 Bruno Jesus
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/test.h"
31 static LRESULT CALLBACK
proc_window(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
33 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
36 static void create_window(void)
38 const char name
[] = "Joystick Test";
41 memset(&wc
, 0, sizeof(wc
));
42 wc
.lpfnWndProc
= proc_window
;
44 wc
.lpszClassName
= name
;
46 window
= CreateWindowExA(0, name
, name
, WS_OVERLAPPEDWINDOW
,
47 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
48 NULL
, NULL
, NULL
, NULL
);
49 ok(window
!= NULL
, "Expected CreateWindowEx to work, error %d\n", GetLastError());
52 static void destroy_window(void)
54 DestroyWindow(window
);
58 static void test_api(void)
67 char buffer
[sizeof(JOYINFOEX
) * 2];
69 UINT i
, par
, devices
, joyid
, win98
= 0, win8
= 0;
70 UINT period
[] = {0, 1, 9, 10, 100, 1000, 1001, 10000, 65535, 65536, 0xFFFFFFFF};
71 UINT threshold_error
= 0x600, period_win8_error
= 0x7CE;
72 UINT flags
[] = { JOY_RETURNALL
, JOY_RETURNBUTTONS
, JOY_RETURNCENTERED
, JOY_RETURNPOV
,
73 JOY_RETURNPOVCTS
, JOY_RETURNR
, JOY_RETURNRAWDATA
, JOY_RETURNU
,
74 JOY_RETURNV
, JOY_RETURNX
, JOY_RETURNY
, JOY_RETURNZ
};
76 devices
= joyGetNumDevs();
78 /* joyGetNumDevs does NOT return the number of joysticks connected, only slots in the OS */
79 for (i
= 0; i
< devices
; i
++)
81 memset(&jc
, 0, sizeof(jc
));
82 ret
= joyGetDevCapsA(JOYSTICKID1
+ i
, &jc
, sizeof(jc
));
83 if (ret
== JOYERR_NOERROR
)
85 if (joyid
== -1) /* Cache the first found joystick to run advanced tests below */
86 joyid
= JOYSTICKID1
+ i
;
88 trace("Joystick[%d] - name: '%s', axes: %d, buttons: %d, period range: %d - %d\n",
89 JOYSTICKID1
+ i
, jc
.szPname
, jc
.wNumAxes
, jc
.wNumButtons
, jc
.wPeriodMin
, jc
.wPeriodMax
);
90 ret
= joyGetDevCapsW(JOYSTICKID1
+ i
, &jcw
, sizeof(jcw
));
91 if (ret
!= MMSYSERR_NOTSUPPORTED
) /* Win 98 */
93 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
94 ok(jc
.wNumAxes
== jcw
.wNumAxes
, "Expected %d == %d\n", jc
.wNumAxes
, jcw
.wNumAxes
);
95 ok(jc
.wNumButtons
== jcw
.wNumButtons
, "Expected %d == %d\n", jc
.wNumButtons
, jcw
.wNumButtons
);
101 ok(ret
== JOYERR_PARMS
, "Expected %d, got %d\n", JOYERR_PARMS
, ret
);
102 ret
= joyGetDevCapsW(JOYSTICKID1
+ i
, &jcw
, sizeof(jcw
));
103 ok(ret
== JOYERR_PARMS
|| (ret
== MMSYSERR_NOTSUPPORTED
) /* Win 98 */,
104 "Expected %d, got %d\n", JOYERR_PARMS
, ret
);
107 /* Test invalid joystick - If no joystick is present the driver is not initialized,
108 * so a NODRIVER error is returned, if at least one joystick is present the error is
109 * about invalid parameters. */
110 ret
= joyGetDevCapsA(joyid
+ devices
, &jc
, sizeof(jc
));
111 ok(ret
== MMSYSERR_NODRIVER
|| ret
== JOYERR_PARMS
,
112 "Expected %d or %d, got %d\n", MMSYSERR_NODRIVER
, JOYERR_PARMS
, ret
);
116 skip("This test requires a real joystick.\n");
121 ret
= joySetCapture(NULL
, joyid
, 100, FALSE
);
122 ok(ret
== JOYERR_PARMS
|| broken(win98
&& ret
== MMSYSERR_INVALPARAM
) /* Win 98 */,
123 "Expected %d, got %d\n", JOYERR_PARMS
, ret
);
124 ret
= joySetCapture(window
, joyid
, 100, FALSE
);
125 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
126 ret
= joySetCapture(window
, joyid
, 100, FALSE
); /* double capture */
127 if (ret
== JOYERR_NOCANDO
)
130 ok(broken(1), "Expected double capture using joySetCapture to work\n");
131 if (!win98
&& broken(1)) win8
++; /* Windows 98 or 8 cannot cope with that */
133 else ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
134 ret
= joyReleaseCapture(joyid
);
135 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
136 ret
= joyReleaseCapture(joyid
);
137 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
); /* double release */
139 /* Try some unusual period values for joySetCapture and unusual threshold values for joySetThreshold.
140 * Windows XP allows almost all test values, Windows 8 will return error on most test values, Windows
141 * 98 allows anything but cuts the values to their maximum supported values internally. */
142 for (i
= 0; i
< ARRAY_SIZE(period
); i
++)
144 ret
= joySetCapture(window
, joyid
, period
[i
], FALSE
);
145 if (win8
&& ((1 << i
) & period_win8_error
))
146 ok(ret
== JOYERR_NOCANDO
, "Test [%d]: Expected %d, got %d\n", i
, JOYERR_NOCANDO
, ret
);
148 ok(ret
== JOYERR_NOERROR
, "Test [%d]: Expected %d, got %d\n", i
, JOYERR_NOERROR
, ret
);
149 ret
= joyReleaseCapture(joyid
);
150 ok(ret
== JOYERR_NOERROR
, "Test [%d]: Expected %d, got %d\n", i
, JOYERR_NOERROR
, ret
);
151 /* Reuse the periods to test the threshold */
152 ret
= joySetThreshold(joyid
, period
[i
]);
153 if (!win98
&& (1 << i
) & threshold_error
)
154 ok(ret
== MMSYSERR_INVALPARAM
, "Test [%d]: Expected %d, got %d\n", i
, MMSYSERR_INVALPARAM
, ret
);
156 ok(ret
== JOYERR_NOERROR
, "Test [%d]: Expected %d, got %d\n", i
, JOYERR_NOERROR
, ret
);
158 ret
= joyGetThreshold(joyid
, &par
);
159 ok(ret
== JOYERR_NOERROR
, "Test [%d]: Expected %d, got %d\n", i
, JOYERR_NOERROR
, ret
);
162 if ((1 << i
) & threshold_error
)
163 ok(par
== period
[8], "Test [%d]: Expected %d, got %d\n", i
, period
[8], par
);
165 ok(par
== period
[i
], "Test [%d]: Expected %d, got %d\n", i
, period
[i
], par
);
170 ret
= joyGetPos(joyid
, NULL
);
171 ok(ret
== MMSYSERR_INVALPARAM
, "Expected %d, got %d\n", MMSYSERR_INVALPARAM
, ret
);
172 ret
= joyGetPos(joyid
, &info
);
173 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
174 ret
= joyGetPosEx(joyid
, NULL
);
175 ok(ret
== MMSYSERR_INVALPARAM
|| broken(win8
&& ret
== JOYERR_PARMS
) /* Win 8 */,
176 "Expected %d, got %d\n", MMSYSERR_INVALPARAM
, ret
);
177 memset(&infoex
, 0, sizeof(infoex
));
178 ret
= joyGetPosEx(joyid
, &infoex
.ex
);
179 ok(ret
== JOYERR_PARMS
|| broken(win98
&& ret
== MMSYSERR_INVALPARAM
),
180 "Expected %d, got %d\n", JOYERR_PARMS
, ret
);
181 infoex
.ex
.dwSize
= sizeof(infoex
.ex
);
182 ret
= joyGetPosEx(joyid
, &infoex
.ex
);
183 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
184 infoex
.ex
.dwSize
= sizeof(infoex
.ex
) - 1;
185 ret
= joyGetPosEx(joyid
, &infoex
.ex
);
186 ok(ret
== JOYERR_PARMS
|| broken(win98
&& ret
== MMSYSERR_INVALPARAM
),
187 "Expected %d, got %d\n", JOYERR_PARMS
, ret
);
188 infoex
.ex
.dwSize
= sizeof(infoex
);
189 ret
= joyGetPosEx(joyid
, &infoex
.ex
);
190 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
192 infoex
.ex
.dwSize
= sizeof(infoex
.ex
);
193 for (i
= 0; i
< ARRAY_SIZE(flags
); i
++)
195 infoex
.ex
.dwFlags
= flags
[i
];
196 ret
= joyGetPosEx(joyid
, &infoex
.ex
);
197 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
200 /* the interactive tests spans for 15 seconds, a 500ms polling is used to get
201 * changes in the joystick. */
202 if (winetest_interactive
)
204 #define MAX_TIME 15000
205 DWORD tick
= timeGetTime(), spent
;
206 infoex
.ex
.dwSize
= sizeof(infoex
.ex
);
207 infoex
.ex
.dwFlags
= JOY_RETURNALL
;
210 spent
= timeGetTime() - tick
;
211 ret
= joyGetPosEx(joyid
, &infoex
.ex
);
212 if (ret
== JOYERR_NOERROR
)
214 trace("X: %5d, Y: %5d, Z: %5d, POV: %5d\n",
215 infoex
.ex
.dwXpos
, infoex
.ex
.dwYpos
, infoex
.ex
.dwZpos
, infoex
.ex
.dwPOV
);
216 trace("R: %5d, U: %5d, V: %5d\n",
217 infoex
.ex
.dwRpos
, infoex
.ex
.dwUpos
, infoex
.ex
.dwVpos
);
218 trace("BUTTONS: 0x%04X, BUTTON_COUNT: %2d, REMAINING: %d ms\n\n",
219 infoex
.ex
.dwButtons
, infoex
.ex
.dwButtonNumber
, MAX_TIME
- spent
);
223 while (spent
< MAX_TIME
);
227 skip("Skipping interactive tests for the joystick\n");