Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
00970356
Commit
00970356
authored
Feb 04, 2020
by
Zhiyi Zhang
Committed by
Alexandre Julliard
Feb 04, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
user32/tests: Add more ChangeDisplaySettings tests.
Signed-off-by:
Zhiyi Zhang
<
zzhang@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
4a3cd01b
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
528 additions
and
53 deletions
+528
-53
monitor.c
dlls/user32/tests/monitor.c
+528
-53
No files found.
dlls/user32/tests/monitor.c
View file @
00970356
...
...
@@ -24,6 +24,7 @@
#include "wingdi.h"
#include "winuser.h"
#include "winreg.h"
#include "wine/heap.h"
#include <stdio.h>
static
HMODULE
hdll
;
...
...
@@ -252,82 +253,167 @@ static const struct vid_mode vid_modes_test[] = {
*/
};
struct
device_info
{
DWORD
index
;
CHAR
name
[
CCHDEVICENAME
];
DEVMODEA
original_mode
;
};
static
BOOL
get_primary_adapter
(
CHAR
*
name
)
{
DISPLAY_DEVICEA
dd
;
DWORD
i
;
dd
.
cb
=
sizeof
(
dd
);
for
(
i
=
0
;
EnumDisplayDevicesA
(
NULL
,
i
,
&
dd
,
0
);
++
i
)
{
if
(
dd
.
StateFlags
&
DISPLAY_DEVICE_PRIMARY_DEVICE
)
{
lstrcpyA
(
name
,
dd
.
DeviceName
);
return
TRUE
;
}
}
return
FALSE
;
}
#define expect_dm(a, b, c) _expect_dm(__LINE__, a, b, c)
static
void
_expect_dm
(
INT
line
,
DEVMODEA
expected
,
const
CHAR
*
device
,
DWORD
test
)
{
CHAR
primary_adapter
[
CCHDEVICENAME
];
BOOL
is_primary
;
DEVMODEA
dm
;
BOOL
ret
;
memset
(
&
dm
,
0
,
sizeof
(
dm
));
dm
.
dmSize
=
sizeof
(
dm
);
SetLastError
(
0xdeadbeef
);
ret
=
EnumDisplaySettingsA
(
device
,
ENUM_CURRENT_SETTINGS
,
&
dm
);
/* On win10 TestBot, after many resolution changes, EnumDisplaySettingsA fails sometimes for unknown reasons */
if
(
!
ret
)
{
win_skip_
(
__FILE__
,
line
)(
"EnumDisplaySettingsA failed.
\n
"
);
return
;
}
ok_
(
__FILE__
,
line
)(
ret
,
"Device %s test %d EnumDisplaySettingsA failed, error %#x
\n
"
,
device
,
test
,
GetLastError
());
ok
(
get_primary_adapter
(
primary_adapter
),
"Failed to get primary adapter name.
\n
"
);
is_primary
=
!
lstrcmpA
(
primary_adapter
,
device
);
todo_wine_if
(
expected
.
dmFields
&
DM_POSITION
)
ok_
(
__FILE__
,
line
)((
dm
.
dmFields
&
expected
.
dmFields
)
==
expected
.
dmFields
,
"Device %s test %d expect dmFields to contain %#x, got %#x
\n
"
,
device
,
test
,
expected
.
dmFields
,
dm
.
dmFields
);
/* Wine doesn't support changing color depth yet */
todo_wine_if
(
expected
.
dmBitsPerPel
!=
32
&&
expected
.
dmBitsPerPel
!=
24
)
ok_
(
__FILE__
,
line
)(
dm
.
dmBitsPerPel
==
expected
.
dmBitsPerPel
,
"Device %s test %d expect dmBitsPerPel %d, got %d
\n
"
,
device
,
test
,
expected
.
dmBitsPerPel
,
dm
.
dmBitsPerPel
);
/* Wine currently reports primary monitor settings for non-primary monitors */
todo_wine_if
(
!
is_primary
&&
dm
.
dmPelsWidth
!=
expected
.
dmPelsWidth
)
ok_
(
__FILE__
,
line
)(
dm
.
dmPelsWidth
==
expected
.
dmPelsWidth
,
"Device %s test %d expect dmPelsWidth %d, got %d
\n
"
,
device
,
test
,
expected
.
dmPelsWidth
,
dm
.
dmPelsWidth
);
todo_wine_if
(
!
is_primary
&&
dm
.
dmPelsHeight
!=
expected
.
dmPelsHeight
)
ok_
(
__FILE__
,
line
)(
dm
.
dmPelsHeight
==
expected
.
dmPelsHeight
,
"Device %s test %d expect dmPelsHeight %d, got %d
\n
"
,
device
,
test
,
expected
.
dmPelsHeight
,
dm
.
dmPelsHeight
);
todo_wine_if
(
!
is_primary
&&
dm
.
dmPosition
.
x
!=
expected
.
dmPosition
.
x
)
ok_
(
__FILE__
,
line
)(
dm
.
dmPosition
.
x
==
expected
.
dmPosition
.
x
,
"Device %s test %d expect dmPosition.x %d, got %d
\n
"
,
device
,
test
,
expected
.
dmPosition
.
x
,
dm
.
dmPosition
.
x
);
todo_wine_if
(
!
is_primary
&&
dm
.
dmPosition
.
y
!=
expected
.
dmPosition
.
y
)
ok_
(
__FILE__
,
line
)(
dm
.
dmPosition
.
y
==
expected
.
dmPosition
.
y
,
"Device %s test %d expect dmPosition.y %d, got %d
\n
"
,
device
,
test
,
expected
.
dmPosition
.
y
,
dm
.
dmPosition
.
y
);
todo_wine_if
(
!
is_primary
&&
dm
.
dmDisplayFrequency
!=
expected
.
dmDisplayFrequency
)
ok_
(
__FILE__
,
line
)(
dm
.
dmDisplayFrequency
==
expected
.
dmDisplayFrequency
,
"Device %s test %d expect dmDisplayFrequency %d, got %d
\n
"
,
device
,
test
,
expected
.
dmDisplayFrequency
,
dm
.
dmDisplayFrequency
);
todo_wine_if
(
!
is_primary
&&
dm
.
dmDisplayOrientation
!=
expected
.
dmDisplayOrientation
)
ok_
(
__FILE__
,
line
)(
dm
.
dmDisplayOrientation
==
expected
.
dmDisplayOrientation
,
"Device %s test %d expect dmDisplayOrientation %d, got %d
\n
"
,
device
,
test
,
expected
.
dmDisplayOrientation
,
dm
.
dmDisplayOrientation
);
}
static
void
test_ChangeDisplaySettingsEx
(
void
)
{
DPI_AWARENESS_CONTEXT
context
=
NULL
;
DEVMODEA
dm
;
UINT
primary
,
device
,
side
,
mode
;
UINT
device_size
,
device_count
;
struct
device_info
*
devices
;
INT
count
,
old_count
;
DISPLAY_DEVICEA
dd
;
DEVMODEA
dm
,
dm2
;
POINTL
position
;
DEVMODEW
dmW
;
DWORD
width
;
LONG
res
;
int
i
;
SetLastError
(
0xdeadbeef
);
/* Test dmDriverExtra */
memset
(
&
dm
,
0
,
sizeof
(
dm
));
dm
.
dmSize
=
sizeof
(
dm
);
res
=
EnumDisplaySettingsA
(
NULL
,
ENUM_CURRENT_SETTINGS
,
&
dm
);
ok
(
res
,
"EnumDisplaySettings
error %u
\n
"
,
GetLastError
());
ok
(
res
,
"EnumDisplaySettings
A failed, error %#x
\n
"
,
GetLastError
());
width
=
dm
.
dmPelsWidth
;
memset
(
&
dmW
,
0
,
sizeof
(
dmW
));
dmW
.
dmSize
=
sizeof
(
dmW
);
res
=
EnumDisplaySettingsW
(
NULL
,
ENUM_CURRENT_SETTINGS
,
&
dmW
);
ok
(
res
,
"EnumDisplaySettingsW failed, error %#x
\n
"
,
GetLastError
());
/* ChangeDisplaySettingsA/W reset dmDriverExtra to 0 */
dm
.
dmDriverExtra
=
1
;
res
=
ChangeDisplaySettingsA
(
&
dm
,
CDS_TEST
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsA returned %d, expected DISP_CHANGE_SUCCESSFUL
\n
"
,
res
);
ok
(
dm
.
dmDriverExtra
==
0
||
broken
(
dm
.
dmDriverExtra
==
1
)
/* win9x */
,
"ChangeDisplaySettingsA didn't reset dmDriverExtra to 0
\n
"
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsA returned unexpected %d
\n
"
,
res
);
ok
(
dm
.
dmDriverExtra
==
0
,
"ChangeDisplaySettingsA didn't reset dmDriverExtra to 0
\n
"
);
/* crashes under XP SP3 for large dmDriverExtra values */
dm
.
dmDriverExtra
=
1
;
res
=
ChangeDisplaySettingsExA
(
NULL
,
&
dm
,
NULL
,
CDS_TEST
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExW returned %d, expected DISP_CHANGE_SUCCESSFUL
\n
"
,
res
);
ok
(
dm
.
dmDriverExtra
==
1
,
"ChangeDisplaySettingsExA shouldn't reset dmDriverExtra to 0
\n
"
);
memset
(
&
dmW
,
0
,
sizeof
(
dmW
));
dmW
.
dmSize
=
sizeof
(
dmW
);
dmW
.
dmFields
=
DM_PELSWIDTH
|
DM_PELSHEIGHT
;
dmW
.
dmPelsWidth
=
dm
.
dmPelsWidth
;
dmW
.
dmPelsHeight
=
dm
.
dmPelsHeight
;
dmW
.
dmDriverExtra
=
1
;
SetLastError
(
0xdeadbeef
);
res
=
ChangeDisplaySettingsW
(
&
dmW
,
CDS_TEST
);
if
(
GetLastError
()
!=
ERROR_CALL_NOT_IMPLEMENTED
)
{
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsW returned %d, expected DISP_CHANGE_SUCCESSFUL
\n
"
,
res
);
ok
(
dmW
.
dmDriverExtra
==
0
,
"ChangeDisplaySettingsW didn't reset dmDriverExtra to 0
\n
"
);
}
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsW returned unexpected %d
\n
"
,
res
);
ok
(
dmW
.
dmDriverExtra
==
0
,
"ChangeDisplaySettingsW didn't reset dmDriverExtra to 0
\n
"
);
/* ChangeDisplaySettingsExA/W do not modify dmDriverExtra */
dm
.
dmDriverExtra
=
1
;
res
=
ChangeDisplaySettingsExA
(
NULL
,
&
dm
,
NULL
,
CDS_TEST
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExA returned unexpected %d
\n
"
,
res
);
ok
(
dm
.
dmDriverExtra
==
1
,
"ChangeDisplaySettingsExA shouldn't change dmDriverExtra
\n
"
);
/* Apparently XP treats dmDriverExtra being != 0 as an error */
dmW
.
dmDriverExtra
=
1
;
res
=
ChangeDisplaySettingsExW
(
NULL
,
&
dmW
,
NULL
,
CDS_TEST
,
NULL
);
if
(
GetLastError
()
!=
ERROR_CALL_NOT_IMPLEMENTED
)
{
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExW returned %d, expected DISP_CHANGE_SUCCESSFUL
\n
"
,
res
);
ok
(
dmW
.
dmDriverExtra
==
1
,
"ChangeDisplaySettingsExW shouldn't reset dmDriverExtra to 0
\n
"
);
}
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExW returned unexpected %d
\n
"
,
res
);
ok
(
dmW
.
dmDriverExtra
==
1
,
"ChangeDisplaySettingsExW shouldn't change dmDriverExtra
\n
"
);
/* the following 2 tests show that dm.dmSize being 0 is invalid, but
* ChangeDisplaySettingsExA still reports success.
*/
/* Test dmSize */
/* ChangeDisplaySettingsA/ExA report success even if dmSize is 0 */
memset
(
&
dm
,
0
,
sizeof
(
dm
));
dm
.
dmFields
=
DM_PELSWIDTH
|
DM_PELSHEIGHT
;
dm
.
dmPelsWidth
=
width
;
dm
.
dmSize
=
sizeof
(
dm
);
res
=
EnumDisplaySettingsA
(
NULL
,
ENUM_CURRENT_SETTINGS
,
&
dm
);
ok
(
res
,
"EnumDisplaySettingsA failed, error %#x
\n
"
,
GetLastError
());
dm
.
dmSize
=
0
;
res
=
ChangeDisplaySettingsA
(
&
dm
,
CDS_TEST
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsA returned unexpected %d
\n
"
,
res
);
dm
.
dmSize
=
0
;
res
=
ChangeDisplaySettingsExA
(
NULL
,
&
dm
,
NULL
,
CDS_TEST
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
||
res
==
DISP_CHANGE_BADMODE
||
/* Win98, WinMe */
res
==
DISP_CHANGE_FAILED
,
/* NT4 */
"ChangeDisplaySettingsExA returned unexpected %d
\n
"
,
res
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExA returned unexpected %d
\n
"
,
res
);
/* dmSize for ChangeDisplaySettingsW/ExW needs to be at least FIELD_OFFSET(DEVMODEW, dmICMMethod) */
memset
(
&
dmW
,
0
,
sizeof
(
dmW
));
dmW
.
dmFields
=
DM_PELSWIDTH
|
DM_PELSHEIGHT
;
dmW
.
dmPelsWidth
=
width
;
SetLastError
(
0xdeadbeef
);
dmW
.
dmSize
=
sizeof
(
dmW
);
res
=
EnumDisplaySettingsW
(
NULL
,
ENUM_CURRENT_SETTINGS
,
&
dmW
);
ok
(
res
,
"EnumDisplaySettingsW failed, error %#x
\n
"
,
GetLastError
());
dmW
.
dmSize
=
FIELD_OFFSET
(
DEVMODEW
,
dmICMMethod
)
-
1
;
res
=
ChangeDisplaySettingsW
(
&
dmW
,
CDS_TEST
);
todo_wine
ok
(
res
==
DISP_CHANGE_BADMODE
,
"ChangeDisplaySettingsW returned %d, expect DISP_CHANGE_BADMODE
\n
"
,
res
);
dmW
.
dmSize
=
FIELD_OFFSET
(
DEVMODEW
,
dmICMMethod
)
-
1
;
res
=
ChangeDisplaySettingsExW
(
NULL
,
&
dmW
,
NULL
,
CDS_TEST
,
NULL
);
if
(
GetLastError
()
!=
ERROR_CALL_NOT_IMPLEMENTED
)
ok
(
res
==
DISP_CHANGE_FAILED
||
res
==
DISP_CHANGE_BADPARAM
||
/* NT4 */
res
==
DISP_CHANGE_BADMODE
/* XP SP3 */
,
"ChangeDisplaySettingsExW returned %d
\n
"
,
res
);
todo_wine
ok
(
res
==
DISP_CHANGE_BADMODE
,
"ChangeDisplaySettingsExW returned %d, expect DISP_CHANGE_BADMODE
\n
"
,
res
);
dmW
.
dmSize
=
FIELD_OFFSET
(
DEVMODEW
,
dmICMMethod
);
res
=
ChangeDisplaySettingsW
(
&
dmW
,
CDS_TEST
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsW returned unexpected %d
\n
"
,
res
);
dmW
.
dmSize
=
FIELD_OFFSET
(
DEVMODEW
,
dmICMMethod
);
res
=
ChangeDisplaySettingsExW
(
NULL
,
&
dmW
,
NULL
,
CDS_TEST
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExW returned unexpected %d
\n
"
,
res
);
/* Test clip rectangle after resolution changes */
/* GetClipCursor always returns result in physical pixels but GetSystemMetrics(SM_CX/CYVIRTUALSCREEN) are not.
...
...
@@ -349,7 +435,7 @@ static void test_ChangeDisplaySettingsEx(void)
(
res
==
DISP_CHANGE_SUCCESSFUL
||
res
==
DISP_CHANGE_RESTART
)
:
(
res
==
DISP_CHANGE_SUCCESSFUL
||
res
==
DISP_CHANGE_RESTART
||
res
==
DISP_CHANGE_BADMODE
||
res
==
DISP_CHANGE_BADPARAM
),
"Unexpected ChangeDisplaySettingsEx
() return code for resolution
[%d]: %d
\n
"
,
i
,
res
);
"Unexpected ChangeDisplaySettingsEx
A() return code for vid_modes_test
[%d]: %d
\n
"
,
i
,
res
);
if
(
res
==
DISP_CHANGE_SUCCESSFUL
)
{
...
...
@@ -394,6 +480,395 @@ static void test_ChangeDisplaySettingsEx(void)
pSetThreadDpiAwarenessContext
(
context
);
res
=
ChangeDisplaySettingsExA
(
NULL
,
NULL
,
NULL
,
CDS_RESET
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"Failed to reset default resolution: %d
\n
"
,
res
);
/* Save the original mode for all devices so that they can be restored at the end of tests */
device_count
=
0
;
device_size
=
2
;
devices
=
heap_calloc
(
device_size
,
sizeof
(
*
devices
));
ok
(
devices
!=
NULL
,
"Failed to allocate memory.
\n
"
);
primary
=
0
;
memset
(
&
dd
,
0
,
sizeof
(
dd
));
dd
.
cb
=
sizeof
(
dd
);
for
(
device
=
0
;
EnumDisplayDevicesA
(
NULL
,
device
,
&
dd
,
0
);
++
device
)
{
INT
number
;
/* Skip software devices */
if
(
sscanf
(
dd
.
DeviceName
,
"
\\\\
.
\\
DISPLAY%d"
,
&
number
)
!=
1
)
continue
;
if
(
!
(
dd
.
StateFlags
&
DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
))
continue
;
if
(
dd
.
StateFlags
&
DISPLAY_DEVICE_PRIMARY_DEVICE
)
primary
=
device_count
;
if
(
device_count
>=
device_size
)
{
device_size
*=
2
;
devices
=
heap_realloc
(
devices
,
device_size
*
sizeof
(
*
devices
));
ok
(
devices
!=
NULL
,
"Failed to reallocate memory.
\n
"
);
}
devices
[
device_count
].
index
=
device
;
lstrcpyA
(
devices
[
device_count
].
name
,
dd
.
DeviceName
);
devices
[
device_count
].
original_mode
.
dmSize
=
sizeof
(
devices
[
device_count
].
original_mode
);
res
=
EnumDisplaySettingsA
(
dd
.
DeviceName
,
ENUM_CURRENT_SETTINGS
,
&
devices
[
device_count
].
original_mode
);
ok
(
res
,
"EnumDisplaySettingsA %s failed, error %#x
\n
"
,
dd
.
DeviceName
,
GetLastError
());
++
device_count
;
}
/* Make the primary adapter first */
if
(
primary
)
{
struct
device_info
tmp
;
tmp
=
devices
[
0
];
devices
[
0
]
=
devices
[
primary
];
devices
[
primary
]
=
tmp
;
}
/* Test detaching adapters */
/* Test that when there is only one adapter, it can't be detached */
if
(
device_count
==
1
)
{
old_count
=
GetSystemMetrics
(
SM_CMONITORS
);
memset
(
&
dm
,
0
,
sizeof
(
dm
));
dm
.
dmSize
=
sizeof
(
dm
);
dm
.
dmFields
=
DM_POSITION
|
DM_PELSWIDTH
|
DM_PELSHEIGHT
;
dm
.
dmPosition
=
devices
[
0
].
original_mode
.
dmPosition
;
res
=
ChangeDisplaySettingsExA
(
devices
[
0
].
name
,
&
dm
,
NULL
,
CDS_UPDATEREGISTRY
|
CDS_NORESET
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
0
].
name
,
res
);
res
=
ChangeDisplaySettingsExA
(
NULL
,
NULL
,
NULL
,
0
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
||
broken
(
res
==
DISP_CHANGE_FAILED
),
/* win8 TestBot */
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
0
].
name
,
res
);
/* Check that the adapter is still attached */
dd
.
cb
=
sizeof
(
dd
);
res
=
EnumDisplayDevicesA
(
NULL
,
devices
[
0
].
index
,
&
dd
,
0
);
ok
(
res
,
"EnumDisplayDevicesA %s failed, error %#x
\n
"
,
devices
[
0
].
name
,
GetLastError
());
ok
(
dd
.
StateFlags
&
DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
,
"Expect device %s still attached.
\n
"
,
devices
[
0
].
name
);
count
=
GetSystemMetrics
(
SM_CMONITORS
);
ok
(
count
==
old_count
,
"Expect monitor count %d, got %d
\n
"
,
old_count
,
count
);
/* Restore registry settings */
res
=
ChangeDisplaySettingsExA
(
devices
[
0
].
name
,
&
devices
[
0
].
original_mode
,
NULL
,
CDS_UPDATEREGISTRY
|
CDS_NORESET
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
||
broken
(
res
==
DISP_CHANGE_BADPARAM
)
||
/* win10 */
broken
(
res
==
DISP_CHANGE_FAILED
),
/* win8 TestBot */
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
0
].
name
,
res
);
res
=
ChangeDisplaySettingsExA
(
NULL
,
NULL
,
NULL
,
0
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
||
broken
(
res
==
DISP_CHANGE_FAILED
),
/* win8 TestBot */
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
0
].
name
,
res
);
}
/* Test that only specifying DM_POSITION in dmFields is not enough to detach an adapter */
if
(
device_count
>=
2
)
{
old_count
=
GetSystemMetrics
(
SM_CMONITORS
);
/* MSDN says set dmFields to DM_POSITION to detach, but DM_PELSWIDTH and DM_PELSHEIGHT are needed actually.
* To successfully detach adapters, settings have to be saved to the registry first, and then call
* ChangeDisplaySettingsExA(device, NULL, NULL, 0, NULL) to update settings. Otherwise on some older versions
* of Windows, e.g., XP and Win7, the adapter doesn't get detached */
memset
(
&
dm
,
0
,
sizeof
(
dm
));
dm
.
dmSize
=
sizeof
(
dm
);
dm
.
dmFields
=
DM_POSITION
;
dm
.
dmPosition
=
devices
[
1
].
original_mode
.
dmPosition
;
res
=
ChangeDisplaySettingsExA
(
devices
[
1
].
name
,
&
dm
,
NULL
,
CDS_UPDATEREGISTRY
|
CDS_NORESET
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
1
].
name
,
res
);
res
=
ChangeDisplaySettingsExA
(
devices
[
1
].
name
,
NULL
,
NULL
,
0
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
1
].
name
,
res
);
dd
.
cb
=
sizeof
(
dd
);
res
=
EnumDisplayDevicesA
(
NULL
,
devices
[
1
].
index
,
&
dd
,
0
);
ok
(
res
,
"EnumDisplayDevicesA %s failed, error %#x
\n
"
,
devices
[
1
].
name
,
GetLastError
());
ok
(
dd
.
StateFlags
&
DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
,
"Expect device %s still attached.
\n
"
,
devices
[
1
].
name
);
count
=
GetSystemMetrics
(
SM_CMONITORS
);
ok
(
count
==
old_count
,
"Expect monitor count %d, got %d
\n
"
,
old_count
,
count
);
}
/* Detach all non-primary adapters to avoid position conflicts */
for
(
device
=
1
;
device
<
device_count
;
++
device
)
{
old_count
=
GetSystemMetrics
(
SM_CMONITORS
);
memset
(
&
dm
,
0
,
sizeof
(
dm
));
dm
.
dmSize
=
sizeof
(
dm
);
dm
.
dmFields
=
DM_POSITION
|
DM_PELSWIDTH
|
DM_PELSHEIGHT
;
dm
.
dmPosition
=
devices
[
device
].
original_mode
.
dmPosition
;
res
=
ChangeDisplaySettingsExA
(
devices
[
device
].
name
,
&
dm
,
NULL
,
CDS_UPDATEREGISTRY
|
CDS_NORESET
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
device
].
name
,
res
);
res
=
ChangeDisplaySettingsExA
(
devices
[
device
].
name
,
NULL
,
NULL
,
0
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
device
].
name
,
res
);
dd
.
cb
=
sizeof
(
dd
);
res
=
EnumDisplayDevicesA
(
NULL
,
devices
[
device
].
index
,
&
dd
,
0
);
ok
(
res
,
"EnumDisplayDevicesA %s failed, error %#x
\n
"
,
devices
[
device
].
name
,
GetLastError
());
todo_wine
ok
(
!
(
dd
.
StateFlags
&
DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
),
"Expect device %s detached.
\n
"
,
devices
[
device
].
name
);
count
=
GetSystemMetrics
(
SM_CMONITORS
);
todo_wine
ok
(
count
==
old_count
-
1
,
"Expect monitor count %d, got %d
\n
"
,
old_count
-
1
,
count
);
}
/* Test changing each adapter to every available mode */
position
.
x
=
0
;
position
.
y
=
0
;
for
(
device
=
0
;
device
<
device_count
;
++
device
)
{
memset
(
&
dm
,
0
,
sizeof
(
dm
));
dm
.
dmSize
=
sizeof
(
dm
);
for
(
mode
=
0
;
EnumDisplaySettingsExA
(
devices
[
device
].
name
,
mode
,
&
dm
,
0
);
++
mode
)
{
dm
.
dmPosition
=
position
;
dm
.
dmFields
|=
DM_POSITION
;
res
=
ChangeDisplaySettingsExA
(
devices
[
device
].
name
,
&
dm
,
NULL
,
CDS_RESET
,
NULL
);
/* Reattach detached non-primary adapters, otherwise ChangeDisplaySettingsExA with only CDS_RESET fails */
if
(
mode
==
0
&&
device
)
{
todo_wine
ok
(
res
==
DISP_CHANGE_FAILED
,
"ChangeDisplaySettingsExA %s mode %d returned unexpected %d
\n
"
,
devices
[
device
].
name
,
mode
,
res
);
res
=
ChangeDisplaySettingsExA
(
devices
[
device
].
name
,
&
dm
,
NULL
,
CDS_UPDATEREGISTRY
|
CDS_NORESET
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExA %s mode %d returned unexpected %d
\n
"
,
devices
[
device
].
name
,
mode
,
res
);
res
=
ChangeDisplaySettingsExA
(
NULL
,
NULL
,
NULL
,
0
,
NULL
);
}
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
||
broken
(
res
==
DISP_CHANGE_FAILED
),
/* TestBots using VGA driver can't change to some modes */
"ChangeDisplaySettingsExA %s mode %d returned unexpected %d
\n
"
,
devices
[
device
].
name
,
mode
,
res
);
if
(
res
!=
DISP_CHANGE_SUCCESSFUL
)
{
win_skip
(
"Failed to change %s to mode %d.
\n
"
,
devices
[
device
].
name
,
mode
);
continue
;
}
expect_dm
(
dm
,
devices
[
device
].
name
,
mode
);
}
/* Restore settings */
res
=
ChangeDisplaySettingsExA
(
devices
[
device
].
name
,
NULL
,
NULL
,
0
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
||
broken
(
res
==
DISP_CHANGE_FAILED
),
/* win8 TestBot */
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
device
].
name
,
res
);
/* Place the next adapter to the right so that there is no position conflict */
memset
(
&
dm
,
0
,
sizeof
(
dm
));
dm
.
dmSize
=
sizeof
(
dm
);
res
=
EnumDisplaySettingsA
(
devices
[
device
].
name
,
ENUM_CURRENT_SETTINGS
,
&
dm
);
/* After many resolution changes, EnumDisplaySettingsA may fail on win10 TestBot */
ok
(
res
||
broken
(
!
res
),
"EnumDisplaySettingsA %s failed, error %#x
\n
"
,
devices
[
device
].
name
,
GetLastError
());
if
(
!
res
)
{
win_skip
(
"EnumDisplaySettingsA %s failed, error %#x
\n
"
,
devices
[
device
].
name
,
GetLastError
());
continue
;
}
position
.
x
=
dm
.
dmPosition
.
x
+
dm
.
dmPelsWidth
;
}
/* Test changing modes by saving settings to the registry first */
for
(
device
=
0
;
device
<
device_count
;
++
device
)
{
memset
(
&
dm
,
0
,
sizeof
(
dm
));
dm
.
dmSize
=
sizeof
(
dm
);
res
=
EnumDisplaySettingsA
(
devices
[
device
].
name
,
ENUM_CURRENT_SETTINGS
,
&
dm
);
/* After many resolution changes, EnumDisplaySettingsA may fail on win10 TestBot */
ok
(
res
||
broken
(
!
res
),
"EnumDisplaySettingsA %s failed, error %#x
\n
"
,
devices
[
device
].
name
,
GetLastError
());
if
(
!
res
)
{
win_skip
(
"EnumDisplaySettingsA %s failed, error %#x
\n
"
,
devices
[
device
].
name
,
GetLastError
());
continue
;
}
/* Find a mode that's different from the current mode */
memset
(
&
dm2
,
0
,
sizeof
(
dm2
));
dm2
.
dmSize
=
sizeof
(
dm2
);
for
(
mode
=
0
;
EnumDisplaySettingsA
(
devices
[
device
].
name
,
mode
,
&
dm2
);
++
mode
)
{
if
(
dm2
.
dmPelsWidth
!=
dm
.
dmPelsWidth
&&
dm2
.
dmPelsHeight
!=
dm
.
dmPelsHeight
)
break
;
}
ok
(
dm2
.
dmPelsWidth
!=
dm
.
dmPelsWidth
&&
dm2
.
dmPelsHeight
!=
dm
.
dmPelsHeight
,
"Failed to find a different mode.
\n
"
);
dm
.
dmPelsWidth
=
dm2
.
dmPelsWidth
;
dm
.
dmPelsHeight
=
dm2
.
dmPelsHeight
;
dm
.
dmDisplayFrequency
=
dm2
.
dmDisplayFrequency
;
res
=
ChangeDisplaySettingsExA
(
devices
[
device
].
name
,
&
dm
,
NULL
,
CDS_UPDATEREGISTRY
|
CDS_NORESET
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
||
broken
(
res
==
DISP_CHANGE_FAILED
),
/* win8 TestBot */
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
device
].
name
,
res
);
res
=
ChangeDisplaySettingsExA
(
devices
[
device
].
name
,
NULL
,
NULL
,
0
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
||
broken
(
res
==
DISP_CHANGE_FAILED
),
/* win8 TestBot */
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
device
].
name
,
res
);
if
(
res
!=
DISP_CHANGE_SUCCESSFUL
)
{
win_skip
(
"Failed to change mode for %s.
\n
"
,
devices
[
device
].
name
);
continue
;
}
expect_dm
(
dm
,
devices
[
device
].
name
,
0
);
}
/* Test dmPosition */
/* First detach all adapters except for the primary and secondary adapters to avoid position conflicts */
if
(
device_count
>=
3
)
{
for
(
device
=
2
;
device
<
device_count
;
++
device
)
{
memset
(
&
dm
,
0
,
sizeof
(
dm
));
dm
.
dmSize
=
sizeof
(
dm
);
res
=
EnumDisplaySettingsA
(
devices
[
device
].
name
,
ENUM_CURRENT_SETTINGS
,
&
dm
);
ok
(
res
,
"EnumDisplaySettingsA %s failed, error %#x
\n
"
,
devices
[
device
].
name
,
GetLastError
());
dm
.
dmPelsWidth
=
0
;
dm
.
dmPelsHeight
=
0
;
dm
.
dmFields
=
DM_POSITION
|
DM_PELSWIDTH
|
DM_PELSHEIGHT
;
res
=
ChangeDisplaySettingsExA
(
devices
[
device
].
name
,
&
dm
,
NULL
,
CDS_UPDATEREGISTRY
|
CDS_NORESET
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
device
].
name
,
res
);
}
res
=
ChangeDisplaySettingsExA
(
NULL
,
NULL
,
NULL
,
0
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExA returned unexpected %d
\n
"
,
res
);
}
if
(
device_count
>=
2
)
{
/* Query the primary adapter settings */
memset
(
&
dm
,
0
,
sizeof
(
dm
));
dm
.
dmSize
=
sizeof
(
dm
);
res
=
EnumDisplaySettingsA
(
devices
[
0
].
name
,
ENUM_CURRENT_SETTINGS
,
&
dm
);
/* After many resolution changes, EnumDisplaySettingsA may fail on win10 TestBot */
ok
(
res
||
broken
(
!
res
),
"EnumDisplaySettingsA %s failed, error %#x
\n
"
,
devices
[
0
].
name
,
GetLastError
());
if
(
res
)
{
/* Query the secondary adapter settings */
memset
(
&
dm2
,
0
,
sizeof
(
dm2
));
dm2
.
dmSize
=
sizeof
(
dm2
);
res
=
EnumDisplaySettingsA
(
devices
[
1
].
name
,
ENUM_CURRENT_SETTINGS
,
&
dm2
);
/* After many resolution changes, EnumDisplaySettingsA may fail on win10 TestBot */
ok
(
res
||
broken
(
!
res
),
"EnumDisplaySettingsA %s failed, error %#x
\n
"
,
devices
[
1
].
name
,
GetLastError
());
}
if
(
res
)
{
/* Test position conflict */
dm2
.
dmPosition
.
x
=
dm
.
dmPosition
.
x
;
dm2
.
dmPosition
.
y
=
dm
.
dmPosition
.
y
;
res
=
ChangeDisplaySettingsExA
(
devices
[
1
].
name
,
&
dm2
,
NULL
,
CDS_RESET
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
1
].
name
,
res
);
/* Position is not changed even if ChangeDisplaySettingsExA returned DISP_CHANGE_SUCCESSFUL */
memset
(
&
dm2
,
0
,
sizeof
(
dm2
));
dm2
.
dmSize
=
sizeof
(
dm2
);
res
=
EnumDisplaySettingsA
(
devices
[
1
].
name
,
ENUM_CURRENT_SETTINGS
,
&
dm2
);
/* After many resolution changes, EnumDisplaySettingsA may fail on win10 TestBot */
ok
(
res
||
broken
(
!
res
),
"EnumDisplaySettingsA %s failed, error %#x
\n
"
,
devices
[
1
].
name
,
GetLastError
());
todo_wine
ok
(
dm2
.
dmPosition
.
x
!=
dm
.
dmPosition
.
x
||
broken
(
!
res
),
"Expect position change not applied.
\n
"
);
/* Test position with extra space. The extra space will be removed */
dm2
.
dmPosition
.
x
=
dm
.
dmPosition
.
x
-
dm2
.
dmPelsWidth
-
dm2
.
dmPelsWidth
/
2
;
dm2
.
dmPosition
.
y
=
dm
.
dmPosition
.
y
;
res
=
ChangeDisplaySettingsExA
(
devices
[
1
].
name
,
&
dm2
,
NULL
,
CDS_RESET
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
1
].
name
,
res
);
dm2
.
dmPosition
.
x
=
dm
.
dmPosition
.
x
-
dm2
.
dmPelsWidth
;
expect_dm
(
dm2
,
devices
[
1
].
name
,
0
);
/* Test placing the secondary adapter to all sides of the primary adapter */
for
(
side
=
0
;
side
<
4
;
++
side
)
{
switch
(
side
)
{
/* Bottom */
case
0
:
dm2
.
dmPosition
.
x
=
dm
.
dmPosition
.
x
;
dm2
.
dmPosition
.
y
=
dm
.
dmPosition
.
y
+
dm
.
dmPelsHeight
;
break
;
/* Left */
case
1
:
dm2
.
dmPosition
.
x
=
dm
.
dmPosition
.
x
-
dm2
.
dmPelsWidth
;
dm2
.
dmPosition
.
y
=
dm
.
dmPosition
.
y
;
break
;
/* Top */
case
2
:
dm2
.
dmPosition
.
x
=
dm
.
dmPosition
.
x
;
dm2
.
dmPosition
.
y
=
dm
.
dmPosition
.
y
-
dm2
.
dmPelsHeight
;
break
;
/* Right */
case
3
:
dm2
.
dmPosition
.
x
=
dm
.
dmPosition
.
x
+
dm
.
dmPelsWidth
;
dm2
.
dmPosition
.
y
=
dm
.
dmPosition
.
y
;
break
;
}
res
=
ChangeDisplaySettingsExA
(
devices
[
1
].
name
,
&
dm2
,
NULL
,
CDS_RESET
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExA %s side %d returned unexpected %d
\n
"
,
devices
[
1
].
name
,
side
,
res
);
if
(
res
!=
DISP_CHANGE_SUCCESSFUL
)
{
win_skip
(
"ChangeDisplaySettingsExA %s side %d returned unexpected %d.
\n
"
,
devices
[
1
].
name
,
side
,
res
);
continue
;
}
expect_dm
(
dm2
,
devices
[
1
].
name
,
side
);
}
/* Test automatic position update when other adapters change resolution */
/* Find a mode that's different from the current mode */
memset
(
&
dm2
,
0
,
sizeof
(
dm2
));
dm2
.
dmSize
=
sizeof
(
dm2
);
for
(
mode
=
0
;
EnumDisplaySettingsA
(
devices
[
0
].
name
,
mode
,
&
dm2
);
++
mode
)
{
if
(
dm2
.
dmPelsWidth
!=
dm
.
dmPelsWidth
&&
dm2
.
dmPelsHeight
!=
dm
.
dmPelsHeight
)
break
;
}
ok
(
dm2
.
dmPelsWidth
!=
dm
.
dmPelsWidth
&&
dm2
.
dmPelsHeight
!=
dm
.
dmPelsHeight
,
"Failed to find a different mode.
\n
"
);
/* Change the primary adapter to a different mode */
dm
=
dm2
;
res
=
ChangeDisplaySettingsExA
(
devices
[
0
].
name
,
&
dm
,
NULL
,
CDS_RESET
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
,
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
0
].
name
,
res
);
/* Now the position of the second adapter should be changed */
memset
(
&
dm2
,
0
,
sizeof
(
dm2
));
dm2
.
dmSize
=
sizeof
(
dm2
);
res
=
EnumDisplaySettingsA
(
devices
[
1
].
name
,
ENUM_CURRENT_SETTINGS
,
&
dm2
);
/* After many resolution changes, EnumDisplaySettingsA may fail on win10 TestBot */
ok
(
res
||
broken
(
!
res
),
"EnumDisplaySettingsA %s failed, error %#x
\n
"
,
devices
[
1
].
name
,
GetLastError
());
todo_wine
ok
(
dm2
.
dmPosition
.
x
==
dm
.
dmPelsWidth
||
broken
(
!
res
),
"Expect dmPosition.x %d, got %d
\n
"
,
dm
.
dmPelsWidth
,
dm2
.
dmPosition
.
x
);
}
else
{
win_skip
(
"EnumDisplaySettingsA failed
\n
"
);
}
}
/* Restore all adapters to their original settings */
for
(
device
=
0
;
device
<
device_count
;
++
device
)
{
res
=
ChangeDisplaySettingsExA
(
devices
[
device
].
name
,
&
devices
[
device
].
original_mode
,
NULL
,
CDS_UPDATEREGISTRY
|
CDS_NORESET
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
||
broken
(
res
==
DISP_CHANGE_FAILED
),
/* win8 TestBot */
"ChangeDisplaySettingsExA %s returned unexpected %d
\n
"
,
devices
[
device
].
name
,
res
);
}
res
=
ChangeDisplaySettingsExA
(
NULL
,
NULL
,
NULL
,
0
,
NULL
);
ok
(
res
==
DISP_CHANGE_SUCCESSFUL
||
broken
(
res
==
DISP_CHANGE_FAILED
),
/* win8 TestBot */
"ChangeDisplaySettingsExA returned unexpected %d
\n
"
,
res
);
for
(
device
=
0
;
device
<
device_count
;
++
device
)
expect_dm
(
devices
[
device
].
original_mode
,
devices
[
device
].
name
,
0
);
heap_free
(
devices
);
}
static
void
test_monitors
(
void
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment