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 joyid
= JOYSTICKID1
+ i
;
86 trace("Joystick[%d] - name: '%s', axes: %d, buttons: %d, period range: %d - %d\n",
87 JOYSTICKID1
+ i
, jc
.szPname
, jc
.wNumAxes
, jc
.wNumButtons
, jc
.wPeriodMin
, jc
.wPeriodMax
);
88 ret
= joyGetDevCapsW(JOYSTICKID1
+ i
, &jcw
, sizeof(jcw
));
89 if (ret
!= MMSYSERR_NOTSUPPORTED
) /* Win 98 */
91 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
92 ok(jc
.wNumAxes
== jcw
.wNumAxes
, "Expected %d == %d\n", jc
.wNumAxes
, jcw
.wNumAxes
);
93 ok(jc
.wNumButtons
== jcw
.wNumButtons
, "Expected %d == %d\n", jc
.wNumButtons
, jcw
.wNumButtons
);
100 ok(ret
== JOYERR_PARMS
, "Expected %d, got %d\n", JOYERR_PARMS
, ret
);
101 ret
= joyGetDevCapsW(JOYSTICKID1
+ i
, &jcw
, sizeof(jcw
));
102 ok(ret
== JOYERR_PARMS
|| (ret
== MMSYSERR_NOTSUPPORTED
) /* Win 98 */,
103 "Expected %d, got %d\n", JOYERR_PARMS
, ret
);
106 /* Test invalid joystick - If no joystick is present the driver is not initialized,
107 * so a NODRIVER error is returned, if at least one joystick is present the error is
108 * about invalid parameters. */
109 ret
= joyGetDevCapsA(joyid
+ devices
, &jc
, sizeof(jc
));
110 ok(ret
== MMSYSERR_NODRIVER
|| ret
== JOYERR_PARMS
,
111 "Expected %d or %d, got %d\n", MMSYSERR_NODRIVER
, JOYERR_PARMS
, ret
);
115 skip("This test requires a real joystick.\n");
120 ret
= joySetCapture(NULL
, joyid
, 100, FALSE
);
121 ok(ret
== JOYERR_PARMS
|| broken(win98
&& ret
== MMSYSERR_INVALPARAM
) /* Win 98 */,
122 "Expected %d, got %d\n", JOYERR_PARMS
, ret
);
123 ret
= joySetCapture(window
, joyid
, 100, FALSE
);
124 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
125 ret
= joySetCapture(window
, joyid
, 100, FALSE
); /* double capture */
126 if (ret
== JOYERR_NOCANDO
)
129 ok(broken(1), "Expected double capture using joySetCapture to work\n");
130 if (!win98
&& broken(1)) win8
++; /* Windows 98 or 8 cannot cope with that */
132 else ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
133 ret
= joyReleaseCapture(joyid
);
134 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
135 ret
= joyReleaseCapture(joyid
);
136 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
); /* double release */
138 /* Try some unusual period values for joySetCapture and unusual threshold values for joySetThreshold.
139 * Windows XP allows almost all test values, Windows 8 will return error on most test values, Windows
140 * 98 allows anything but cuts the values to their maximum supported values internally. */
141 for (i
= 0; i
< sizeof(period
) / sizeof(period
[0]); i
++)
143 ret
= joySetCapture(window
, joyid
, period
[i
], FALSE
);
144 if (win8
&& ((1 << i
) & period_win8_error
))
145 ok(ret
== JOYERR_NOCANDO
, "Test [%d]: Expected %d, got %d\n", i
, JOYERR_NOCANDO
, ret
);
147 ok(ret
== JOYERR_NOERROR
, "Test [%d]: Expected %d, got %d\n", i
, JOYERR_NOERROR
, ret
);
148 ret
= joyReleaseCapture(joyid
);
149 ok(ret
== JOYERR_NOERROR
, "Test [%d]: Expected %d, got %d\n", i
, JOYERR_NOERROR
, ret
);
150 /* Reuse the periods to test the threshold */
151 ret
= joySetThreshold(joyid
, period
[i
]);
152 if (!win98
&& (1 << i
) & threshold_error
)
153 ok(ret
== MMSYSERR_INVALPARAM
, "Test [%d]: Expected %d, got %d\n", i
, MMSYSERR_INVALPARAM
, ret
);
155 ok(ret
== JOYERR_NOERROR
, "Test [%d]: Expected %d, got %d\n", i
, JOYERR_NOERROR
, ret
);
157 ret
= joyGetThreshold(joyid
, &par
);
158 ok(ret
== JOYERR_NOERROR
, "Test [%d]: Expected %d, got %d\n", i
, JOYERR_NOERROR
, ret
);
161 if ((1 << i
) & threshold_error
)
162 ok(par
== period
[8], "Test [%d]: Expected %d, got %d\n", i
, period
[8], par
);
164 ok(par
== period
[i
], "Test [%d]: Expected %d, got %d\n", i
, period
[i
], par
);
169 ret
= joyGetPos(joyid
, NULL
);
170 ok(ret
== MMSYSERR_INVALPARAM
, "Expected %d, got %d\n", MMSYSERR_INVALPARAM
, ret
);
171 ret
= joyGetPos(joyid
, &info
);
172 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
173 ret
= joyGetPosEx(joyid
, NULL
);
174 ok(ret
== MMSYSERR_INVALPARAM
|| broken(win8
&& ret
== JOYERR_PARMS
) /* Win 8 */,
175 "Expected %d, got %d\n", MMSYSERR_INVALPARAM
, ret
);
176 memset(&infoex
, 0, sizeof(infoex
));
177 ret
= joyGetPosEx(joyid
, &infoex
.ex
);
178 ok(ret
== JOYERR_PARMS
|| broken(win98
&& ret
== MMSYSERR_INVALPARAM
),
179 "Expected %d, got %d\n", JOYERR_PARMS
, ret
);
180 infoex
.ex
.dwSize
= sizeof(infoex
.ex
);
181 ret
= joyGetPosEx(joyid
, &infoex
.ex
);
182 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
183 infoex
.ex
.dwSize
= sizeof(infoex
.ex
) - 1;
184 ret
= joyGetPosEx(joyid
, &infoex
.ex
);
185 ok(ret
== JOYERR_PARMS
|| broken(win98
&& ret
== MMSYSERR_INVALPARAM
),
186 "Expected %d, got %d\n", JOYERR_PARMS
, ret
);
187 infoex
.ex
.dwSize
= sizeof(infoex
);
188 ret
= joyGetPosEx(joyid
, &infoex
.ex
);
189 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
191 infoex
.ex
.dwSize
= sizeof(infoex
.ex
);
192 for (i
= 0; i
< sizeof(flags
) / sizeof(flags
[0]); i
++)
194 infoex
.ex
.dwFlags
= flags
[i
];
195 ret
= joyGetPosEx(joyid
, &infoex
.ex
);
196 ok(ret
== JOYERR_NOERROR
, "Expected %d, got %d\n", JOYERR_NOERROR
, ret
);
199 /* the interactive tests spans for 15 seconds, a 500ms polling is used to get
200 * changes in the joystick. */
201 if (winetest_interactive
)
203 #define MAX_TIME 15000
204 DWORD tick
= GetTickCount(), spent
;
205 infoex
.ex
.dwSize
= sizeof(infoex
.ex
);
206 infoex
.ex
.dwFlags
= JOY_RETURNALL
;
209 spent
= GetTickCount() - tick
;
210 ret
= joyGetPosEx(joyid
, &infoex
.ex
);
211 if (ret
== JOYERR_NOERROR
)
213 trace("X: %5d, Y: %5d, Z: %5d, POV: %5d\n",
214 infoex
.ex
.dwXpos
, infoex
.ex
.dwYpos
, infoex
.ex
.dwZpos
, infoex
.ex
.dwPOV
);
215 trace("R: %5d, U: %5d, V: %5d\n",
216 infoex
.ex
.dwRpos
, infoex
.ex
.dwUpos
, infoex
.ex
.dwVpos
);
217 trace("BUTTONS: 0x%04X, BUTTON_COUNT: %2d, REMAINING: %d ms\n\n",
218 infoex
.ex
.dwButtons
, infoex
.ex
.dwButtonNumber
, MAX_TIME
- spent
);
222 while (spent
< MAX_TIME
);
226 skip("Skipping interactive tests for the joystick\n");