2 * Unit tests for monitor APIs
4 * Copyright 2005 Huw Davies
5 * Copyright 2008 Dmitry Timoshkov
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 "wine/test.h"
28 static LONG (WINAPI
*pChangeDisplaySettingsExA
)(LPCSTR
, LPDEVMODEA
, HWND
, DWORD
, LPVOID
);
29 static LONG (WINAPI
*pChangeDisplaySettingsExW
)(LPCWSTR
, LPDEVMODEW
, HWND
, DWORD
, LPVOID
);
30 static BOOL (WINAPI
*pEnumDisplayDevicesA
)(LPCSTR
,DWORD
,LPDISPLAY_DEVICEA
,DWORD
);
31 static BOOL (WINAPI
*pEnumDisplayMonitors
)(HDC
,LPRECT
,MONITORENUMPROC
,LPARAM
);
32 static BOOL (WINAPI
*pGetMonitorInfoA
)(HMONITOR
,LPMONITORINFO
);
33 static BOOL (WINAPI
*pGetMonitorInfoW
)(HMONITOR
,LPMONITORINFO
);
34 static HMONITOR (WINAPI
*pMonitorFromPoint
)(POINT
,DWORD
);
35 static HMONITOR (WINAPI
*pMonitorFromRect
)(LPCRECT
,DWORD
);
36 static HMONITOR (WINAPI
*pMonitorFromWindow
)(HWND
,DWORD
);
37 static LONG (WINAPI
*pGetDisplayConfigBufferSizes
)(UINT32
,UINT32
*,UINT32
*);
39 static void init_function_pointers(void)
41 hdll
= GetModuleHandleA("user32.dll");
43 #define GET_PROC(func) \
44 p ## func = (void*)GetProcAddress(hdll, #func); \
46 trace("GetProcAddress(%s) failed\n", #func);
48 GET_PROC(ChangeDisplaySettingsExA
)
49 GET_PROC(ChangeDisplaySettingsExW
)
50 GET_PROC(EnumDisplayDevicesA
)
51 GET_PROC(EnumDisplayMonitors
)
52 GET_PROC(GetDisplayConfigBufferSizes
)
53 GET_PROC(GetMonitorInfoA
)
54 GET_PROC(GetMonitorInfoW
)
55 GET_PROC(MonitorFromPoint
)
56 GET_PROC(MonitorFromRect
)
57 GET_PROC(MonitorFromWindow
)
62 static BOOL CALLBACK
monitor_enum_proc(HMONITOR hmon
, HDC hdc
, LPRECT lprc
,
66 char *primary
= (char *)lparam
;
68 mi
.cbSize
= sizeof(mi
);
70 ok(pGetMonitorInfoA(hmon
, (MONITORINFO
*)&mi
), "GetMonitorInfo failed\n");
71 if (mi
.dwFlags
& MONITORINFOF_PRIMARY
)
72 strcpy(primary
, mi
.szDevice
);
77 static void test_enumdisplaydevices(void)
80 char primary_device_name
[32];
81 char primary_monitor_device_name
[32];
82 DWORD primary_num
= -1, num
= 0;
85 if (!pEnumDisplayDevicesA
)
87 win_skip("EnumDisplayDevicesA is not available\n");
95 ret
= pEnumDisplayDevicesA(NULL
, num
, &dd
, 0);
98 if(dd
.StateFlags
& DISPLAY_DEVICE_PRIMARY_DEVICE
)
100 strcpy(primary_device_name
, dd
.DeviceName
);
103 if(dd
.StateFlags
& DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
)
105 /* test creating DC */
106 dc
= CreateDCA(dd
.DeviceName
, NULL
, NULL
, NULL
);
107 ok(dc
!= NULL
, "Failed to CreateDC(\"%s\") err=%d\n", dd
.DeviceName
, GetLastError());
112 if (primary_num
== -1 || !pEnumDisplayMonitors
|| !pGetMonitorInfoA
)
114 win_skip("EnumDisplayMonitors or GetMonitorInfoA are not available\n");
118 primary_monitor_device_name
[0] = 0;
119 ret
= pEnumDisplayMonitors(NULL
, NULL
, monitor_enum_proc
, (LPARAM
)primary_monitor_device_name
);
120 ok(ret
, "EnumDisplayMonitors failed\n");
121 ok(!strcmp(primary_monitor_device_name
, primary_device_name
),
122 "monitor device name %s, device name %s\n", primary_monitor_device_name
,
123 primary_device_name
);
126 for (num
= 0;; num
++)
128 ret
= pEnumDisplayDevicesA(primary_device_name
, num
, &dd
, 0);
132 ok(!strcasecmp(dd
.DeviceID
, "Monitor\\Default_Monitor\\{4D36E96E-E325-11CE-BFC1-08002BE10318}\\"),
133 "DeviceID \"%s\" does not start with \"Monitor\\Default_Monitor\\...\" prefix\n", dd
.DeviceID
);
139 DWORD w
, h
, bpp
, freq
, fields
;
143 static const struct vid_mode vid_modes_test
[] = {
144 {640, 480, 0, 0, DM_PELSWIDTH
| DM_PELSHEIGHT
| DM_BITSPERPEL
| DM_DISPLAYFREQUENCY
, 0},
145 {640, 480, 0, 0, DM_PELSWIDTH
| DM_PELSHEIGHT
| DM_DISPLAYFREQUENCY
, 1},
146 {640, 480, 0, 0, DM_PELSWIDTH
| DM_PELSHEIGHT
| DM_BITSPERPEL
, 0},
147 {640, 480, 0, 0, DM_PELSWIDTH
| DM_PELSHEIGHT
, 1},
148 {640, 480, 0, 0, DM_BITSPERPEL
, 0},
149 {640, 480, 0, 0, DM_DISPLAYFREQUENCY
, 0},
151 {0, 0, 0, 0, DM_PELSWIDTH
, 0},
152 {0, 0, 0, 0, DM_PELSHEIGHT
, 0},
154 {640, 480, 0, 0, DM_PELSWIDTH
, 0},
155 {640, 480, 0, 0, DM_PELSHEIGHT
, 0},
156 { 0, 480, 0, 0, DM_PELSWIDTH
| DM_PELSHEIGHT
, 0},
157 {640, 0, 0, 0, DM_PELSWIDTH
| DM_PELSHEIGHT
, 0},
159 /* the following test succeeds under XP SP3
160 {0, 0, 0, 0, DM_DISPLAYFREQUENCY, 0}
163 #define vid_modes_cnt (sizeof(vid_modes_test) / sizeof(vid_modes_test[0]))
165 static void test_ChangeDisplaySettingsEx(void)
173 if (!pChangeDisplaySettingsExA
)
175 win_skip("ChangeDisplaySettingsExA is not available\n");
179 SetLastError(0xdeadbeef);
180 res
= EnumDisplaySettingsA(NULL
, ENUM_CURRENT_SETTINGS
, &dm
);
181 ok(res
, "EnumDisplaySettings error %u\n", GetLastError());
183 width
= dm
.dmPelsWidth
;
185 dm
.dmDriverExtra
= 1;
186 res
= ChangeDisplaySettingsA(&dm
, CDS_TEST
);
187 ok(res
== DISP_CHANGE_SUCCESSFUL
,
188 "ChangeDisplaySettingsA returned %d, expected DISP_CHANGE_SUCCESSFUL\n", res
);
189 ok(dm
.dmDriverExtra
== 0 || broken(dm
.dmDriverExtra
== 1) /* win9x */,
190 "ChangeDisplaySettingsA didn't reset dmDriverExtra to 0\n");
192 /* crashes under XP SP3 for large dmDriverExtra values */
193 dm
.dmDriverExtra
= 1;
194 res
= pChangeDisplaySettingsExA(NULL
, &dm
, NULL
, CDS_TEST
, NULL
);
195 ok(res
== DISP_CHANGE_SUCCESSFUL
,
196 "ChangeDisplaySettingsExW returned %d, expected DISP_CHANGE_SUCCESSFUL\n", res
);
197 ok(dm
.dmDriverExtra
== 1, "ChangeDisplaySettingsExA shouldn't reset dmDriverExtra to 0\n");
199 memset(&dmW
, 0, sizeof(dmW
));
200 dmW
.dmSize
= sizeof(dmW
);
201 dmW
.dmFields
= DM_PELSWIDTH
| DM_PELSHEIGHT
;
202 dmW
.dmPelsWidth
= dm
.dmPelsWidth
;
203 dmW
.dmPelsHeight
= dm
.dmPelsHeight
;
204 dmW
.dmDriverExtra
= 1;
205 SetLastError(0xdeadbeef);
206 res
= ChangeDisplaySettingsW(&dmW
, CDS_TEST
);
207 if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED
)
209 ok(res
== DISP_CHANGE_SUCCESSFUL
,
210 "ChangeDisplaySettingsW returned %d, expected DISP_CHANGE_SUCCESSFUL\n", res
);
211 ok(dmW
.dmDriverExtra
== 0, "ChangeDisplaySettingsW didn't reset dmDriverExtra to 0\n");
214 /* Apparently XP treats dmDriverExtra being != 0 as an error */
215 dmW
.dmDriverExtra
= 1;
216 res
= pChangeDisplaySettingsExW(NULL
, &dmW
, NULL
, CDS_TEST
, NULL
);
217 if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED
)
219 ok(res
== DISP_CHANGE_SUCCESSFUL
,
220 "ChangeDisplaySettingsExW returned %d, expected DISP_CHANGE_SUCCESSFUL\n", res
);
221 ok(dmW
.dmDriverExtra
== 1, "ChangeDisplaySettingsExW shouldn't reset dmDriverExtra to 0\n");
224 /* the following 2 tests show that dm.dmSize being 0 is invalid, but
225 * ChangeDisplaySettingsExA still reports success.
227 memset(&dm
, 0, sizeof(dm
));
228 dm
.dmFields
= DM_PELSWIDTH
| DM_PELSHEIGHT
;
229 dm
.dmPelsWidth
= width
;
230 res
= pChangeDisplaySettingsExA(NULL
, &dm
, NULL
, CDS_TEST
, NULL
);
231 ok(res
== DISP_CHANGE_SUCCESSFUL
||
232 res
== DISP_CHANGE_BADMODE
|| /* Win98, WinMe */
233 res
== DISP_CHANGE_FAILED
, /* NT4 */
234 "ChangeDisplaySettingsExA returned unexpected %d\n", res
);
236 memset(&dmW
, 0, sizeof(dmW
));
237 dmW
.dmFields
= DM_PELSWIDTH
| DM_PELSHEIGHT
;
238 dmW
.dmPelsWidth
= width
;
239 SetLastError(0xdeadbeef);
240 res
= pChangeDisplaySettingsExW(NULL
, &dmW
, NULL
, CDS_TEST
, NULL
);
241 if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED
)
242 ok(res
== DISP_CHANGE_FAILED
||
243 res
== DISP_CHANGE_BADPARAM
|| /* NT4 */
244 res
== DISP_CHANGE_BADMODE
/* XP SP3 */,
245 "ChangeDisplaySettingsExW returned %d\n", res
);
247 memset(&dm
, 0, sizeof(dm
));
248 dm
.dmSize
= sizeof(dm
);
250 for (i
= 0; i
< vid_modes_cnt
; i
++)
252 dm
.dmPelsWidth
= vid_modes_test
[i
].w
;
253 dm
.dmPelsHeight
= vid_modes_test
[i
].h
;
254 dm
.dmBitsPerPel
= vid_modes_test
[i
].bpp
;
255 dm
.dmDisplayFrequency
= vid_modes_test
[i
].freq
;
256 dm
.dmFields
= vid_modes_test
[i
].fields
;
257 res
= pChangeDisplaySettingsExA(NULL
, &dm
, NULL
, CDS_TEST
, NULL
);
258 ok(vid_modes_test
[i
].must_succeed
?
259 (res
== DISP_CHANGE_SUCCESSFUL
|| res
== DISP_CHANGE_RESTART
) :
260 (res
== DISP_CHANGE_SUCCESSFUL
|| res
== DISP_CHANGE_RESTART
||
261 res
== DISP_CHANGE_BADMODE
|| res
== DISP_CHANGE_BADPARAM
),
262 "Unexpected ChangeDisplaySettingsEx() return code for resolution[%d]: %d\n", i
, res
);
264 if (res
== DISP_CHANGE_SUCCESSFUL
)
268 SetRect(&virt
, 0, 0, GetSystemMetrics(SM_CXVIRTUALSCREEN
), GetSystemMetrics(SM_CYVIRTUALSCREEN
));
269 if (IsRectEmpty(&virt
)) /* NT4 doesn't have SM_CX/YVIRTUALSCREEN */
270 SetRect(&virt
, 0, 0, GetSystemMetrics(SM_CXSCREEN
), GetSystemMetrics(SM_CYSCREEN
));
271 OffsetRect(&virt
, GetSystemMetrics(SM_XVIRTUALSCREEN
), GetSystemMetrics(SM_YVIRTUALSCREEN
));
273 /* Resolution change resets clip rect */
274 ok(GetClipCursor(&r
), "GetClipCursor() failed\n");
275 ok(EqualRect(&r
, &virt
), "Invalid clip rect: %s\n", wine_dbgstr_rect(&r
));
277 if (!ClipCursor(NULL
)) continue;
278 ok(GetClipCursor(&r
), "GetClipCursor() failed\n");
279 ok(EqualRect(&r
, &virt
), "Invalid clip rect: %s\n", wine_dbgstr_rect(&r
));
281 /* This should always work. Primary monitor is at (0,0) */
282 SetRect(&r1
, 10, 10, 20, 20);
283 ok(ClipCursor(&r1
), "ClipCursor() failed\n");
284 ok(GetClipCursor(&r
), "GetClipCursor() failed\n");
285 ok(EqualRect(&r
, &r1
), "Invalid clip rect: %s\n", wine_dbgstr_rect(&r
));
286 SetRect(&r1
, 10, 10, 10, 10);
287 ok(ClipCursor(&r1
), "ClipCursor() failed\n");
288 ok(GetClipCursor(&r
), "GetClipCursor() failed\n");
289 ok(EqualRect(&r
, &r1
), "Invalid clip rect: %s\n", wine_dbgstr_rect(&r
));
290 SetRect(&r1
, 10, 10, 10, 9);
291 ok(!ClipCursor(&r1
), "ClipCursor() succeeded\n");
292 /* Windows bug: further clipping fails once an empty rect is set, so we have to reset it */
295 SetRect(&r1
, virt
.left
- 10, virt
.top
- 10, virt
.right
+ 20, virt
.bottom
+ 20);
296 ok(ClipCursor(&r1
), "ClipCursor() failed\n");
297 ok(GetClipCursor(&r
), "GetClipCursor() failed\n");
298 ok(EqualRect(&r
, &virt
) || broken(EqualRect(&r
, &r1
)) /* win9x */,
299 "Invalid clip rect: %s\n", wine_dbgstr_rect(&r
));
303 res
= pChangeDisplaySettingsExA(NULL
, NULL
, NULL
, CDS_RESET
, NULL
);
304 ok(res
== DISP_CHANGE_SUCCESSFUL
, "Failed to reset default resolution: %d\n", res
);
307 static void test_monitors(void)
309 HMONITOR monitor
, primary
, nearest
;
313 MONITORINFOEXA miexa
;
314 MONITORINFOEXW miexw
;
324 {sizeof(MONITORINFO
)+1, FALSE
},
325 {sizeof(MONITORINFO
)-1, FALSE
},
326 {sizeof(MONITORINFO
), TRUE
},
332 {sizeof(MONITORINFOEXA
)+1, FALSE
},
333 {sizeof(MONITORINFOEXA
)-1, FALSE
},
334 {sizeof(MONITORINFOEXA
), TRUE
},
340 {sizeof(MONITORINFOEXW
)+1, FALSE
},
341 {sizeof(MONITORINFOEXW
)-1, FALSE
},
342 {sizeof(MONITORINFOEXW
), TRUE
},
347 if (!pMonitorFromPoint
|| !pMonitorFromWindow
|| !pMonitorFromRect
)
349 win_skip("MonitorFromPoint, MonitorFromWindow, or MonitorFromRect is not available\n");
354 primary
= pMonitorFromPoint( pt
, MONITOR_DEFAULTTOPRIMARY
);
355 ok( primary
!= 0, "couldn't get primary monitor\n" );
357 monitor
= pMonitorFromWindow( 0, MONITOR_DEFAULTTONULL
);
358 ok( !monitor
, "got %p, should not get a monitor for an invalid window\n", monitor
);
359 monitor
= pMonitorFromWindow( 0, MONITOR_DEFAULTTOPRIMARY
);
360 ok( monitor
== primary
, "got %p, should get primary %p for MONITOR_DEFAULTTOPRIMARY\n", monitor
, primary
);
361 monitor
= pMonitorFromWindow( 0, MONITOR_DEFAULTTONEAREST
);
362 ok( monitor
== primary
, "got %p, should get primary %p for MONITOR_DEFAULTTONEAREST\n", monitor
, primary
);
364 SetRect( &rc
, 0, 0, 1, 1 );
365 monitor
= pMonitorFromRect( &rc
, MONITOR_DEFAULTTONULL
);
366 ok( monitor
== primary
, "got %p, should get primary %p\n", monitor
, primary
);
368 monitor
= pMonitorFromRect( &rc
, MONITOR_DEFAULTTOPRIMARY
);
369 ok( monitor
== primary
, "got %p, should get primary %p\n", monitor
, primary
);
371 monitor
= pMonitorFromRect( &rc
, MONITOR_DEFAULTTONEAREST
);
372 ok( monitor
== primary
, "got %p, should get primary %p\n", monitor
, primary
);
374 /* Empty rect at 0,0 is considered inside the primary monitor */
375 SetRect( &rc
, 0, 0, -1, -1 );
376 monitor
= pMonitorFromRect( &rc
, MONITOR_DEFAULTTONULL
);
377 ok( monitor
== primary
, "got %p, should get primary %p\n", monitor
, primary
);
379 /* Even if there is a monitor left of the primary, the primary will have the most overlapping area */
380 SetRect( &rc
, -1, 0, 2, 1 );
381 monitor
= pMonitorFromRect( &rc
, MONITOR_DEFAULTTONULL
);
382 ok( monitor
== primary
, "got %p, should get primary %p\n", monitor
, primary
);
384 /* But the width of the rect doesn't matter if it's empty. */
385 SetRect( &rc
, -1, 0, 2, -1 );
386 monitor
= pMonitorFromRect( &rc
, MONITOR_DEFAULTTONULL
);
387 ok( monitor
!= primary
, "got primary %p\n", monitor
);
389 if (!pGetMonitorInfoA
)
391 win_skip("GetMonitorInfoA is not available\n");
395 /* Search for a monitor that has no others equally near to (left, top-1) */
396 SetRect( &rc
, -1, -2, 2, 0 );
397 monitor
= pMonitorFromRect( &rc
, MONITOR_DEFAULTTONULL
);
399 while (monitor
!= NULL
)
401 ok( monitor
!= primary
, "got primary %p\n", monitor
);
403 mi
.cbSize
= sizeof(mi
);
404 ret
= pGetMonitorInfoA( monitor
, &mi
);
405 ok( ret
, "GetMonitorInfo failed\n" );
406 SetRect( &rc
, mi
.rcMonitor
.left
-1, mi
.rcMonitor
.top
-2, mi
.rcMonitor
.left
+2, mi
.rcMonitor
.top
);
407 monitor
= pMonitorFromRect( &rc
, MONITOR_DEFAULTTONULL
);
410 /* tests for cbSize in MONITORINFO */
411 monitor
= pMonitorFromWindow( 0, MONITOR_DEFAULTTOPRIMARY
);
412 for (i
= 0; i
< (sizeof(testdatami
) / sizeof(testdatami
[0])); i
++)
414 memset( &mi
, 0, sizeof(mi
) );
415 mi
.cbSize
= testdatami
[i
].cbSize
;
416 ret
= pGetMonitorInfoA( monitor
, &mi
);
417 ok( ret
== testdatami
[i
].ret
, "GetMonitorInfo returned wrong value\n" );
419 ok( (mi
.dwFlags
& MONITORINFOF_PRIMARY
), "MONITORINFOF_PRIMARY flag isn't set\n" );
421 ok( !(mi
.dwFlags
& MONITORINFOF_PRIMARY
), "MONITORINFOF_PRIMARY flag is set\n" );
423 memset( &miexw
, 0, sizeof(miexw
) );
424 miexw
.cbSize
= testdatamiexw
[i
].cbSize
;
425 ret
= pGetMonitorInfoW( monitor
, (LPMONITORINFO
)&miexw
);
426 ok( ret
== testdatamiexw
[i
].ret
, "GetMonitorInfo returned wrong value\n" );
428 ok( (miexw
.dwFlags
& MONITORINFOF_PRIMARY
), "MONITORINFOF_PRIMARY flag isn't set\n" );
430 ok( !(miexw
.dwFlags
& MONITORINFOF_PRIMARY
), "MONITORINFOF_PRIMARY flag is set\n" );
433 /* tests for cbSize in MONITORINFOEXA */
434 for (i
= 0; i
< (sizeof(testdatamiexa
) / sizeof(testdatamiexa
[0])); i
++)
436 memset( &miexa
, 0, sizeof(miexa
) );
437 miexa
.cbSize
= testdatamiexa
[i
].cbSize
;
438 ret
= pGetMonitorInfoA( monitor
, (LPMONITORINFO
)&miexa
);
439 ok( ret
== testdatamiexa
[i
].ret
, "GetMonitorInfo returned wrong value\n" );
441 ok( (miexa
.dwFlags
& MONITORINFOF_PRIMARY
), "MONITORINFOF_PRIMARY flag isn't set\n" );
443 ok( !(miexa
.dwFlags
& MONITORINFOF_PRIMARY
), "MONITORINFOF_PRIMARY flag is set\n" );
446 /* tests for cbSize in MONITORINFOEXW */
447 for (i
= 0; i
< (sizeof(testdatamiexw
) / sizeof(testdatamiexw
[0])); i
++)
449 memset( &miexw
, 0, sizeof(miexw
) );
450 miexw
.cbSize
= testdatamiexw
[i
].cbSize
;
451 ret
= pGetMonitorInfoW( monitor
, (LPMONITORINFO
)&miexw
);
452 ok( ret
== testdatamiexw
[i
].ret
, "GetMonitorInfo returned wrong value\n" );
454 ok( (miexw
.dwFlags
& MONITORINFOF_PRIMARY
), "MONITORINFOF_PRIMARY flag isn't set\n" );
456 ok( !(miexw
.dwFlags
& MONITORINFOF_PRIMARY
), "MONITORINFOF_PRIMARY flag is set\n" );
459 SetRect( &rc
, rc
.left
+1, rc
.top
+1, rc
.left
+2, rc
.top
+2 );
461 monitor
= pMonitorFromRect( &rc
, MONITOR_DEFAULTTONULL
);
462 ok( monitor
== NULL
, "got %p\n", monitor
);
464 monitor
= pMonitorFromRect( &rc
, MONITOR_DEFAULTTOPRIMARY
);
465 ok( monitor
== primary
, "got %p, should get primary %p\n", monitor
, primary
);
467 monitor
= pMonitorFromRect( &rc
, MONITOR_DEFAULTTONEAREST
);
468 ok( monitor
== nearest
, "got %p, should get nearest %p\n", monitor
, nearest
);
471 static BOOL CALLBACK
find_primary_mon(HMONITOR hmon
, HDC hdc
, LPRECT rc
, LPARAM lp
)
476 mi
.cbSize
= sizeof(mi
);
477 ret
= pGetMonitorInfoA(hmon
, &mi
);
478 ok(ret
, "GetMonitorInfo failed\n");
479 if (mi
.dwFlags
& MONITORINFOF_PRIMARY
)
481 *(HMONITOR
*)lp
= hmon
;
487 static void test_work_area(void)
491 RECT rc_work
, rc_normal
;
496 if (!pEnumDisplayMonitors
|| !pGetMonitorInfoA
)
498 win_skip("EnumDisplayMonitors or GetMonitorInfoA are not available\n");
503 ret
= pEnumDisplayMonitors(NULL
, NULL
, find_primary_mon
, (LPARAM
)&hmon
);
504 ok(!ret
&& hmon
!= 0, "Failed to find primary monitor\n");
506 mi
.cbSize
= sizeof(mi
);
507 SetLastError(0xdeadbeef);
508 ret
= pGetMonitorInfoA(hmon
, &mi
);
509 ok(ret
, "GetMonitorInfo error %u\n", GetLastError());
510 ok(mi
.dwFlags
& MONITORINFOF_PRIMARY
, "not a primary monitor\n");
511 trace("primary monitor %s\n", wine_dbgstr_rect(&mi
.rcMonitor
));
513 SetLastError(0xdeadbeef);
514 ret
= SystemParametersInfoA(SPI_GETWORKAREA
, 0, &rc_work
, 0);
515 ok(ret
, "SystemParametersInfo error %u\n", GetLastError());
516 trace("work area %s\n", wine_dbgstr_rect(&rc_work
));
517 ok(EqualRect(&rc_work
, &mi
.rcWork
), "work area is different\n");
519 hwnd
= CreateWindowExA(0, "static", NULL
, WS_OVERLAPPEDWINDOW
|WS_VISIBLE
,100,100,10,10,0,0,0,NULL
);
520 ok(hwnd
!= 0, "CreateWindowEx failed\n");
522 ret
= GetWindowRect(hwnd
, &rc_normal
);
523 ok(ret
, "GetWindowRect failed\n");
524 trace("normal %s\n", wine_dbgstr_rect(&rc_normal
));
526 wp
.length
= sizeof(wp
);
527 ret
= GetWindowPlacement(hwnd
, &wp
);
528 ok(ret
, "GetWindowPlacement failed\n");
529 trace("min: %d,%d max %d,%d normal %s\n", wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
,
530 wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
, wine_dbgstr_rect(&wp
.rcNormalPosition
));
531 OffsetRect(&wp
.rcNormalPosition
, rc_work
.left
, rc_work
.top
);
532 todo_wine_if (mi
.rcMonitor
.left
!= mi
.rcWork
.left
||
533 mi
.rcMonitor
.top
!= mi
.rcWork
.top
) /* FIXME: remove once Wine is fixed */
535 ok(EqualRect(&rc_normal
, &wp
.rcNormalPosition
), "normal pos is different\n");
538 SetWindowLongA(hwnd
, GWL_EXSTYLE
, WS_EX_TOOLWINDOW
);
540 wp
.length
= sizeof(wp
);
541 ret
= GetWindowPlacement(hwnd
, &wp
);
542 ok(ret
, "GetWindowPlacement failed\n");
543 trace("min: %d,%d max %d,%d normal %s\n", wp
.ptMinPosition
.x
, wp
.ptMinPosition
.y
,
544 wp
.ptMaxPosition
.x
, wp
.ptMaxPosition
.y
, wine_dbgstr_rect(&wp
.rcNormalPosition
));
545 ok(EqualRect(&rc_normal
, &wp
.rcNormalPosition
), "normal pos is different\n");
550 static void test_display_config(void)
555 if (!pGetDisplayConfigBufferSizes
)
557 win_skip("GetDisplayConfigBufferSizes is not supported\n");
561 ret
= pGetDisplayConfigBufferSizes(QDC_ALL_PATHS
, NULL
, NULL
);
562 ok(ret
== ERROR_INVALID_PARAMETER
, "got %d\n", ret
);
565 ret
= pGetDisplayConfigBufferSizes(QDC_ALL_PATHS
, &paths
, NULL
);
566 ok(ret
== ERROR_INVALID_PARAMETER
, "got %d\n", ret
);
567 ok(paths
== 100, "got %u\n", paths
);
570 ret
= pGetDisplayConfigBufferSizes(QDC_ALL_PATHS
, NULL
, &modes
);
571 ok(ret
== ERROR_INVALID_PARAMETER
, "got %d\n", ret
);
572 ok(modes
== 100, "got %u\n", modes
);
575 ret
= pGetDisplayConfigBufferSizes(QDC_ALL_PATHS
, &paths
, &modes
);
577 ok(paths
> 0 && modes
> 0, "got %u, %u\n", paths
, modes
);
579 ok(ret
== ERROR_NOT_SUPPORTED
, "got %d\n", ret
);
581 /* Invalid flags, non-zero invalid flags validation is version (or driver?) dependent,
582 it's unreliable to use in tests. */
583 ret
= pGetDisplayConfigBufferSizes(0, NULL
, NULL
);
584 ok(ret
== ERROR_INVALID_PARAMETER
, "got %d\n", ret
);
587 ret
= pGetDisplayConfigBufferSizes(0, &paths
, NULL
);
588 ok(ret
== ERROR_INVALID_PARAMETER
, "got %d\n", ret
);
589 ok(paths
== 100, "got %u\n", paths
);
592 ret
= pGetDisplayConfigBufferSizes(0, NULL
, &modes
);
593 ok(ret
== ERROR_INVALID_PARAMETER
, "got %d\n", ret
);
594 ok(modes
== 100, "got %u\n", modes
);
597 ret
= pGetDisplayConfigBufferSizes(0, &paths
, &modes
);
598 ok(ret
== ERROR_INVALID_PARAMETER
|| ret
== ERROR_NOT_SUPPORTED
, "got %d\n", ret
);
599 ok(modes
== 0 && paths
== 0, "got %u, %u\n", modes
, paths
);
604 init_function_pointers();
605 test_enumdisplaydevices();
606 test_ChangeDisplaySettingsEx();
609 test_display_config();