2005-09-28 12:17:13 +02:00
/*
* Unit tests for monitor APIs
*
* Copyright 2005 Huw Davies
2008-08-26 13:40:58 +02:00
* Copyright 2008 Dmitry Timoshkov
2005-09-28 12:17:13 +02:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
2006-05-18 14:49:52 +02:00
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA
2005-09-28 12:17:13 +02:00
*/
2021-09-01 08:37:21 +02:00
# include "ntstatus.h"
# define WIN32_NO_STATUS
2005-09-28 12:17:13 +02:00
# include "wine/test.h"
# include "winbase.h"
# include "wingdi.h"
# include "winuser.h"
2019-02-21 10:04:39 +01:00
# include "winreg.h"
2021-09-01 08:37:21 +02:00
# include "winternl.h"
# include "ddk/d3dkmthk.h"
2020-02-04 08:54:34 +01:00
# include "wine/heap.h"
2019-02-21 10:04:39 +01:00
# include <stdio.h>
2005-09-28 12:17:13 +02:00
2015-10-23 20:40:50 +02:00
static LONG ( WINAPI * pGetDisplayConfigBufferSizes ) ( UINT32 , UINT32 * , UINT32 * ) ;
2021-09-01 08:37:21 +02:00
static BOOL ( WINAPI * pGetDpiForMonitorInternal ) ( HMONITOR , UINT , UINT * , UINT * ) ;
2020-05-05 03:08:29 +02:00
static LONG ( WINAPI * pQueryDisplayConfig ) ( UINT32 , UINT32 * , DISPLAYCONFIG_PATH_INFO * , UINT32 * ,
DISPLAYCONFIG_MODE_INFO * , DISPLAYCONFIG_TOPOLOGY_ID * ) ;
static LONG ( WINAPI * pDisplayConfigGetDeviceInfo ) ( DISPLAYCONFIG_DEVICE_INFO_HEADER * ) ;
2021-09-01 08:37:21 +02:00
static LONG ( WINAPI * pDisplayConfigSetDeviceInfo ) ( DISPLAYCONFIG_DEVICE_INFO_HEADER * ) ;
2019-12-03 15:38:15 +01:00
static DPI_AWARENESS_CONTEXT ( WINAPI * pSetThreadDpiAwarenessContext ) ( DPI_AWARENESS_CONTEXT ) ;
2005-10-11 22:27:27 +02:00
2021-09-01 08:37:21 +02:00
static NTSTATUS ( WINAPI * pD3DKMTCloseAdapter ) ( const D3DKMT_CLOSEADAPTER * ) ;
static NTSTATUS ( WINAPI * pD3DKMTOpenAdapterFromGdiDisplayName ) ( D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME * ) ;
2005-10-11 22:27:27 +02:00
static void init_function_pointers ( void )
{
2021-09-01 08:37:21 +02:00
HMODULE user32 = GetModuleHandleA ( " user32.dll " ) ;
HMODULE gdi32 = GetModuleHandleA ( " gdi32.dll " ) ;
2007-08-15 14:23:45 +02:00
2021-09-01 08:37:21 +02:00
# define GET_PROC(module, func) \
p # # func = ( void * ) GetProcAddress ( module , # func ) ; \
if ( ! p # # func ) \
trace ( " GetProcAddress(%s, %s) failed. \n " , # module , # func ) ;
2007-08-15 14:23:45 +02:00
2021-09-01 08:37:21 +02:00
GET_PROC ( user32 , GetDisplayConfigBufferSizes )
GET_PROC ( user32 , GetDpiForMonitorInternal )
GET_PROC ( user32 , QueryDisplayConfig )
GET_PROC ( user32 , DisplayConfigGetDeviceInfo )
GET_PROC ( user32 , DisplayConfigSetDeviceInfo )
GET_PROC ( user32 , SetThreadDpiAwarenessContext )
GET_PROC ( gdi32 , D3DKMTCloseAdapter )
GET_PROC ( gdi32 , D3DKMTOpenAdapterFromGdiDisplayName )
2007-08-15 14:23:45 +02:00
# undef GET_PROC
2005-10-11 22:27:27 +02:00
}
2020-05-05 14:30:07 +02:00
static void flush_events ( void )
{
int diff = 1000 ;
DWORD time ;
MSG msg ;
time = GetTickCount ( ) + diff ;
while ( diff > 0 )
{
if ( MsgWaitForMultipleObjects ( 0 , NULL , FALSE , 200 , QS_ALLINPUT ) = = WAIT_TIMEOUT )
break ;
while ( PeekMessageA ( & msg , 0 , 0 , 0 , PM_REMOVE ) )
DispatchMessageA ( & msg ) ;
diff = time - GetTickCount ( ) ;
}
}
2021-09-01 08:37:21 +02:00
static unsigned int get_primary_dpi ( void )
{
DPI_AWARENESS_CONTEXT old_context ;
UINT dpi_x = 0 , dpi_y = 0 ;
POINT point = { 0 , 0 } ;
HMONITOR monitor ;
if ( ! pSetThreadDpiAwarenessContext | | ! pGetDpiForMonitorInternal )
return 0 ;
old_context = pSetThreadDpiAwarenessContext ( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ) ;
monitor = MonitorFromPoint ( point , MONITOR_DEFAULTTOPRIMARY ) ;
pGetDpiForMonitorInternal ( monitor , 0 , & dpi_x , & dpi_y ) ;
pSetThreadDpiAwarenessContext ( old_context ) ;
return dpi_y ;
}
2021-05-17 09:20:42 +02:00
static int get_bitmap_stride ( int width , int bpp )
{
return ( ( width * bpp + 15 ) > > 3 ) & ~ 1 ;
}
2019-02-21 10:04:39 +01:00
static int adapter_count = 0 ;
static int monitor_count = 0 ;
static void test_enumdisplaydevices_adapter ( int index , const DISPLAY_DEVICEA * device , DWORD flags )
{
char buffer [ 128 ] ;
int number ;
int vendor_id ;
int device_id ;
int subsys_id ;
int revision_id ;
HDC hdc ;
adapter_count + + ;
/* DeviceName */
ok ( sscanf ( device - > DeviceName , " \\ \\ . \\ DISPLAY%d " , & number ) = = 1 , " #%d: wrong DeviceName %s \n " , index ,
device - > DeviceName ) ;
/* DeviceKey */
2019-11-07 15:06:18 +01:00
/* \Device\Video? value in HLKM\HARDWARE\DEVICEMAP\VIDEO are not necessarily in order with adapter index.
* Check format only */
ok ( sscanf ( device - > DeviceKey , " \\ Registry \\ Machine \\ System \\ CurrentControlSet \\ Control \\ Video \\ %[^ \\ ] \\ %04d " , buffer , & number ) = = 2 ,
" #%d: wrong DeviceKey %s \n " , index , device - > DeviceKey ) ;
2019-02-21 10:04:39 +01:00
/* DeviceString */
2019-12-09 09:41:53 +01:00
ok ( broken ( ! * device - > DeviceString ) | | /* XP on Testbot will return an empty string, whereas XP on real machine doesn't. Probably a bug in virtual adapter driver */
* device - > DeviceString , " #%d: expect DeviceString not empty \n " , index ) ;
2019-02-21 10:04:39 +01:00
/* StateFlags */
if ( device - > StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP )
{
/* Test creating DC */
hdc = CreateDCA ( device - > DeviceName , NULL , NULL , NULL ) ;
ok ( hdc ! = NULL , " #%d: failed to CreateDC( \" %s \" ) err=%d \n " , index , device - > DeviceName , GetLastError ( ) ) ;
DeleteDC ( hdc ) ;
}
/* DeviceID */
/* DeviceID should equal to the first string of HardwareID value data in PCI GPU instance. You can verify this
* by changing the data and rerun EnumDisplayDevices . But it ' s difficult to find corresponding PCI device on
* userland . So here we check the expected format instead . */
if ( flags & EDD_GET_DEVICE_INTERFACE_NAME )
2019-06-10 16:08:40 +02:00
ok ( strlen ( device - > DeviceID ) = = 0 | | /* vista+ */
2019-02-21 10:04:39 +01:00
sscanf ( device - > DeviceID , " PCI \\ VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X " ,
& vendor_id , & device_id , & subsys_id , & revision_id ) = = 4 , /* XP/2003 ignores EDD_GET_DEVICE_INTERFACE_NAME */
" #%d: got %s \n " , index , device - > DeviceID ) ;
else
{
2019-06-10 16:08:40 +02:00
ok ( broken ( strlen ( device - > DeviceID ) = = 0 ) | | /* XP on Testbot returns an empty string, whereas real machine doesn't */
2019-02-21 10:04:39 +01:00
sscanf ( device - > DeviceID , " PCI \\ VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X " , & vendor_id , & device_id , & subsys_id ,
& revision_id ) = = 4 , " #%d: wrong DeviceID %s \n " , index , device - > DeviceID ) ;
}
}
2021-09-16 09:17:38 +02:00
static void test_enumdisplaydevices_monitor ( int monitor_index , const char * adapter_name ,
2019-11-07 15:06:18 +01:00
DISPLAY_DEVICEA * device , DWORD flags )
2019-02-21 10:04:39 +01:00
{
static const char device_key_prefix [ ] = " \\ Registry \\ Machine \\ System \\ CurrentControlSet \\ Control \\ Class "
" \\ {4d36e96e-e325-11ce-bfc1-08002be10318} \\ " ;
char monitor_name [ 32 ] ;
char buffer [ 128 ] ;
int number ;
monitor_count + + ;
/* DeviceName */
lstrcpyA ( monitor_name , adapter_name ) ;
sprintf ( monitor_name + strlen ( monitor_name ) , " \\ Monitor%d " , monitor_index ) ;
2019-06-10 16:08:40 +02:00
ok ( ! strcmp ( monitor_name , device - > DeviceName ) , " #%d: expect %s, got %s \n " , monitor_index , monitor_name , device - > DeviceName ) ;
2019-02-21 10:04:39 +01:00
/* DeviceString */
2019-12-09 09:41:53 +01:00
ok ( * device - > DeviceString , " #%d: expect DeviceString not empty \n " , monitor_index ) ;
2019-02-21 10:04:39 +01:00
/* StateFlags */
2021-09-16 09:17:38 +02:00
ok ( device - > StateFlags < = ( DISPLAY_DEVICE_ATTACHED | DISPLAY_DEVICE_ACTIVE ) ,
" #%d wrong state %#x \n " , monitor_index , device - > StateFlags ) ;
2019-02-21 10:04:39 +01:00
/* DeviceID */
2019-11-07 15:06:18 +01:00
CharLowerA ( device - > DeviceID ) ;
2019-02-21 10:04:39 +01:00
if ( flags & EDD_GET_DEVICE_INTERFACE_NAME )
2019-11-07 15:06:18 +01:00
{ /* HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY\[monitor name]\[instance id] GUID_DEVINTERFACE_MONITOR
* ^ ^ ^
* Expect format \ \ ? \ DISPLAY # [ monitor name ] # [ instance id ] # { e6f07b5f - ee97 - 4 a90 - b076 - 33f 57 bf4eaa7 } */
2019-06-10 16:08:40 +02:00
ok ( strlen ( device - > DeviceID ) = = 0 | | /* vista ~ win7 */
2019-11-07 15:06:18 +01:00
sscanf ( device - > DeviceID , " \\ \\ ? \\ display#%[^#]#%[^#]#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7} " , buffer , buffer ) = = 2 | | /* win8+ */
sscanf ( device - > DeviceID , " monitor \\ %[^ \\ ] \\ {4d36e96e-e325-11ce-bfc1-08002be10318} \\ %04d " , buffer , & number ) = = 2 , /* XP/2003 ignores EDD_GET_DEVICE_INTERFACE_NAME */
" #%d: wrong DeviceID : %s \n " , monitor_index , device - > DeviceID ) ;
2019-02-21 10:04:39 +01:00
}
else
{
2019-11-07 15:06:18 +01:00
/* Expect HarewareID value data + Driver value data in HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY\[monitor name]\{instance} */
2019-02-21 10:04:39 +01:00
/* But we don't know which monitor instance this belongs to, so check format instead */
2019-11-07 15:06:18 +01:00
ok ( sscanf ( device - > DeviceID , " monitor \\ %[^ \\ ] \\ {4d36e96e-e325-11ce-bfc1-08002be10318} \\ %04d " , buffer , & number ) = = 2 ,
" #%d: wrong DeviceID : %s \n " , monitor_index , device - > DeviceID ) ;
2019-02-21 10:04:39 +01:00
}
/* DeviceKey */
lstrcpynA ( buffer , device - > DeviceKey , sizeof ( device_key_prefix ) ) ;
2019-06-10 16:08:52 +02:00
ok ( ! lstrcmpiA ( buffer , device_key_prefix ) , " #%d: wrong DeviceKey : %s \n " , monitor_index , device - > DeviceKey ) ;
ok ( sscanf ( device - > DeviceKey + sizeof ( device_key_prefix ) - 1 , " %04d " , & number ) = = 1 ,
" #%d wrong DeviceKey : %s \n " , monitor_index , device - > DeviceKey ) ;
2019-02-21 10:04:39 +01:00
}
2005-09-28 12:17:13 +02:00
static void test_enumdisplaydevices ( void )
{
2019-02-21 10:04:39 +01:00
static const DWORD flags [ ] = { 0 , EDD_GET_DEVICE_INTERFACE_NAME } ;
2005-09-28 12:17:13 +02:00
DISPLAY_DEVICEA dd ;
2019-02-21 10:04:39 +01:00
char adapter_name [ 32 ] ;
int number ;
int flag_index ;
int adapter_index ;
int monitor_index ;
2008-08-26 13:40:58 +02:00
BOOL ret ;
2019-02-21 10:04:39 +01:00
/* Doesn't accept \\.\DISPLAY */
2005-09-28 12:17:13 +02:00
dd . cb = sizeof ( dd ) ;
2019-12-03 15:37:50 +01:00
ret = EnumDisplayDevicesA ( " \\ \\ . \\ DISPLAY " , 0 , & dd , 0 ) ;
2019-06-10 16:08:40 +02:00
ok ( ! ret , " Expect failure \n " ) ;
2019-02-21 10:04:39 +01:00
/* Enumeration */
for ( flag_index = 0 ; flag_index < ARRAY_SIZE ( flags ) ; flag_index + + )
2019-12-03 15:37:50 +01:00
for ( adapter_index = 0 ; EnumDisplayDevicesA ( NULL , adapter_index , & dd , flags [ flag_index ] ) ; adapter_index + + )
2006-01-03 12:05:54 +01:00
{
2019-02-21 10:04:39 +01:00
lstrcpyA ( adapter_name , dd . DeviceName ) ;
if ( sscanf ( adapter_name , " \\ \\ . \\ DISPLAYV%d " , & number ) = = 1 )
{
skip ( " Skipping software devices %s:%s \n " , adapter_name , dd . DeviceString ) ;
continue ;
}
test_enumdisplaydevices_adapter ( adapter_index , & dd , flags [ flag_index ] ) ;
2019-12-03 15:37:50 +01:00
for ( monitor_index = 0 ; EnumDisplayDevicesA ( adapter_name , monitor_index , & dd , flags [ flag_index ] ) ;
2019-02-21 10:04:39 +01:00
monitor_index + + )
2021-09-16 09:17:38 +02:00
test_enumdisplaydevices_monitor ( monitor_index , adapter_name , & dd , flags [ flag_index ] ) ;
2006-01-03 12:05:54 +01:00
}
2005-09-28 12:17:13 +02:00
2019-02-21 10:04:39 +01:00
ok ( adapter_count > 0 , " Expect at least one adapter found \n " ) ;
/* XP on Testbot doesn't report a monitor, whereas XP on real machine does */
ok ( broken ( monitor_count = = 0 ) | | monitor_count > 0 , " Expect at least one monitor found \n " ) ;
2005-09-28 12:17:13 +02:00
}
2006-07-26 07:31:22 +02:00
struct vid_mode
{
DWORD w , h , bpp , freq , fields ;
2008-09-17 16:29:32 +02:00
BOOL must_succeed ;
2006-07-26 07:31:22 +02:00
} ;
2007-12-20 07:50:30 +01:00
static const struct vid_mode vid_modes_test [ ] = {
2019-12-03 15:40:00 +01:00
{ 1024 , 768 , 0 , 0 , DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY , 0 } ,
{ 1024 , 768 , 0 , 0 , DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY , 1 } ,
2020-08-13 11:53:02 +02:00
{ 1024 , 768 , 0 , 1 , DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY , 0 } ,
2019-12-03 15:40:00 +01:00
{ 1024 , 768 , 0 , 0 , DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL , 0 } ,
{ 1024 , 768 , 0 , 0 , DM_PELSWIDTH | DM_PELSHEIGHT , 1 } ,
{ 1024 , 768 , 0 , 0 , DM_BITSPERPEL , 0 } ,
{ 1024 , 768 , 0 , 0 , DM_DISPLAYFREQUENCY , 0 } ,
2007-02-22 12:43:06 +01:00
2008-09-17 16:29:32 +02:00
{ 0 , 0 , 0 , 0 , DM_PELSWIDTH , 0 } ,
{ 0 , 0 , 0 , 0 , DM_PELSHEIGHT , 0 } ,
2007-02-22 12:43:06 +01:00
2019-12-03 15:40:00 +01:00
{ 1024 , 768 , 0 , 0 , DM_PELSWIDTH , 0 } ,
{ 1024 , 768 , 0 , 0 , DM_PELSHEIGHT , 0 } ,
{ 0 , 768 , 0 , 0 , DM_PELSWIDTH | DM_PELSHEIGHT , 0 } ,
{ 1024 , 0 , 0 , 0 , DM_PELSWIDTH | DM_PELSHEIGHT , 0 } ,
2007-02-22 12:43:06 +01:00
2008-05-18 11:47:14 +02:00
/* the following test succeeds under XP SP3
{ 0 , 0 , 0 , 0 , DM_DISPLAYFREQUENCY , 0 }
*/
2006-07-26 07:31:22 +02:00
} ;
2020-02-04 08:54:34 +01:00
struct device_info
{
DWORD index ;
CHAR name [ CCHDEVICENAME ] ;
DEVMODEA original_mode ;
} ;
# define expect_dm(a, b, c) _expect_dm(__LINE__, a, b, c)
2020-11-13 08:53:09 +01:00
static void _expect_dm ( INT line , const DEVMODEA * expected , const CHAR * device , DWORD test )
2020-02-04 08:54:34 +01:00
{
DEVMODEA dm ;
BOOL ret ;
memset ( & dm , 0 , sizeof ( dm ) ) ;
dm . dmSize = sizeof ( dm ) ;
SetLastError ( 0xdeadbeef ) ;
ret = EnumDisplaySettingsA ( device , ENUM_CURRENT_SETTINGS , & dm ) ;
ok_ ( __FILE__ , line ) ( ret , " Device %s test %d EnumDisplaySettingsA failed, error %#x \n " , device , test , GetLastError ( ) ) ;
2020-11-13 08:53:09 +01:00
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 ) ;
ok_ ( __FILE__ , line ) ( ! ( expected - > dmFields & DM_BITSPERPEL ) | | dm . dmBitsPerPel = = expected - > dmBitsPerPel ,
" Device %s test %d expect dmBitsPerPel %u, got %u \n " , device , test , expected - > dmBitsPerPel , dm . dmBitsPerPel ) ;
ok_ ( __FILE__ , line ) ( ! ( expected - > dmFields & DM_PELSWIDTH ) | | dm . dmPelsWidth = = expected - > dmPelsWidth ,
" Device %s test %d expect dmPelsWidth %u, got %u \n " , device , test , expected - > dmPelsWidth , dm . dmPelsWidth ) ;
ok_ ( __FILE__ , line ) ( ! ( expected - > dmFields & DM_PELSHEIGHT ) | | dm . dmPelsHeight = = expected - > dmPelsHeight ,
" Device %s test %d expect dmPelsHeight %u, got %u \n " , device , test , expected - > dmPelsHeight , dm . dmPelsHeight ) ;
ok_ ( __FILE__ , line ) ( ! ( expected - > dmFields & DM_POSITION ) | | 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 ) ;
ok_ ( __FILE__ , line ) ( ! ( expected - > dmFields & DM_POSITION ) | | 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 ) ;
ok_ ( __FILE__ , line ) ( ! ( expected - > dmFields & DM_DISPLAYFREQUENCY ) | |
dm . dmDisplayFrequency = = expected - > dmDisplayFrequency ,
" Device %s test %d expect dmDisplayFrequency %u, got %u \n " , device , test , expected - > dmDisplayFrequency ,
2020-02-04 08:54:34 +01:00
dm . dmDisplayFrequency ) ;
2020-11-13 08:53:09 +01:00
ok_ ( __FILE__ , line ) ( ! ( expected - > dmFields & DM_DISPLAYORIENTATION ) | |
dm . dmDisplayOrientation = = expected - > dmDisplayOrientation ,
" Device %s test %d expect dmDisplayOrientation %d, got %d \n " , device , test , expected - > dmDisplayOrientation ,
2020-02-04 08:54:34 +01:00
dm . dmDisplayOrientation ) ;
}
2006-07-26 07:31:22 +02:00
static void test_ChangeDisplaySettingsEx ( void )
{
2020-08-25 09:11:56 +02:00
static const DWORD registry_fields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY | DM_POSITION ;
2020-10-27 07:59:34 +01:00
static const DWORD depths [ ] = { 8 , 16 , 32 } ;
2019-12-03 15:38:15 +01:00
DPI_AWARENESS_CONTEXT context = NULL ;
2020-07-21 08:50:05 +02:00
UINT primary , device , test , mode ;
2020-02-04 08:54:34 +01:00
UINT device_size , device_count ;
struct device_info * devices ;
2020-08-25 09:11:56 +02:00
DEVMODEA dm , dm2 , dm3 ;
2020-02-04 08:54:34 +01:00
INT count , old_count ;
DISPLAY_DEVICEA dd ;
POINTL position ;
2007-12-20 07:50:30 +01:00
DEVMODEW dmW ;
2021-05-17 09:20:21 +02:00
BOOL found ;
2006-07-26 07:31:22 +02:00
LONG res ;
int i ;
2020-07-21 08:50:05 +02:00
/* Test invalid device names */
memset ( & dm , 0 , sizeof ( dm ) ) ;
dm . dmSize = sizeof ( dm ) ;
res = EnumDisplaySettingsA ( NULL , ENUM_CURRENT_SETTINGS , & dm ) ;
ok ( res , " EnumDisplaySettingsA failed, error %#x \n " , GetLastError ( ) ) ;
res = ChangeDisplaySettingsExA ( " invalid " , & dm , NULL , CDS_TEST , NULL ) ;
2020-07-21 08:50:19 +02:00
ok ( res = = DISP_CHANGE_BADPARAM , " ChangeDisplaySettingsA returned unexpected %d \n " , res ) ;
2020-07-21 08:50:05 +02:00
res = ChangeDisplaySettingsExA ( " \\ \\ . \\ DISPLAY0 " , & dm , NULL , CDS_TEST , NULL ) ;
2020-07-21 08:50:19 +02:00
ok ( res = = DISP_CHANGE_BADPARAM , " ChangeDisplaySettingsA returned unexpected %d \n " , res ) ;
2020-07-21 08:50:05 +02:00
res = ChangeDisplaySettingsExA ( " \\ \\ . \\ DISPLAY1 \\ Monitor0 " , & dm , NULL , CDS_TEST , NULL ) ;
2020-07-21 08:50:19 +02:00
ok ( res = = DISP_CHANGE_BADPARAM , " ChangeDisplaySettingsA returned unexpected %d \n " , res ) ;
2020-07-21 08:50:05 +02:00
2020-02-04 08:54:34 +01:00
/* Test dmDriverExtra */
memset ( & dm , 0 , sizeof ( dm ) ) ;
dm . dmSize = sizeof ( dm ) ;
2013-10-23 07:53:58 +02:00
res = EnumDisplaySettingsA ( NULL , ENUM_CURRENT_SETTINGS , & dm ) ;
2020-02-04 08:54:34 +01:00
ok ( res , " EnumDisplaySettingsA failed, error %#x \n " , GetLastError ( ) ) ;
2007-12-20 07:50:30 +01:00
2020-02-04 08:54:34 +01:00
memset ( & dmW , 0 , sizeof ( dmW ) ) ;
dmW . dmSize = sizeof ( dmW ) ;
res = EnumDisplaySettingsW ( NULL , ENUM_CURRENT_SETTINGS , & dmW ) ;
ok ( res , " EnumDisplaySettingsW failed, error %#x \n " , GetLastError ( ) ) ;
2007-12-20 07:50:30 +01:00
2020-02-04 08:54:34 +01:00
/* ChangeDisplaySettingsA/W reset dmDriverExtra to 0 */
2008-05-18 11:47:14 +02:00
dm . dmDriverExtra = 1 ;
res = ChangeDisplaySettingsA ( & dm , CDS_TEST ) ;
2020-02-04 08:54:34 +01:00
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsA returned unexpected %d \n " , res ) ;
ok ( dm . dmDriverExtra = = 0 , " ChangeDisplaySettingsA didn't reset dmDriverExtra to 0 \n " ) ;
2008-05-18 11:47:14 +02:00
dmW . dmDriverExtra = 1 ;
res = ChangeDisplaySettingsW ( & dmW , CDS_TEST ) ;
2020-02-04 08:54:34 +01:00
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 " ) ;
2008-05-18 11:47:14 +02:00
dmW . dmDriverExtra = 1 ;
2019-12-03 15:37:50 +01:00
res = ChangeDisplaySettingsExW ( NULL , & dmW , NULL , CDS_TEST , NULL ) ;
2020-02-04 08:54:34 +01:00
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExW returned unexpected %d \n " , res ) ;
ok ( dmW . dmDriverExtra = = 1 , " ChangeDisplaySettingsExW shouldn't change dmDriverExtra \n " ) ;
2008-05-18 11:47:14 +02:00
2020-02-04 08:54:34 +01:00
/* Test dmSize */
/* ChangeDisplaySettingsA/ExA report success even if dmSize is 0 */
2007-12-20 07:50:30 +01:00
memset ( & dm , 0 , sizeof ( dm ) ) ;
2020-02-04 08:54:34 +01:00
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 ;
2019-12-03 15:37:50 +01:00
res = ChangeDisplaySettingsExA ( NULL , & dm , NULL , CDS_TEST , NULL ) ;
2020-02-04 08:54:34 +01:00
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA returned unexpected %d \n " , res ) ;
2007-12-20 07:50:30 +01:00
2020-02-04 08:54:34 +01:00
/* dmSize for ChangeDisplaySettingsW/ExW needs to be at least FIELD_OFFSET(DEVMODEW, dmICMMethod) */
2007-12-20 07:50:30 +01:00
memset ( & dmW , 0 , sizeof ( dmW ) ) ;
2020-02-04 08:54:34 +01:00
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 ) ;
2020-02-10 04:09:43 +01:00
ok ( res = = DISP_CHANGE_BADMODE , " ChangeDisplaySettingsW returned %d, expect DISP_CHANGE_BADMODE \n " , res ) ;
2020-02-04 08:54:34 +01:00
dmW . dmSize = FIELD_OFFSET ( DEVMODEW , dmICMMethod ) - 1 ;
2019-12-03 15:37:50 +01:00
res = ChangeDisplaySettingsExW ( NULL , & dmW , NULL , CDS_TEST , NULL ) ;
2020-02-10 04:09:43 +01:00
ok ( res = = DISP_CHANGE_BADMODE , " ChangeDisplaySettingsExW returned %d, expect DISP_CHANGE_BADMODE \n " , res ) ;
2020-02-04 08:54:34 +01:00
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 ) ;
2007-12-20 07:50:30 +01:00
2019-12-03 15:38:15 +01:00
/* Test clip rectangle after resolution changes */
/* GetClipCursor always returns result in physical pixels but GetSystemMetrics(SM_CX/CYVIRTUALSCREEN) are not.
* Set per - monitor aware context so that virtual screen rectangles are in physical pixels */
if ( pSetThreadDpiAwarenessContext )
context = pSetThreadDpiAwarenessContext ( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ) ;
2006-07-26 07:31:22 +02:00
memset ( & dm , 0 , sizeof ( dm ) ) ;
dm . dmSize = sizeof ( dm ) ;
2018-06-28 18:17:00 +02:00
for ( i = 0 ; i < ARRAY_SIZE ( vid_modes_test ) ; i + + )
2006-07-26 07:31:22 +02:00
{
dm . dmPelsWidth = vid_modes_test [ i ] . w ;
dm . dmPelsHeight = vid_modes_test [ i ] . h ;
dm . dmBitsPerPel = vid_modes_test [ i ] . bpp ;
dm . dmDisplayFrequency = vid_modes_test [ i ] . freq ;
dm . dmFields = vid_modes_test [ i ] . fields ;
2019-12-03 15:37:50 +01:00
res = ChangeDisplaySettingsExA ( NULL , & dm , NULL , CDS_TEST , NULL ) ;
2008-09-17 16:29:32 +02:00
ok ( vid_modes_test [ i ] . must_succeed ?
2009-01-25 17:28:39 +01:00
( res = = DISP_CHANGE_SUCCESSFUL | | res = = DISP_CHANGE_RESTART ) :
2009-01-27 14:38:23 +01:00
( res = = DISP_CHANGE_SUCCESSFUL | | res = = DISP_CHANGE_RESTART | |
res = = DISP_CHANGE_BADMODE | | res = = DISP_CHANGE_BADPARAM ) ,
2020-02-04 08:54:34 +01:00
" Unexpected ChangeDisplaySettingsExA() return code for vid_modes_test[%d]: %d \n " , i , res ) ;
2006-12-14 18:33:51 +01:00
if ( res = = DISP_CHANGE_SUCCESSFUL )
{
RECT r , r1 , virt ;
SetRect ( & virt , 0 , 0 , GetSystemMetrics ( SM_CXVIRTUALSCREEN ) , GetSystemMetrics ( SM_CYVIRTUALSCREEN ) ) ;
2008-11-20 20:06:46 +01:00
if ( IsRectEmpty ( & virt ) ) /* NT4 doesn't have SM_CX/YVIRTUALSCREEN */
SetRect ( & virt , 0 , 0 , GetSystemMetrics ( SM_CXSCREEN ) , GetSystemMetrics ( SM_CYSCREEN ) ) ;
2006-12-14 18:33:51 +01:00
OffsetRect ( & virt , GetSystemMetrics ( SM_XVIRTUALSCREEN ) , GetSystemMetrics ( SM_YVIRTUALSCREEN ) ) ;
/* Resolution change resets clip rect */
ok ( GetClipCursor ( & r ) , " GetClipCursor() failed \n " ) ;
2016-06-16 10:32:02 +02:00
ok ( EqualRect ( & r , & virt ) , " Invalid clip rect: %s \n " , wine_dbgstr_rect ( & r ) ) ;
2006-12-14 18:33:51 +01:00
2009-01-25 17:28:39 +01:00
if ( ! ClipCursor ( NULL ) ) continue ;
2006-12-14 18:33:51 +01:00
ok ( GetClipCursor ( & r ) , " GetClipCursor() failed \n " ) ;
2016-06-16 10:32:02 +02:00
ok ( EqualRect ( & r , & virt ) , " Invalid clip rect: %s \n " , wine_dbgstr_rect ( & r ) ) ;
2006-12-14 18:33:51 +01:00
/* This should always work. Primary monitor is at (0,0) */
SetRect ( & r1 , 10 , 10 , 20 , 20 ) ;
ok ( ClipCursor ( & r1 ) , " ClipCursor() failed \n " ) ;
ok ( GetClipCursor ( & r ) , " GetClipCursor() failed \n " ) ;
2016-06-16 10:32:02 +02:00
ok ( EqualRect ( & r , & r1 ) , " Invalid clip rect: %s \n " , wine_dbgstr_rect ( & r ) ) ;
2011-06-21 14:50:23 +02:00
SetRect ( & r1 , 10 , 10 , 10 , 10 ) ;
ok ( ClipCursor ( & r1 ) , " ClipCursor() failed \n " ) ;
ok ( GetClipCursor ( & r ) , " GetClipCursor() failed \n " ) ;
2016-06-16 10:32:02 +02:00
ok ( EqualRect ( & r , & r1 ) , " Invalid clip rect: %s \n " , wine_dbgstr_rect ( & r ) ) ;
2011-06-21 14:50:23 +02:00
SetRect ( & r1 , 10 , 10 , 10 , 9 ) ;
ok ( ! ClipCursor ( & r1 ) , " ClipCursor() succeeded \n " ) ;
/* Windows bug: further clipping fails once an empty rect is set, so we have to reset it */
ClipCursor ( NULL ) ;
2006-12-14 18:33:51 +01:00
SetRect ( & r1 , virt . left - 10 , virt . top - 10 , virt . right + 20 , virt . bottom + 20 ) ;
ok ( ClipCursor ( & r1 ) , " ClipCursor() failed \n " ) ;
ok ( GetClipCursor ( & r ) , " GetClipCursor() failed \n " ) ;
2016-06-16 10:32:02 +02:00
ok ( EqualRect ( & r , & virt ) | | broken ( EqualRect ( & r , & r1 ) ) /* win9x */ ,
" Invalid clip rect: %s \n " , wine_dbgstr_rect ( & r ) ) ;
2008-09-17 16:29:32 +02:00
ClipCursor ( & virt ) ;
2006-12-14 18:33:51 +01:00
}
2006-07-26 07:31:22 +02:00
}
2019-12-03 15:38:15 +01:00
if ( pSetThreadDpiAwarenessContext & & context )
pSetThreadDpiAwarenessContext ( context ) ;
2019-12-03 15:37:50 +01:00
res = ChangeDisplaySettingsExA ( NULL , NULL , NULL , CDS_RESET , NULL ) ;
2006-10-07 21:45:11 +02:00
ok ( res = = DISP_CHANGE_SUCCESSFUL , " Failed to reset default resolution: %d \n " , res ) ;
2020-02-04 08:54:34 +01:00
/* 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 ) ;
2020-08-11 12:15:28 +02:00
memset ( & devices [ device_count ] . original_mode , 0 , sizeof ( devices [ device_count ] . original_mode ) ) ;
2020-02-04 08:54:34 +01:00
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 ) ;
}
2020-10-27 07:59:34 +01:00
/* Test changing to a mode with depth set but with zero width and height */
2020-10-27 08:00:47 +01:00
for ( device = 0 ; device < device_count ; + + device )
2020-10-27 07:59:34 +01:00
{
for ( test = 0 ; test < ARRAY_SIZE ( depths ) ; + + test )
{
/* Find the native resolution */
memset ( & dm , 0 , sizeof ( dm ) ) ;
memset ( & dm2 , 0 , sizeof ( dm2 ) ) ;
dm2 . dmSize = sizeof ( dm2 ) ;
for ( mode = 0 ; EnumDisplaySettingsExA ( devices [ device ] . name , mode , & dm2 , 0 ) ; + + mode )
{
if ( dm2 . dmBitsPerPel = = depths [ test ]
& & dm2 . dmPelsWidth > dm . dmPelsWidth & & dm2 . dmPelsHeight > dm . dmPelsHeight )
dm = dm2 ;
}
if ( dm . dmBitsPerPel ! = depths [ test ] )
{
skip ( " Depth %u is unsupported for %s. \n " , depths [ test ] , devices [ device ] . name ) ;
continue ;
}
/* Find the second resolution */
memset ( & dm2 , 0 , sizeof ( dm2 ) ) ;
dm2 . dmSize = sizeof ( dm2 ) ;
for ( mode = 0 ; EnumDisplaySettingsExA ( devices [ device ] . name , mode , & dm2 , 0 ) ; + + mode )
{
if ( dm2 . dmBitsPerPel = = depths [ test ]
& & dm2 . dmPelsWidth ! = dm . dmPelsWidth & & dm2 . dmPelsHeight ! = dm . dmPelsHeight )
break ;
}
if ( dm2 . dmBitsPerPel ! = depths [ test ]
| | dm2 . dmPelsWidth = = dm . dmPelsWidth | | dm2 . dmPelsHeight = = dm . dmPelsHeight )
{
skip ( " Failed to find the second mode for %s. \n " , devices [ device ] . name ) ;
continue ;
}
/* Find the third resolution */
memset ( & dm3 , 0 , sizeof ( dm3 ) ) ;
dm3 . dmSize = sizeof ( dm3 ) ;
for ( mode = 0 ; EnumDisplaySettingsExA ( devices [ device ] . name , mode , & dm3 , 0 ) ; + + mode )
{
if ( dm3 . dmBitsPerPel = = depths [ test ]
& & dm3 . dmPelsWidth ! = dm . dmPelsWidth & & dm3 . dmPelsHeight ! = dm . dmPelsHeight
& & dm3 . dmPelsWidth ! = dm2 . dmPelsWidth & & dm3 . dmPelsHeight ! = dm2 . dmPelsHeight )
break ;
}
if ( dm3 . dmBitsPerPel ! = depths [ test ]
| | dm3 . dmPelsWidth = = dm . dmPelsWidth | | dm3 . dmPelsHeight = = dm . dmPelsHeight
| | dm3 . dmPelsWidth = = dm2 . dmPelsWidth | | dm3 . dmPelsHeight = = dm2 . dmPelsHeight )
{
skip ( " Failed to find the third mode for %s. \n " , devices [ device ] . name ) ;
continue ;
}
/* Change the current mode to the third mode first */
res = ChangeDisplaySettingsExA ( devices [ device ] . name , & dm3 , NULL , CDS_RESET , NULL ) ;
ok ( res = = DISP_CHANGE_SUCCESSFUL
| | broken ( res = = DISP_CHANGE_FAILED ) , /* Win8 TestBots */
" ChangeDisplaySettingsExA %s returned unexpected %d. \n " , devices [ device ] . name , res ) ;
if ( res ! = DISP_CHANGE_SUCCESSFUL )
{
win_skip ( " Failed to change display mode for %s. \n " , devices [ device ] . name ) ;
continue ;
}
flush_events ( ) ;
2020-11-13 08:53:09 +01:00
expect_dm ( & dm3 , devices [ device ] . name , test ) ;
2020-10-27 07:59:34 +01:00
/* Change the registry mode to the second mode */
res = ChangeDisplaySettingsExA ( devices [ device ] . name , & dm2 , NULL , CDS_UPDATEREGISTRY | CDS_NORESET , NULL ) ;
ok ( res = = DISP_CHANGE_SUCCESSFUL
| | broken ( res = = DISP_CHANGE_BADFLAGS ) , /* Win10 32bit */
" ChangeDisplaySettingsExA %s returned unexpected %d. \n " , devices [ device ] . name , res ) ;
/* Change to a mode with depth set but with zero width and height */
memset ( & dm , 0 , sizeof ( dm ) ) ;
dm . dmSize = sizeof ( dm ) ;
dm . dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT ;
dm . dmBitsPerPel = depths [ test ] ;
res = ChangeDisplaySettingsExA ( devices [ device ] . name , & dm , NULL , CDS_RESET , NULL ) ;
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA %s returned unexpected %d. \n " ,
devices [ device ] . name , res ) ;
flush_events ( ) ;
dd . cb = sizeof ( dd ) ;
res = EnumDisplayDevicesA ( NULL , devices [ device ] . index , & dd , 0 ) ;
ok ( res , " EnumDisplayDevicesA %s failed, error %#x. \n " , devices [ device ] . name , GetLastError ( ) ) ;
2020-10-27 08:00:47 +01:00
ok ( dd . StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP , " Expect %s attached. \n " ,
devices [ device ] . name ) ;
2020-10-27 07:59:34 +01:00
memset ( & dm , 0 , sizeof ( dm ) ) ;
dm . dmSize = sizeof ( dm ) ;
res = EnumDisplaySettingsA ( devices [ device ] . name , ENUM_CURRENT_SETTINGS , & dm ) ;
ok ( res , " Device %s EnumDisplaySettingsA failed, error %#x. \n " , devices [ device ] . name , GetLastError ( ) ) ;
ok ( dm . dmBitsPerPel = = depths [ test ] , " Device %s expect dmBitsPerPel %u, got %u. \n " ,
devices [ device ] . name , depths [ test ] , dm . dmBitsPerPel ) ;
/* 2008 resets to the resolution in the registry. Newer versions of Windows doesn't
* change the current resolution */
ok ( dm . dmPelsWidth = = dm3 . dmPelsWidth | | broken ( dm . dmPelsWidth = = dm2 . dmPelsWidth ) ,
" Device %s expect dmPelsWidth %u, got %u. \n " ,
devices [ device ] . name , dm3 . dmPelsWidth , dm . dmPelsWidth ) ;
ok ( dm . dmPelsHeight = = dm3 . dmPelsHeight | | broken ( dm . dmPelsHeight = = dm2 . dmPelsHeight ) ,
" Device %s expect dmPelsHeight %u, got %u. \n " ,
devices [ device ] . name , dm3 . dmPelsHeight , dm . dmPelsHeight ) ;
}
}
2020-02-04 08:54:34 +01:00
/* 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 ( ) ) ;
2020-07-27 10:01:04 +02:00
ok ( ! ( dd . StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP ) , " Expect device %s detached. \n " , devices [ device ] . name ) ;
2020-02-04 08:54:34 +01:00
count = GetSystemMetrics ( SM_CMONITORS ) ;
2020-07-27 10:01:04 +02:00
ok ( count = = old_count - 1 , " Expect monitor count %d, got %d \n " , old_count - 1 , count ) ;
2020-02-04 08:54:34 +01:00
}
2021-05-17 09:20:21 +02:00
/* Test changing each adapter to different width, height, frequency and depth */
2020-02-04 08:54:34 +01:00
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 )
{
2021-05-17 09:20:21 +02:00
if ( mode = = 0 )
{
dm2 = dm ;
}
else
{
found = FALSE ;
if ( dm2 . dmPelsWidth & & dm . dmPelsWidth ! = dm2 . dmPelsWidth )
{
dm2 . dmPelsWidth = 0 ;
found = TRUE ;
}
if ( dm2 . dmPelsHeight & & dm . dmPelsHeight ! = dm2 . dmPelsHeight )
{
dm2 . dmPelsHeight = 0 ;
found = TRUE ;
}
if ( dm2 . dmDisplayFrequency & & dm . dmDisplayFrequency ! = dm2 . dmDisplayFrequency )
{
dm2 . dmDisplayFrequency = 0 ;
found = TRUE ;
}
if ( dm2 . dmBitsPerPel & & dm . dmBitsPerPel ! = dm2 . dmBitsPerPel )
{
dm2 . dmBitsPerPel = 0 ;
found = TRUE ;
}
if ( ! dm2 . dmPelsWidth & & ! dm2 . dmPelsHeight & & ! dm2 . dmDisplayFrequency
& & ! dm2 . dmBitsPerPel )
break ;
if ( ! found )
continue ;
}
2020-02-04 08:54:34 +01:00
dm . dmPosition = position ;
dm . dmFields | = DM_POSITION ;
/* Reattach detached non-primary adapters, otherwise ChangeDisplaySettingsExA with only CDS_RESET fails */
if ( mode = = 0 & & device )
{
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 ) ;
}
2021-02-22 14:38:01 +01:00
else
{
res = ChangeDisplaySettingsExA ( devices [ device ] . name , & dm , NULL , CDS_RESET , NULL ) ;
}
2020-02-04 08:54:34 +01:00
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 ;
}
2020-05-05 14:30:07 +02:00
flush_events ( ) ;
2020-11-13 08:53:09 +01:00
expect_dm ( & dm , devices [ device ] . name , mode ) ;
2020-02-04 08:54:34 +01:00
}
/* 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 ) ;
2020-05-05 14:30:07 +02:00
ok ( res , " EnumDisplaySettingsA %s failed, error %#x \n " , devices [ device ] . name , GetLastError ( ) ) ;
2020-02-04 08:54:34 +01:00
position . x = dm . dmPosition . x + dm . dmPelsWidth ;
}
/* Test changing modes by saving settings to the registry first */
for ( device = 0 ; device < device_count ; + + device )
{
2020-08-25 09:11:56 +02:00
/* Place adapter to the right */
if ( device = = 0 )
{
position . x = 0 ;
position . y = 0 ;
}
else
{
memset ( & dm , 0 , sizeof ( dm ) ) ;
dm . dmSize = sizeof ( dm ) ;
res = EnumDisplaySettingsA ( devices [ device - 1 ] . name , ENUM_CURRENT_SETTINGS , & dm ) ;
ok ( res , " EnumDisplaySettingsA %s failed, error %#x. \n " , devices [ device - 1 ] . name , GetLastError ( ) ) ;
position . x = dm . dmPosition . x + dm . dmPelsWidth ;
}
2020-02-04 08:54:34 +01:00
memset ( & dm , 0 , sizeof ( dm ) ) ;
dm . dmSize = sizeof ( dm ) ;
res = EnumDisplaySettingsA ( devices [ device ] . name , ENUM_CURRENT_SETTINGS , & dm ) ;
2020-05-05 14:30:07 +02:00
ok ( res , " EnumDisplaySettingsA %s failed, error %#x \n " , devices [ device ] . name , GetLastError ( ) ) ;
2020-08-25 09:11:56 +02:00
dm3 = dm ;
2020-02-04 08:54:34 +01:00
/* 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 )
{
2020-09-15 12:34:43 +02:00
/* Use the same color depth because the win2008 TestBots are unable to change it */
if ( dm2 . dmPelsWidth ! = dm . dmPelsWidth & & dm2 . dmPelsHeight ! = dm . dmPelsHeight & &
dm2 . dmBitsPerPel = = dm . dmBitsPerPel )
2020-02-04 08:54:34 +01:00
break ;
}
2020-09-15 12:34:43 +02:00
ok ( dm2 . dmPelsWidth ! = dm . dmPelsWidth & & dm2 . dmPelsHeight ! = dm . dmPelsHeight & &
dm2 . dmBitsPerPel = = dm . dmBitsPerPel , " Failed to find a different mode. \n " ) ;
2020-02-04 08:54:34 +01:00
2020-08-25 09:11:56 +02:00
/* Test normal operation */
2020-09-15 12:34:43 +02:00
dm = dm2 ;
dm . dmFields | = DM_POSITION ;
2020-08-25 09:11:56 +02:00
dm . dmPosition = position ;
2020-02-04 08:54:34 +01:00
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 ;
}
2020-05-05 14:30:07 +02:00
flush_events ( ) ;
2020-11-13 08:53:09 +01:00
expect_dm ( & dm , devices [ device ] . name , 0 ) ;
2020-08-25 09:11:56 +02:00
/* Test specifying only position, width and height */
memset ( & dm , 0 , sizeof ( dm ) ) ;
dm . dmSize = sizeof ( dm ) ;
dm . dmFields = DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT ;
dm . dmPosition = position ;
dm . dmPelsWidth = dm3 . dmPelsWidth ;
dm . dmPelsHeight = dm3 . dmPelsHeight ;
res = ChangeDisplaySettingsExA ( devices [ device ] . name , & dm , NULL , CDS_UPDATEREGISTRY | CDS_NORESET , NULL ) ;
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA %s returned %d. \n " , devices [ device ] . name , res ) ;
res = EnumDisplaySettingsA ( devices [ device ] . name , ENUM_REGISTRY_SETTINGS , & dm ) ;
/* Win10 either returns failure here or retrieves outdated display settings until they're applied */
if ( res )
{
ok ( ( dm . dmFields & registry_fields ) = = registry_fields , " Got unexpected dmFields %#x. \n " , dm . dmFields ) ;
ok ( dm . dmPosition . x = = position . x , " Expected dmPosition.x %d, got %d. \n " , position . x , dm . dmPosition . x ) ;
ok ( dm . dmPosition . y = = position . y , " Expected dmPosition.y %d, got %d. \n " , position . y , dm . dmPosition . y ) ;
ok ( dm . dmPelsWidth = = dm3 . dmPelsWidth | | broken ( dm . dmPelsWidth = = dm2 . dmPelsWidth ) , /* Win10 */
" Expected dmPelsWidth %u, got %u. \n " , dm3 . dmPelsWidth , dm . dmPelsWidth ) ;
ok ( dm . dmPelsHeight = = dm3 . dmPelsHeight | | broken ( dm . dmPelsHeight = = dm2 . dmPelsHeight ) , /* Win10 */
" Expected dmPelsHeight %u, got %u. \n " , dm3 . dmPelsHeight , dm . dmPelsHeight ) ;
2020-08-25 09:12:09 +02:00
ok ( dm . dmBitsPerPel , " Expected dmBitsPerPel not zero. \n " ) ;
ok ( dm . dmDisplayFrequency , " Expected dmDisplayFrequency not zero. \n " ) ;
2020-08-25 09:11:56 +02:00
}
else
{
win_skip ( " EnumDisplaySettingsA %s failed, error %#x. \n " , devices [ device ] . name , GetLastError ( ) ) ;
}
res = ChangeDisplaySettingsExA ( devices [ device ] . name , NULL , NULL , 0 , NULL ) ;
2020-08-25 09:12:09 +02:00
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA %s returned %d. \n " , devices [ device ] . name , res ) ;
2020-08-25 09:11:56 +02:00
flush_events ( ) ;
res = EnumDisplaySettingsA ( devices [ device ] . name , ENUM_REGISTRY_SETTINGS , & dm ) ;
ok ( res , " EnumDisplaySettingsA %s failed, error %#x. \n " , devices [ device ] . name , GetLastError ( ) ) ;
ok ( ( dm . dmFields & registry_fields ) = = registry_fields , " Got unexpected dmFields %#x. \n " , dm . dmFields ) ;
ok ( dm . dmPosition . x = = position . x , " Expected dmPosition.x %d, got %d. \n " , position . x , dm . dmPosition . x ) ;
ok ( dm . dmPosition . y = = position . y , " Expected dmPosition.y %d, got %d. \n " , position . y , dm . dmPosition . y ) ;
ok ( dm . dmPelsWidth = = dm3 . dmPelsWidth , " Expected dmPelsWidth %u, got %u. \n " , dm3 . dmPelsWidth , dm . dmPelsWidth ) ;
ok ( dm . dmPelsHeight = = dm3 . dmPelsHeight , " Expected dmPelsHeight %u, got %u. \n " , dm3 . dmPelsHeight ,
dm . dmPelsHeight ) ;
ok ( dm . dmBitsPerPel , " Expected dmBitsPerPel not zero. \n " ) ;
ok ( dm . dmDisplayFrequency , " Expected dmDisplayFrequency not zero. \n " ) ;
2020-11-13 08:53:09 +01:00
expect_dm ( & dm , devices [ device ] . name , 0 ) ;
2020-02-04 08:54:34 +01:00
}
/* 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 ) ;
2020-05-05 14:30:07 +02:00
ok ( res , " EnumDisplaySettingsA %s failed, error %#x \n " , devices [ 0 ] . name , GetLastError ( ) ) ;
2020-02-04 08:54:34 +01:00
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 ) ;
2020-05-05 14:30:07 +02:00
ok ( res , " EnumDisplaySettingsA %s failed, error %#x \n " , devices [ 1 ] . name , GetLastError ( ) ) ;
2020-02-04 08:54:34 +01:00
}
if ( res )
{
2020-05-05 14:30:19 +02:00
/* The secondary adapter should be to the right of the primary adapter */
2020-07-27 10:00:43 +02:00
ok ( dm2 . dmPosition . x = = dm . dmPosition . x + dm . dmPelsWidth ,
2020-05-05 14:30:19 +02:00
" Expected dm2.dmPosition.x %d, got %d. \n " , dm . dmPosition . x + dm . dmPelsWidth ,
dm2 . dmPosition . x ) ;
ok ( dm2 . dmPosition . y = = dm . dmPosition . y , " Expected dm2.dmPosition.y %d, got %d. \n " ,
dm . dmPosition . y , dm2 . dmPosition . y ) ;
2020-02-04 08:54:34 +01:00
/* Test position conflict */
2020-05-05 14:30:19 +02:00
dm2 . dmPosition . x = dm . dmPosition . x - dm2 . dmPelsWidth + 1 ;
2020-02-04 08:54:34 +01:00
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 ) ;
2020-05-05 14:30:19 +02:00
/* Position is changed and automatically moved */
2020-02-04 08:54:34 +01:00
memset ( & dm2 , 0 , sizeof ( dm2 ) ) ;
dm2 . dmSize = sizeof ( dm2 ) ;
res = EnumDisplaySettingsA ( devices [ 1 ] . name , ENUM_CURRENT_SETTINGS , & dm2 ) ;
2020-05-05 14:30:07 +02:00
ok ( res , " EnumDisplaySettingsA %s failed, error %#x \n " , devices [ 1 ] . name , GetLastError ( ) ) ;
2020-07-27 10:00:43 +02:00
ok ( dm2 . dmPosition . x = = dm . dmPosition . x - dm2 . dmPelsWidth ,
2020-05-05 14:30:19 +02:00
" Expected dmPosition.x %d, got %d. \n " , dm . dmPosition . x - dm2 . dmPelsWidth ,
dm2 . dmPosition . x ) ;
2020-02-04 08:54:34 +01:00
/* Test position with extra space. The extra space will be removed */
2020-05-05 14:30:19 +02:00
dm2 . dmPosition . x = dm . dmPosition . x + dm . dmPelsWidth + 1 ;
2020-02-04 08:54:34 +01:00
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 ) ;
2020-05-05 14:30:19 +02:00
dm2 . dmPosition . x = dm . dmPosition . x + dm . dmPelsWidth ;
2020-11-13 08:53:09 +01:00
expect_dm ( & dm2 , devices [ 1 ] . name , 0 ) ;
2020-02-04 08:54:34 +01:00
/* Test placing the secondary adapter to all sides of the primary adapter */
2020-07-21 08:50:05 +02:00
for ( test = 0 ; test < 8 ; + + test )
2020-02-04 08:54:34 +01:00
{
2020-07-21 08:50:05 +02:00
switch ( test )
2020-02-04 08:54:34 +01:00
{
2020-07-21 08:50:05 +02:00
/* Bottom side with x offset */
2020-02-04 08:54:34 +01:00
case 0 :
2020-07-21 08:50:05 +02:00
dm2 . dmPosition . x = dm . dmPosition . x + dm . dmPelsWidth / 2 ;
2020-02-04 08:54:34 +01:00
dm2 . dmPosition . y = dm . dmPosition . y + dm . dmPelsHeight ;
break ;
2020-07-21 08:50:05 +02:00
/* Left side with y offset */
2020-02-04 08:54:34 +01:00
case 1 :
dm2 . dmPosition . x = dm . dmPosition . x - dm2 . dmPelsWidth ;
2020-07-21 08:50:05 +02:00
dm2 . dmPosition . y = dm . dmPosition . y + dm . dmPelsHeight / 2 ;
2020-02-04 08:54:34 +01:00
break ;
2020-07-21 08:50:05 +02:00
/* Top side with x offset */
2020-02-04 08:54:34 +01:00
case 2 :
2020-07-21 08:50:05 +02:00
dm2 . dmPosition . x = dm . dmPosition . x + dm . dmPelsWidth / 2 ;
2020-02-04 08:54:34 +01:00
dm2 . dmPosition . y = dm . dmPosition . y - dm2 . dmPelsHeight ;
break ;
2020-07-21 08:50:05 +02:00
/* Right side with y offset */
2020-02-04 08:54:34 +01:00
case 3 :
2020-07-21 08:50:05 +02:00
dm2 . dmPosition . x = dm . dmPosition . x + dm . dmPelsWidth ;
dm2 . dmPosition . y = dm . dmPosition . y + dm . dmPelsHeight / 2 ;
break ;
/* Bottom side with the same x */
case 4 :
dm2 . dmPosition . x = dm . dmPosition . x ;
dm2 . dmPosition . y = dm . dmPosition . y + dm . dmPelsHeight ;
break ;
/* Left side with the same y */
case 5 :
dm2 . dmPosition . x = dm . dmPosition . x - dm2 . dmPelsWidth ;
dm2 . dmPosition . y = dm . dmPosition . y ;
break ;
/* Top side with the same x */
case 6 :
dm2 . dmPosition . x = dm . dmPosition . x ;
dm2 . dmPosition . y = dm . dmPosition . y - dm2 . dmPelsHeight ;
break ;
/* Right side with the same y */
case 7 :
2020-02-04 08:54:34 +01:00
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 ) ;
2020-07-21 08:50:05 +02:00
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA %s test %d returned unexpected %d \n " ,
devices [ 1 ] . name , test , res ) ;
2020-02-04 08:54:34 +01:00
if ( res ! = DISP_CHANGE_SUCCESSFUL )
{
2020-07-21 08:50:05 +02:00
win_skip ( " ChangeDisplaySettingsExA %s test %d returned unexpected %d. \n " , devices [ 1 ] . name , test , res ) ;
2020-02-04 08:54:34 +01:00
continue ;
}
2020-05-05 14:30:07 +02:00
flush_events ( ) ;
2020-11-13 08:53:09 +01:00
expect_dm ( & dm2 , devices [ 1 ] . name , test ) ;
2020-02-04 08:54:34 +01:00
}
/* 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 ) ;
2020-05-05 14:30:07 +02:00
ok ( res , " EnumDisplaySettingsA %s failed, error %#x \n " , devices [ 1 ] . name , GetLastError ( ) ) ;
2020-07-27 10:00:43 +02:00
ok ( dm2 . dmPosition . x = = dm . dmPelsWidth , " Expect dmPosition.x %d, got %d \n " ,
2020-02-04 08:54:34 +01:00
dm . dmPelsWidth , dm2 . dmPosition . x ) ;
}
else
{
win_skip ( " EnumDisplaySettingsA failed \n " ) ;
}
}
2020-09-22 09:01:35 +02:00
/* Test changing each adapter to every supported display orientation */
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 ) ;
ok ( res , " EnumDisplaySettingsA %s failed, error %#x. \n " , devices [ device ] . name , GetLastError ( ) ) ;
memset ( & dm2 , 0 , sizeof ( dm2 ) ) ;
dm2 . dmSize = sizeof ( dm2 ) ;
for ( mode = 0 ; EnumDisplaySettingsExA ( devices [ device ] . name , mode , & dm2 , EDS_ROTATEDMODE ) ; + + mode )
{
if ( dm2 . dmBitsPerPel ! = dm . dmBitsPerPel | | dm2 . dmDisplayFrequency ! = dm . dmDisplayFrequency )
continue ;
if ( ( dm2 . dmDisplayOrientation = = DMDO_DEFAULT | | dm2 . dmDisplayOrientation = = DMDO_180 )
& & ( dm2 . dmPelsWidth ! = dm . dmPelsWidth | | dm2 . dmPelsHeight ! = dm . dmPelsHeight ) )
continue ;
if ( ( dm2 . dmDisplayOrientation = = DMDO_90 | | dm2 . dmDisplayOrientation = = DMDO_270 )
& & ( dm2 . dmPelsWidth ! = dm . dmPelsHeight | | dm2 . dmPelsHeight ! = dm . dmPelsWidth ) )
continue ;
res = ChangeDisplaySettingsExA ( devices [ device ] . name , & dm2 , NULL , CDS_RESET , NULL ) ;
if ( res ! = DISP_CHANGE_SUCCESSFUL )
{
win_skip ( " Failed to change %s to mode %d. \n " , devices [ device ] . name , mode ) ;
continue ;
}
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA %s mode %d returned unexpected %d. \n " ,
devices [ device ] . name , mode , res ) ;
flush_events ( ) ;
2020-11-13 08:53:09 +01:00
expect_dm ( & dm2 , devices [ device ] . name , mode ) ;
2020-09-22 09:01:35 +02:00
/* EnumDisplaySettingsEx without EDS_ROTATEDMODE reports modes with current orientation */
memset ( & dm3 , 0 , sizeof ( dm3 ) ) ;
dm3 . dmSize = sizeof ( dm3 ) ;
for ( i = 0 ; EnumDisplaySettingsExA ( devices [ device ] . name , i , & dm3 , 0 ) ; + + i )
{
ok ( dm3 . dmDisplayOrientation = = dm2 . dmDisplayOrientation ,
" Expected %s display mode %d orientation %d, got %d. \n " ,
devices [ device ] . name , i , dm2 . dmDisplayOrientation , dm3 . dmDisplayOrientation ) ;
}
ok ( i > 0 , " Expected at least one display mode found. \n " ) ;
if ( device = = 0 )
{
ok ( GetSystemMetrics ( SM_CXSCREEN ) = = dm2 . dmPelsWidth , " Expected %d, got %d. \n " ,
dm2 . dmPelsWidth , GetSystemMetrics ( SM_CXSCREEN ) ) ;
ok ( GetSystemMetrics ( SM_CYSCREEN ) = = dm2 . dmPelsHeight , " Expected %d, got %d. \n " ,
dm2 . dmPelsHeight , GetSystemMetrics ( SM_CYSCREEN ) ) ;
}
if ( device_count = = 1 )
{
ok ( GetSystemMetrics ( SM_CXVIRTUALSCREEN ) = = dm2 . dmPelsWidth , " Expected %d, got %d. \n " ,
dm2 . dmPelsWidth , GetSystemMetrics ( SM_CXVIRTUALSCREEN ) ) ;
ok ( GetSystemMetrics ( SM_CYVIRTUALSCREEN ) = = dm2 . dmPelsHeight , " Expected %d, got %d. \n " ,
dm2 . dmPelsHeight , GetSystemMetrics ( SM_CYVIRTUALSCREEN ) ) ;
}
}
ok ( mode > 0 , " Expected at least one display mode found. \n " ) ;
}
2020-02-04 08:54:34 +01:00
/* 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 )
2020-11-13 08:53:09 +01:00
expect_dm ( & devices [ device ] . original_mode , devices [ device ] . name , 0 ) ;
2020-02-04 08:54:34 +01:00
heap_free ( devices ) ;
2006-07-26 07:31:22 +02:00
}
2006-10-23 18:03:16 +02:00
static void test_monitors ( void )
{
2014-01-27 22:16:38 +01:00
HMONITOR monitor , primary , nearest ;
2006-10-23 18:03:16 +02:00
POINT pt ;
2014-01-27 22:16:38 +01:00
RECT rc ;
2014-04-18 19:07:55 +02:00
MONITORINFO mi ;
2014-04-23 17:35:43 +02:00
MONITORINFOEXA miexa ;
MONITORINFOEXW miexw ;
2014-04-18 19:07:55 +02:00
BOOL ret ;
DWORD i ;
static const struct
{
DWORD cbSize ;
BOOL ret ;
} testdatami [ ] = {
{ 0 , FALSE } ,
{ sizeof ( MONITORINFO ) + 1 , FALSE } ,
{ sizeof ( MONITORINFO ) - 1 , FALSE } ,
{ sizeof ( MONITORINFO ) , TRUE } ,
{ - 1 , FALSE } ,
{ 0xdeadbeef , FALSE } ,
} ,
2014-04-23 17:35:43 +02:00
testdatamiexa [ ] = {
2014-04-18 19:07:55 +02:00
{ 0 , FALSE } ,
{ sizeof ( MONITORINFOEXA ) + 1 , FALSE } ,
{ sizeof ( MONITORINFOEXA ) - 1 , FALSE } ,
{ sizeof ( MONITORINFOEXA ) , TRUE } ,
{ - 1 , FALSE } ,
{ 0xdeadbeef , FALSE } ,
2014-04-23 17:35:43 +02:00
} ,
testdatamiexw [ ] = {
{ 0 , FALSE } ,
{ sizeof ( MONITORINFOEXW ) + 1 , FALSE } ,
{ sizeof ( MONITORINFOEXW ) - 1 , FALSE } ,
{ sizeof ( MONITORINFOEXW ) , TRUE } ,
{ - 1 , FALSE } ,
{ 0xdeadbeef , FALSE } ,
2014-04-18 19:07:55 +02:00
} ;
2006-10-23 18:03:16 +02:00
pt . x = pt . y = 0 ;
2019-12-03 15:37:50 +01:00
primary = MonitorFromPoint ( pt , MONITOR_DEFAULTTOPRIMARY ) ;
2006-10-23 18:03:16 +02:00
ok ( primary ! = 0 , " couldn't get primary monitor \n " ) ;
2019-12-03 15:37:50 +01:00
monitor = MonitorFromWindow ( 0 , MONITOR_DEFAULTTONULL ) ;
2006-10-23 18:03:16 +02:00
ok ( ! monitor , " got %p, should not get a monitor for an invalid window \n " , monitor ) ;
2019-12-03 15:37:50 +01:00
monitor = MonitorFromWindow ( 0 , MONITOR_DEFAULTTOPRIMARY ) ;
2006-10-23 18:03:16 +02:00
ok ( monitor = = primary , " got %p, should get primary %p for MONITOR_DEFAULTTOPRIMARY \n " , monitor , primary ) ;
2019-12-03 15:37:50 +01:00
monitor = MonitorFromWindow ( 0 , MONITOR_DEFAULTTONEAREST ) ;
2006-10-23 18:03:16 +02:00
ok ( monitor = = primary , " got %p, should get primary %p for MONITOR_DEFAULTTONEAREST \n " , monitor , primary ) ;
2014-01-27 22:16:38 +01:00
SetRect ( & rc , 0 , 0 , 1 , 1 ) ;
2019-12-03 15:37:50 +01:00
monitor = MonitorFromRect ( & rc , MONITOR_DEFAULTTONULL ) ;
2014-01-27 22:16:38 +01:00
ok ( monitor = = primary , " got %p, should get primary %p \n " , monitor , primary ) ;
2019-12-03 15:37:50 +01:00
monitor = MonitorFromRect ( & rc , MONITOR_DEFAULTTOPRIMARY ) ;
2014-01-27 22:16:38 +01:00
ok ( monitor = = primary , " got %p, should get primary %p \n " , monitor , primary ) ;
2019-12-03 15:37:50 +01:00
monitor = MonitorFromRect ( & rc , MONITOR_DEFAULTTONEAREST ) ;
2014-01-27 22:16:38 +01:00
ok ( monitor = = primary , " got %p, should get primary %p \n " , monitor , primary ) ;
/* Empty rect at 0,0 is considered inside the primary monitor */
SetRect ( & rc , 0 , 0 , - 1 , - 1 ) ;
2019-12-03 15:37:50 +01:00
monitor = MonitorFromRect ( & rc , MONITOR_DEFAULTTONULL ) ;
2014-01-27 22:16:38 +01:00
ok ( monitor = = primary , " got %p, should get primary %p \n " , monitor , primary ) ;
/* Even if there is a monitor left of the primary, the primary will have the most overlapping area */
SetRect ( & rc , - 1 , 0 , 2 , 1 ) ;
2019-12-03 15:37:50 +01:00
monitor = MonitorFromRect ( & rc , MONITOR_DEFAULTTONULL ) ;
2014-01-27 22:16:38 +01:00
ok ( monitor = = primary , " got %p, should get primary %p \n " , monitor , primary ) ;
/* But the width of the rect doesn't matter if it's empty. */
SetRect ( & rc , - 1 , 0 , 2 , - 1 ) ;
2019-12-03 15:37:50 +01:00
monitor = MonitorFromRect ( & rc , MONITOR_DEFAULTTONULL ) ;
2014-01-27 22:16:38 +01:00
ok ( monitor ! = primary , " got primary %p \n " , monitor ) ;
/* Search for a monitor that has no others equally near to (left, top-1) */
SetRect ( & rc , - 1 , - 2 , 2 , 0 ) ;
2019-12-03 15:37:50 +01:00
monitor = MonitorFromRect ( & rc , MONITOR_DEFAULTTONULL ) ;
2014-01-27 22:16:38 +01:00
nearest = primary ;
while ( monitor ! = NULL )
{
ok ( monitor ! = primary , " got primary %p \n " , monitor ) ;
nearest = monitor ;
mi . cbSize = sizeof ( mi ) ;
2019-12-03 15:37:50 +01:00
ret = GetMonitorInfoA ( monitor , & mi ) ;
2014-01-27 22:16:38 +01:00
ok ( ret , " GetMonitorInfo failed \n " ) ;
SetRect ( & rc , mi . rcMonitor . left - 1 , mi . rcMonitor . top - 2 , mi . rcMonitor . left + 2 , mi . rcMonitor . top ) ;
2019-12-03 15:37:50 +01:00
monitor = MonitorFromRect ( & rc , MONITOR_DEFAULTTONULL ) ;
2014-01-27 22:16:38 +01:00
}
2014-04-18 19:07:55 +02:00
/* tests for cbSize in MONITORINFO */
2019-12-03 15:37:50 +01:00
monitor = MonitorFromWindow ( 0 , MONITOR_DEFAULTTOPRIMARY ) ;
2018-06-28 18:17:01 +02:00
for ( i = 0 ; i < ARRAY_SIZE ( testdatami ) ; i + + )
2014-04-18 19:07:55 +02:00
{
memset ( & mi , 0 , sizeof ( mi ) ) ;
mi . cbSize = testdatami [ i ] . cbSize ;
2019-12-03 15:37:50 +01:00
ret = GetMonitorInfoA ( monitor , & mi ) ;
2014-04-18 19:07:55 +02:00
ok ( ret = = testdatami [ i ] . ret , " GetMonitorInfo returned wrong value \n " ) ;
if ( ret )
ok ( ( mi . dwFlags & MONITORINFOF_PRIMARY ) , " MONITORINFOF_PRIMARY flag isn't set \n " ) ;
else
ok ( ! ( mi . dwFlags & MONITORINFOF_PRIMARY ) , " MONITORINFOF_PRIMARY flag is set \n " ) ;
2014-04-23 17:35:43 +02:00
memset ( & miexw , 0 , sizeof ( miexw ) ) ;
miexw . cbSize = testdatamiexw [ i ] . cbSize ;
2019-12-03 15:37:50 +01:00
ret = GetMonitorInfoW ( monitor , ( LPMONITORINFO ) & miexw ) ;
2014-04-23 17:35:43 +02:00
ok ( ret = = testdatamiexw [ i ] . ret , " GetMonitorInfo returned wrong value \n " ) ;
if ( ret )
ok ( ( miexw . dwFlags & MONITORINFOF_PRIMARY ) , " MONITORINFOF_PRIMARY flag isn't set \n " ) ;
else
ok ( ! ( miexw . dwFlags & MONITORINFOF_PRIMARY ) , " MONITORINFOF_PRIMARY flag is set \n " ) ;
2014-04-18 19:07:55 +02:00
}
/* tests for cbSize in MONITORINFOEXA */
2018-06-28 18:17:01 +02:00
for ( i = 0 ; i < ARRAY_SIZE ( testdatamiexa ) ; i + + )
2014-04-23 17:35:43 +02:00
{
memset ( & miexa , 0 , sizeof ( miexa ) ) ;
miexa . cbSize = testdatamiexa [ i ] . cbSize ;
2019-12-03 15:37:50 +01:00
ret = GetMonitorInfoA ( monitor , ( LPMONITORINFO ) & miexa ) ;
2014-04-23 17:35:43 +02:00
ok ( ret = = testdatamiexa [ i ] . ret , " GetMonitorInfo returned wrong value \n " ) ;
if ( ret )
ok ( ( miexa . dwFlags & MONITORINFOF_PRIMARY ) , " MONITORINFOF_PRIMARY flag isn't set \n " ) ;
else
ok ( ! ( miexa . dwFlags & MONITORINFOF_PRIMARY ) , " MONITORINFOF_PRIMARY flag is set \n " ) ;
}
/* tests for cbSize in MONITORINFOEXW */
2018-06-28 18:17:01 +02:00
for ( i = 0 ; i < ARRAY_SIZE ( testdatamiexw ) ; i + + )
2014-04-18 19:07:55 +02:00
{
2014-04-23 17:35:43 +02:00
memset ( & miexw , 0 , sizeof ( miexw ) ) ;
miexw . cbSize = testdatamiexw [ i ] . cbSize ;
2019-12-03 15:37:50 +01:00
ret = GetMonitorInfoW ( monitor , ( LPMONITORINFO ) & miexw ) ;
2014-04-23 17:35:43 +02:00
ok ( ret = = testdatamiexw [ i ] . ret , " GetMonitorInfo returned wrong value \n " ) ;
2014-04-18 19:07:55 +02:00
if ( ret )
2014-04-23 17:35:43 +02:00
ok ( ( miexw . dwFlags & MONITORINFOF_PRIMARY ) , " MONITORINFOF_PRIMARY flag isn't set \n " ) ;
2014-04-18 19:07:55 +02:00
else
2014-04-23 17:35:43 +02:00
ok ( ! ( miexw . dwFlags & MONITORINFOF_PRIMARY ) , " MONITORINFOF_PRIMARY flag is set \n " ) ;
2014-04-18 19:07:55 +02:00
}
2014-01-27 22:16:38 +01:00
SetRect ( & rc , rc . left + 1 , rc . top + 1 , rc . left + 2 , rc . top + 2 ) ;
2019-12-03 15:37:50 +01:00
monitor = MonitorFromRect ( & rc , MONITOR_DEFAULTTONULL ) ;
2014-01-27 22:16:38 +01:00
ok ( monitor = = NULL , " got %p \n " , monitor ) ;
2019-12-03 15:37:50 +01:00
monitor = MonitorFromRect ( & rc , MONITOR_DEFAULTTOPRIMARY ) ;
2014-01-27 22:16:38 +01:00
ok ( monitor = = primary , " got %p, should get primary %p \n " , monitor , primary ) ;
2019-12-03 15:37:50 +01:00
monitor = MonitorFromRect ( & rc , MONITOR_DEFAULTTONEAREST ) ;
2014-01-27 22:16:38 +01:00
ok ( monitor = = nearest , " got %p, should get nearest %p \n " , monitor , nearest ) ;
2006-10-23 18:03:16 +02:00
}
2008-08-26 13:40:58 +02:00
static BOOL CALLBACK find_primary_mon ( HMONITOR hmon , HDC hdc , LPRECT rc , LPARAM lp )
{
MONITORINFO mi ;
BOOL ret ;
mi . cbSize = sizeof ( mi ) ;
2019-12-03 15:37:50 +01:00
ret = GetMonitorInfoA ( hmon , & mi ) ;
2008-08-26 13:40:58 +02:00
ok ( ret , " GetMonitorInfo failed \n " ) ;
if ( mi . dwFlags & MONITORINFOF_PRIMARY )
{
* ( HMONITOR * ) lp = hmon ;
return FALSE ;
}
return TRUE ;
}
static void test_work_area ( void )
{
HMONITOR hmon ;
MONITORINFO mi ;
RECT rc_work , rc_normal ;
HWND hwnd ;
WINDOWPLACEMENT wp ;
BOOL ret ;
hmon = 0 ;
2019-12-03 15:37:50 +01:00
ret = EnumDisplayMonitors ( NULL , NULL , find_primary_mon , ( LPARAM ) & hmon ) ;
2008-08-26 13:40:58 +02:00
ok ( ! ret & & hmon ! = 0 , " Failed to find primary monitor \n " ) ;
mi . cbSize = sizeof ( mi ) ;
SetLastError ( 0xdeadbeef ) ;
2019-12-03 15:37:50 +01:00
ret = GetMonitorInfoA ( hmon , & mi ) ;
2008-08-26 13:40:58 +02:00
ok ( ret , " GetMonitorInfo error %u \n " , GetLastError ( ) ) ;
ok ( mi . dwFlags & MONITORINFOF_PRIMARY , " not a primary monitor \n " ) ;
2016-06-16 10:32:02 +02:00
trace ( " primary monitor %s \n " , wine_dbgstr_rect ( & mi . rcMonitor ) ) ;
2008-08-26 13:40:58 +02:00
SetLastError ( 0xdeadbeef ) ;
2013-10-23 07:53:58 +02:00
ret = SystemParametersInfoA ( SPI_GETWORKAREA , 0 , & rc_work , 0 ) ;
2008-08-26 13:40:58 +02:00
ok ( ret , " SystemParametersInfo error %u \n " , GetLastError ( ) ) ;
2016-06-16 10:32:02 +02:00
trace ( " work area %s \n " , wine_dbgstr_rect ( & rc_work ) ) ;
2008-08-26 13:40:58 +02:00
ok ( EqualRect ( & rc_work , & mi . rcWork ) , " work area is different \n " ) ;
2013-10-23 07:53:58 +02:00
hwnd = CreateWindowExA ( 0 , " static " , NULL , WS_OVERLAPPEDWINDOW | WS_VISIBLE , 100 , 100 , 10 , 10 , 0 , 0 , 0 , NULL ) ;
2008-08-26 13:40:58 +02:00
ok ( hwnd ! = 0 , " CreateWindowEx failed \n " ) ;
ret = GetWindowRect ( hwnd , & rc_normal ) ;
ok ( ret , " GetWindowRect failed \n " ) ;
2016-06-16 10:32:02 +02:00
trace ( " normal %s \n " , wine_dbgstr_rect ( & rc_normal ) ) ;
2008-08-26 13:40:58 +02:00
wp . length = sizeof ( wp ) ;
ret = GetWindowPlacement ( hwnd , & wp ) ;
ok ( ret , " GetWindowPlacement failed \n " ) ;
2016-06-16 10:32:02 +02:00
trace ( " min: %d,%d max %d,%d normal %s \n " , wp . ptMinPosition . x , wp . ptMinPosition . y ,
wp . ptMaxPosition . x , wp . ptMaxPosition . y , wine_dbgstr_rect ( & wp . rcNormalPosition ) ) ;
2008-09-11 06:38:21 +02:00
OffsetRect ( & wp . rcNormalPosition , rc_work . left , rc_work . top ) ;
2016-02-11 03:26:32 +01:00
todo_wine_if ( mi . rcMonitor . left ! = mi . rcWork . left | |
2009-01-25 17:28:39 +01:00
mi . rcMonitor . top ! = mi . rcWork . top ) /* FIXME: remove once Wine is fixed */
2016-02-11 03:26:32 +01:00
{
2008-08-26 13:40:58 +02:00
ok ( EqualRect ( & rc_normal , & wp . rcNormalPosition ) , " normal pos is different \n " ) ;
2016-02-11 03:26:32 +01:00
}
2008-08-26 13:40:58 +02:00
2013-10-23 07:53:58 +02:00
SetWindowLongA ( hwnd , GWL_EXSTYLE , WS_EX_TOOLWINDOW ) ;
2008-08-26 13:40:58 +02:00
wp . length = sizeof ( wp ) ;
ret = GetWindowPlacement ( hwnd , & wp ) ;
ok ( ret , " GetWindowPlacement failed \n " ) ;
2016-06-16 10:32:02 +02:00
trace ( " min: %d,%d max %d,%d normal %s \n " , wp . ptMinPosition . x , wp . ptMinPosition . y ,
wp . ptMaxPosition . x , wp . ptMaxPosition . y , wine_dbgstr_rect ( & wp . rcNormalPosition ) ) ;
2008-08-26 13:40:58 +02:00
ok ( EqualRect ( & rc_normal , & wp . rcNormalPosition ) , " normal pos is different \n " ) ;
DestroyWindow ( hwnd ) ;
}
2005-09-28 12:17:13 +02:00
2020-05-06 19:17:29 +02:00
static void test_GetDisplayConfigBufferSizes ( void )
2015-10-23 20:40:50 +02:00
{
UINT32 paths , modes ;
LONG ret ;
ret = pGetDisplayConfigBufferSizes ( QDC_ALL_PATHS , NULL , NULL ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
paths = 100 ;
ret = pGetDisplayConfigBufferSizes ( QDC_ALL_PATHS , & paths , NULL ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
ok ( paths = = 100 , " got %u \n " , paths ) ;
modes = 100 ;
ret = pGetDisplayConfigBufferSizes ( QDC_ALL_PATHS , NULL , & modes ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
ok ( modes = = 100 , " got %u \n " , modes ) ;
ret = pGetDisplayConfigBufferSizes ( 0 , NULL , NULL ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
paths = 100 ;
ret = pGetDisplayConfigBufferSizes ( 0 , & paths , NULL ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
ok ( paths = = 100 , " got %u \n " , paths ) ;
modes = 100 ;
ret = pGetDisplayConfigBufferSizes ( 0 , NULL , & modes ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
ok ( modes = = 100 , " got %u \n " , modes ) ;
2020-06-30 06:55:22 +02:00
/* Flag validation on Windows is driver-dependent */
2015-10-23 20:40:50 +02:00
paths = modes = 100 ;
ret = pGetDisplayConfigBufferSizes ( 0 , & paths , & modes ) ;
ok ( ret = = ERROR_INVALID_PARAMETER | | ret = = ERROR_NOT_SUPPORTED , " got %d \n " , ret ) ;
2018-09-18 20:19:10 +02:00
ok ( ( modes = = 0 | | modes = = 100 ) & & paths = = 0 , " got %u, %u \n " , modes , paths ) ;
2020-06-30 06:55:22 +02:00
paths = modes = 100 ;
ret = pGetDisplayConfigBufferSizes ( 0xFF , & paths , & modes ) ;
ok ( ret = = ERROR_INVALID_PARAMETER | | ret = = ERROR_NOT_SUPPORTED , " got %d \n " , ret ) ;
ok ( ( modes = = 0 | | modes = = 100 ) & & paths = = 0 , " got %u, %u \n " , modes , paths ) ;
/* Test success */
paths = modes = 0 ;
ret = pGetDisplayConfigBufferSizes ( QDC_ALL_PATHS , & paths , & modes ) ;
if ( ! ret )
ok ( paths > 0 & & modes > 0 , " got %u, %u \n " , paths , modes ) ;
else
ok ( ret = = ERROR_NOT_SUPPORTED , " got %d \n " , ret ) ;
paths = modes = 0 ;
ret = pGetDisplayConfigBufferSizes ( QDC_ONLY_ACTIVE_PATHS , & paths , & modes ) ;
if ( ! ret )
ok ( paths > 0 & & modes > 0 , " got %u, %u \n " , paths , modes ) ;
else
ok ( ret = = ERROR_NOT_SUPPORTED , " got %d \n " , ret ) ;
paths = modes = 0 ;
ret = pGetDisplayConfigBufferSizes ( QDC_DATABASE_CURRENT , & paths , & modes ) ;
if ( ! ret )
ok ( paths > 0 & & modes > 0 , " got %u, %u \n " , paths , modes ) ;
else
ok ( ret = = ERROR_NOT_SUPPORTED , " got %d \n " , ret ) ;
2015-10-23 20:40:50 +02:00
}
2020-05-05 14:30:30 +02:00
static BOOL CALLBACK test_EnumDisplayMonitors_normal_cb ( HMONITOR monitor , HDC hdc , LPRECT rect ,
LPARAM lparam )
{
MONITORINFO mi ;
LONG ret ;
mi . cbSize = sizeof ( mi ) ;
ret = GetMonitorInfoA ( monitor , & mi ) ;
ok ( ret , " GetMonitorInfoA failed, error %#x. \n " , GetLastError ( ) ) ;
ok ( EqualRect ( rect , & mi . rcMonitor ) , " Expected rect %s, got %s. \n " ,
wine_dbgstr_rect ( & mi . rcMonitor ) , wine_dbgstr_rect ( rect ) ) ;
return TRUE ;
}
static BOOL CALLBACK test_EnumDisplayMonitors_return_false_cb ( HMONITOR monitor , HDC hdc ,
LPRECT rect , LPARAM lparam )
{
return FALSE ;
}
static BOOL CALLBACK test_EnumDisplayMonitors_invalid_handle_cb ( HMONITOR monitor , HDC hdc ,
LPRECT rect , LPARAM lparam )
{
MONITORINFOEXA mi , mi2 ;
DEVMODEA old_dm , dm ;
2020-07-21 08:49:49 +02:00
DWORD error ;
2020-05-05 14:30:30 +02:00
INT count ;
LONG ret ;
mi . cbSize = sizeof ( mi ) ;
ret = GetMonitorInfoA ( monitor , ( MONITORINFO * ) & mi ) ;
ok ( ret , " GetMonitorInfoA failed, error %#x. \n " , GetLastError ( ) ) ;
/* Test that monitor handle is invalid after the monitor is detached */
if ( ! ( mi . dwFlags & MONITORINFOF_PRIMARY ) )
{
count = GetSystemMetrics ( SM_CMONITORS ) ;
/* Save current display settings */
memset ( & old_dm , 0 , sizeof ( old_dm ) ) ;
old_dm . dmSize = sizeof ( old_dm ) ;
ret = EnumDisplaySettingsA ( mi . szDevice , ENUM_CURRENT_SETTINGS , & old_dm ) ;
ok ( ret , " EnumDisplaySettingsA %s failed, error %#x. \n " , mi . szDevice , GetLastError ( ) ) ;
/* Detach monitor */
memset ( & dm , 0 , sizeof ( dm ) ) ;
dm . dmSize = sizeof ( dm ) ;
dm . dmFields = DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT ;
dm . dmPosition . x = mi . rcMonitor . left ;
dm . dmPosition . y = mi . rcMonitor . top ;
ret = ChangeDisplaySettingsExA ( mi . szDevice , & dm , NULL , CDS_UPDATEREGISTRY | CDS_NORESET ,
NULL ) ;
ok ( ret = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA %s returned unexpected %d. \n " ,
mi . szDevice , ret ) ;
ret = ChangeDisplaySettingsExA ( mi . szDevice , NULL , NULL , 0 , NULL ) ;
ok ( ret = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA %s returned unexpected %d. \n " ,
mi . szDevice , ret ) ;
/* Check if it's really detached */
if ( GetSystemMetrics ( SM_CMONITORS ) ! = count - 1 )
{
skip ( " Failed to detach %s. \n " , mi . szDevice ) ;
2020-07-21 08:49:49 +02:00
SetLastError ( 0xdeadbeef ) ;
2020-05-05 14:30:30 +02:00
return TRUE ;
}
/* The monitor handle should be invalid now */
mi2 . cbSize = sizeof ( mi2 ) ;
2020-07-21 08:49:49 +02:00
SetLastError ( 0xdeadbeef ) ;
2020-05-05 14:30:30 +02:00
ret = GetMonitorInfoA ( monitor , ( MONITORINFO * ) & mi2 ) ;
ok ( ! ret , " GetMonitorInfoA succeeded. \n " ) ;
2020-07-21 08:49:49 +02:00
error = GetLastError ( ) ;
ok ( error = = ERROR_INVALID_MONITOR_HANDLE | | error = = ERROR_INVALID_HANDLE ,
" Expected error %#x, got %#x. \n " , ERROR_INVALID_MONITOR_HANDLE , error ) ;
2020-05-05 14:30:30 +02:00
/* Restore the original display settings */
ret = ChangeDisplaySettingsExA ( mi . szDevice , & old_dm , NULL , CDS_UPDATEREGISTRY | CDS_NORESET ,
NULL ) ;
ok ( ret = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA %s returned unexpected %d. \n " ,
mi . szDevice , ret ) ;
ret = ChangeDisplaySettingsExA ( mi . szDevice , NULL , NULL , 0 , NULL ) ;
ok ( ret = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA %s returned unexpected %d. \n " ,
mi . szDevice , ret ) ;
}
2020-07-21 08:49:49 +02:00
SetLastError ( 0xdeadbeef ) ;
2020-05-05 14:30:30 +02:00
return TRUE ;
}
2020-12-08 09:12:26 +01:00
static BOOL CALLBACK test_EnumDisplayMonitors_count ( HMONITOR monitor , HDC hdc , LPRECT rect ,
LPARAM lparam )
{
INT * count = ( INT * ) lparam ;
+ + ( * count ) ;
return TRUE ;
}
2020-05-05 14:30:30 +02:00
static void test_EnumDisplayMonitors ( void )
{
2020-12-08 09:12:26 +01:00
static const DWORD DESKTOP_ALL_ACCESS = 0x01ff ;
HWINSTA winstation , old_winstation ;
HDESK desktop , old_desktop ;
2021-08-17 10:29:59 +02:00
USEROBJECTFLAGS flags ;
2020-12-08 09:12:26 +01:00
INT count , old_count ;
2020-05-05 14:30:30 +02:00
DWORD error ;
BOOL ret ;
ret = EnumDisplayMonitors ( NULL , NULL , test_EnumDisplayMonitors_normal_cb , 0 ) ;
ok ( ret , " EnumDisplayMonitors failed, error %#x. \n " , GetLastError ( ) ) ;
SetLastError ( 0xdeadbeef ) ;
ret = EnumDisplayMonitors ( NULL , NULL , test_EnumDisplayMonitors_return_false_cb , 0 ) ;
error = GetLastError ( ) ;
ok ( ! ret , " EnumDisplayMonitors succeeded. \n " ) ;
ok ( error = = 0xdeadbeef , " Expected error %#x, got %#x. \n " , 0xdeadbeef , error ) ;
count = GetSystemMetrics ( SM_CMONITORS ) ;
SetLastError ( 0xdeadbeef ) ;
ret = EnumDisplayMonitors ( NULL , NULL , test_EnumDisplayMonitors_invalid_handle_cb , 0 ) ;
error = GetLastError ( ) ;
if ( count > = 2 )
todo_wine ok ( ! ret , " EnumDisplayMonitors succeeded. \n " ) ;
else
ok ( ret , " EnumDisplayMonitors failed. \n " ) ;
2020-07-21 08:49:49 +02:00
ok ( error = = 0xdeadbeef , " Expected error %#x, got %#x. \n " , 0xdeadbeef , error ) ;
2020-12-08 09:12:26 +01:00
/* Test that monitor enumeration is not affected by window stations and desktops */
old_winstation = GetProcessWindowStation ( ) ;
old_desktop = GetThreadDesktop ( GetCurrentThreadId ( ) ) ;
old_count = GetSystemMetrics ( SM_CMONITORS ) ;
count = 0 ;
ret = EnumDisplayMonitors ( NULL , NULL , test_EnumDisplayMonitors_count , ( LPARAM ) & count ) ;
ok ( ret , " EnumDisplayMonitors failed, error %#x. \n " , GetLastError ( ) ) ;
ok ( count = = old_count , " Expected %d, got %d. \n " , old_count , count ) ;
winstation = CreateWindowStationW ( NULL , 0 , WINSTA_ALL_ACCESS , NULL ) ;
ok ( ! ! winstation & & winstation ! = old_winstation , " CreateWindowStationW failed, error %#x. \n " , GetLastError ( ) ) ;
ret = SetProcessWindowStation ( winstation ) ;
ok ( ret , " SetProcessWindowStation failed, error %#x. \n " , GetLastError ( ) ) ;
ok ( winstation = = GetProcessWindowStation ( ) , " Expected %p, got %p. \n " , GetProcessWindowStation ( ) , winstation ) ;
2021-08-17 10:29:59 +02:00
flags . fInherit = FALSE ;
flags . fReserved = FALSE ;
flags . dwFlags = WSF_VISIBLE ;
ret = SetUserObjectInformationW ( winstation , UOI_FLAGS , & flags , sizeof ( flags ) ) ;
ok ( ret , " SetUserObjectInformationW failed, error %#x. \n " , GetLastError ( ) ) ;
2020-12-08 09:12:26 +01:00
desktop = CreateDesktopW ( L " test_desktop " , NULL , NULL , 0 , DESKTOP_ALL_ACCESS , NULL ) ;
ok ( ! ! desktop & & desktop ! = old_desktop , " CreateDesktopW failed, error %#x. \n " , GetLastError ( ) ) ;
ret = SetThreadDesktop ( desktop ) ;
ok ( ret , " SetThreadDesktop failed, error %#x. \n " , GetLastError ( ) ) ;
ok ( desktop = = GetThreadDesktop ( GetCurrentThreadId ( ) ) , " Expected %p, got %p. \n " ,
GetThreadDesktop ( GetCurrentThreadId ( ) ) , desktop ) ;
count = GetSystemMetrics ( SM_CMONITORS ) ;
ok ( count = = old_count , " Expected %d, got %d. \n " , old_count , count ) ;
count = 0 ;
ret = EnumDisplayMonitors ( NULL , NULL , test_EnumDisplayMonitors_count , ( LPARAM ) & count ) ;
ok ( ret , " EnumDisplayMonitors failed, error %#x. \n " , GetLastError ( ) ) ;
ok ( count = = old_count , " Expected %d, got %d. \n " , old_count , count ) ;
ret = SetProcessWindowStation ( old_winstation ) ;
ok ( ret , " SetProcessWindowStation failed, error %#x. \n " , GetLastError ( ) ) ;
ret = SetThreadDesktop ( old_desktop ) ;
ok ( ret , " SetThreadDesktop failed, error %#x. \n " , GetLastError ( ) ) ;
ret = CloseDesktop ( desktop ) ;
ok ( ret , " CloseDesktop failed, error %#x. \n " , GetLastError ( ) ) ;
ret = CloseWindowStation ( winstation ) ;
ok ( ret , " CloseWindowStation failed, error %#x. \n " , GetLastError ( ) ) ;
2020-05-05 14:30:30 +02:00
}
2020-06-30 06:55:24 +02:00
static void test_QueryDisplayConfig_result ( UINT32 flags ,
UINT32 paths , const DISPLAYCONFIG_PATH_INFO * pi , UINT32 modes , const DISPLAYCONFIG_MODE_INFO * mi )
2020-05-06 19:17:30 +02:00
{
UINT32 i ;
LONG ret ;
DISPLAYCONFIG_SOURCE_DEVICE_NAME source_name ;
DISPLAYCONFIG_TARGET_DEVICE_NAME target_name ;
DISPLAYCONFIG_TARGET_PREFERRED_MODE preferred_mode ;
DISPLAYCONFIG_ADAPTER_NAME adapter_name ;
for ( i = 0 ; i < paths ; i + + )
{
source_name . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME ;
source_name . header . size = sizeof ( source_name ) ;
source_name . header . adapterId = pi [ i ] . sourceInfo . adapterId ;
source_name . header . id = pi [ i ] . sourceInfo . id ;
source_name . viewGdiDeviceName [ 0 ] = ' \0 ' ;
ret = pDisplayConfigGetDeviceInfo ( & source_name . header ) ;
ok ( ! ret , " Expected 0, got %d \n " , ret ) ;
ok ( source_name . viewGdiDeviceName [ 0 ] ! = ' \0 ' , " Expected GDI device name, got empty string \n " ) ;
2020-07-14 22:34:25 +02:00
/* Test with an invalid adapter LUID */
source_name . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME ;
source_name . header . size = sizeof ( source_name ) ;
source_name . header . adapterId . LowPart = 0xFFFF ;
source_name . header . adapterId . HighPart = 0xFFFF ;
source_name . header . id = pi [ i ] . sourceInfo . id ;
ret = pDisplayConfigGetDeviceInfo ( & source_name . header ) ;
ok ( ret = = ERROR_GEN_FAILURE , " Expected GEN_FAILURE, got %d \n " , ret ) ;
2020-06-30 06:55:23 +02:00
todo_wine {
2020-05-06 19:17:30 +02:00
target_name . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME ;
target_name . header . size = sizeof ( target_name ) ;
target_name . header . adapterId = pi [ i ] . targetInfo . adapterId ;
target_name . header . id = pi [ i ] . targetInfo . id ;
target_name . monitorDevicePath [ 0 ] = ' \0 ' ;
ret = pDisplayConfigGetDeviceInfo ( & target_name . header ) ;
ok ( ! ret , " Expected 0, got %d \n " , ret ) ;
ok ( target_name . monitorDevicePath [ 0 ] ! = ' \0 ' , " Expected monitor device path, got empty string \n " ) ;
2020-06-30 06:55:23 +02:00
}
2020-05-06 19:17:30 +02:00
2020-06-30 06:55:23 +02:00
todo_wine {
2020-05-06 19:17:30 +02:00
preferred_mode . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE ;
preferred_mode . header . size = sizeof ( preferred_mode ) ;
preferred_mode . header . adapterId = pi [ i ] . targetInfo . adapterId ;
preferred_mode . header . id = pi [ i ] . targetInfo . id ;
preferred_mode . width = preferred_mode . height = 0 ;
ret = pDisplayConfigGetDeviceInfo ( & preferred_mode . header ) ;
ok ( ! ret , " Expected 0, got %d \n " , ret ) ;
ok ( preferred_mode . width > 0 & & preferred_mode . height > 0 , " Expected non-zero height/width, got %ux%u \n " ,
preferred_mode . width , preferred_mode . height ) ;
2020-06-30 06:55:23 +02:00
}
2020-05-06 19:17:30 +02:00
2020-06-30 06:55:23 +02:00
todo_wine {
2020-05-06 19:17:30 +02:00
adapter_name . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME ;
adapter_name . header . size = sizeof ( adapter_name ) ;
adapter_name . header . adapterId = pi [ i ] . sourceInfo . adapterId ;
adapter_name . adapterDevicePath [ 0 ] = ' \0 ' ;
ret = pDisplayConfigGetDeviceInfo ( & adapter_name . header ) ;
ok ( ! ret , " Expected 0, got %d \n " , ret ) ;
ok ( adapter_name . adapterDevicePath [ 0 ] ! = ' \0 ' , " Expected adapter device path, got empty string \n " ) ;
2020-06-30 06:55:23 +02:00
}
2020-05-06 19:17:30 +02:00
/* Check corresponding modes */
if ( pi [ i ] . sourceInfo . modeInfoIdx = = DISPLAYCONFIG_PATH_MODE_IDX_INVALID )
{
skip ( " Path doesn't contain source modeInfoIdx " ) ;
continue ;
}
ok ( pi [ i ] . sourceInfo . modeInfoIdx < modes , " Expected index <%d, got %d \n " , modes , pi [ i ] . sourceInfo . modeInfoIdx ) ;
if ( pi [ i ] . sourceInfo . modeInfoIdx > = modes )
continue ;
ok ( mi [ pi [ i ] . sourceInfo . modeInfoIdx ] . infoType = = DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE , " Expected infoType %d, got %d \n " ,
DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE , mi [ pi [ i ] . sourceInfo . modeInfoIdx ] . infoType ) ;
ok ( pi [ i ] . sourceInfo . id = = mi [ pi [ i ] . sourceInfo . modeInfoIdx ] . id , " Expected id %u, got %u \n " ,
pi [ i ] . sourceInfo . id , mi [ pi [ i ] . sourceInfo . modeInfoIdx ] . id ) ;
ok ( pi [ i ] . sourceInfo . adapterId . HighPart = = mi [ pi [ i ] . sourceInfo . modeInfoIdx ] . adapterId . HighPart & &
pi [ i ] . sourceInfo . adapterId . LowPart = = mi [ pi [ i ] . sourceInfo . modeInfoIdx ] . adapterId . LowPart ,
" Expected LUID %08x:%08x, got %08x:%08x \n " ,
pi [ i ] . sourceInfo . adapterId . HighPart , pi [ i ] . sourceInfo . adapterId . LowPart ,
mi [ pi [ i ] . sourceInfo . modeInfoIdx ] . adapterId . HighPart , mi [ pi [ i ] . sourceInfo . modeInfoIdx ] . adapterId . LowPart ) ;
ok ( mi [ pi [ i ] . sourceInfo . modeInfoIdx ] . sourceMode . width > 0 & & mi [ pi [ i ] . sourceInfo . modeInfoIdx ] . sourceMode . height > 0 ,
" Expected non-zero height/width, got %ux%u \n " ,
mi [ pi [ i ] . sourceInfo . modeInfoIdx ] . sourceMode . width , mi [ pi [ i ] . sourceInfo . modeInfoIdx ] . sourceMode . height ) ;
if ( pi [ i ] . targetInfo . modeInfoIdx = = DISPLAYCONFIG_PATH_MODE_IDX_INVALID )
{
skip ( " Path doesn't contain target modeInfoIdx " ) ;
continue ;
}
ok ( pi [ i ] . targetInfo . modeInfoIdx < modes , " Expected index <%d, got %d \n " , modes , pi [ i ] . targetInfo . modeInfoIdx ) ;
if ( pi [ i ] . targetInfo . modeInfoIdx > = modes )
continue ;
ok ( mi [ pi [ i ] . targetInfo . modeInfoIdx ] . infoType = = DISPLAYCONFIG_MODE_INFO_TYPE_TARGET , " Expected infoType %d, got %d \n " ,
DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE , mi [ pi [ i ] . targetInfo . modeInfoIdx ] . infoType ) ;
ok ( pi [ i ] . targetInfo . id = = mi [ pi [ i ] . targetInfo . modeInfoIdx ] . id , " Expected id %u, got %u \n " ,
pi [ i ] . targetInfo . id , mi [ pi [ i ] . targetInfo . modeInfoIdx ] . id ) ;
ok ( pi [ i ] . targetInfo . adapterId . HighPart = = mi [ pi [ i ] . targetInfo . modeInfoIdx ] . adapterId . HighPart & &
pi [ i ] . targetInfo . adapterId . LowPart = = mi [ pi [ i ] . targetInfo . modeInfoIdx ] . adapterId . LowPart ,
" Expected LUID %08x:%08x, got %08x:%08x \n " ,
pi [ i ] . targetInfo . adapterId . HighPart , pi [ i ] . targetInfo . adapterId . LowPart ,
mi [ pi [ i ] . targetInfo . modeInfoIdx ] . adapterId . HighPart , mi [ pi [ i ] . targetInfo . modeInfoIdx ] . adapterId . LowPart ) ;
2020-06-30 06:55:24 +02:00
ok ( mi [ pi [ i ] . targetInfo . modeInfoIdx ] . targetMode . targetVideoSignalInfo . activeSize . cx > 0 & &
mi [ pi [ i ] . targetInfo . modeInfoIdx ] . targetMode . targetVideoSignalInfo . activeSize . cy > 0 ,
" Expected non-zero height/width, got %ux%u \n " ,
mi [ pi [ i ] . targetInfo . modeInfoIdx ] . targetMode . targetVideoSignalInfo . activeSize . cx ,
mi [ pi [ i ] . targetInfo . modeInfoIdx ] . targetMode . targetVideoSignalInfo . activeSize . cy ) ;
if ( flags = = QDC_DATABASE_CURRENT )
ok ( mi [ pi [ i ] . targetInfo . modeInfoIdx ] . targetMode . targetVideoSignalInfo . totalSize . cx = = 0 & &
mi [ pi [ i ] . targetInfo . modeInfoIdx ] . targetMode . targetVideoSignalInfo . totalSize . cy = = 0 ,
" Expected zero height/width, got %ux%u \n " ,
mi [ pi [ i ] . targetInfo . modeInfoIdx ] . targetMode . targetVideoSignalInfo . totalSize . cx ,
mi [ pi [ i ] . targetInfo . modeInfoIdx ] . targetMode . targetVideoSignalInfo . totalSize . cy ) ;
else
ok ( mi [ pi [ i ] . targetInfo . modeInfoIdx ] . targetMode . targetVideoSignalInfo . totalSize . cx > 0 & &
mi [ pi [ i ] . targetInfo . modeInfoIdx ] . targetMode . targetVideoSignalInfo . totalSize . cy > 0 ,
" Expected non-zero height/width, got %ux%u \n " ,
mi [ pi [ i ] . targetInfo . modeInfoIdx ] . targetMode . targetVideoSignalInfo . totalSize . cx ,
mi [ pi [ i ] . targetInfo . modeInfoIdx ] . targetMode . targetVideoSignalInfo . totalSize . cy ) ;
2020-05-06 19:17:30 +02:00
}
}
2020-05-06 19:17:29 +02:00
static void test_QueryDisplayConfig ( void )
2020-05-05 03:08:29 +02:00
{
UINT32 paths , modes ;
DISPLAYCONFIG_PATH_INFO pi [ 10 ] ;
DISPLAYCONFIG_MODE_INFO mi [ 20 ] ;
2020-06-30 06:55:24 +02:00
DISPLAYCONFIG_TOPOLOGY_ID topologyid ;
2020-05-05 03:08:29 +02:00
LONG ret ;
ret = pQueryDisplayConfig ( QDC_ALL_PATHS , NULL , NULL , NULL , NULL , NULL ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
paths = modes = 0 ;
ret = pQueryDisplayConfig ( QDC_ALL_PATHS , & paths , NULL , & modes , NULL , NULL ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
paths = modes = 0 ;
ret = pQueryDisplayConfig ( QDC_ALL_PATHS , & paths , pi , & modes , NULL , NULL ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
paths = modes = 0 ;
ret = pQueryDisplayConfig ( QDC_ALL_PATHS , & paths , NULL , & modes , mi , NULL ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
paths = modes = 0 ;
ret = pQueryDisplayConfig ( QDC_ALL_PATHS , & paths , pi , & modes , mi , NULL ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
paths = 0 ;
modes = 1 ;
ret = pQueryDisplayConfig ( QDC_ALL_PATHS , & paths , pi , & modes , mi , NULL ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
ok ( paths = = 0 , " got %u \n " , paths ) ;
ok ( modes = = 1 , " got %u \n " , modes ) ;
/* Crashes on Windows 10 */
if ( 0 )
{
ret = pQueryDisplayConfig ( QDC_ALL_PATHS , NULL , pi , NULL , mi , NULL ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
ret = pQueryDisplayConfig ( QDC_ALL_PATHS , NULL , pi , & modes , mi , NULL ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
}
paths = modes = 1 ;
ret = pQueryDisplayConfig ( 0 , & paths , pi , & modes , mi , NULL ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
2020-06-30 06:55:24 +02:00
paths = modes = 1 ;
ret = pQueryDisplayConfig ( 0xFF , & paths , pi , & modes , mi , NULL ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
paths = modes = 1 ;
ret = pQueryDisplayConfig ( QDC_DATABASE_CURRENT , & paths , pi , & modes , mi , NULL ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
paths = modes = 1 ;
ret = pQueryDisplayConfig ( QDC_ALL_PATHS , & paths , pi , & modes , mi , & topologyid ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
2020-05-06 19:17:30 +02:00
/* Below this point, test functionality that requires a WDDM driver on Windows */
2020-05-05 03:08:29 +02:00
paths = modes = 1 ;
memset ( pi , 0xFF , sizeof ( pi [ 0 ] ) ) ;
memset ( mi , 0xFF , sizeof ( mi [ 0 ] ) ) ;
ret = pQueryDisplayConfig ( QDC_ALL_PATHS , & paths , pi , & modes , mi , NULL ) ;
2020-05-06 19:17:30 +02:00
if ( ret = = ERROR_NOT_SUPPORTED )
{
todo_wine
win_skip ( " QueryDisplayConfig() functionality is unsupported \n " ) ;
return ;
}
ok ( ret = = ERROR_INSUFFICIENT_BUFFER , " got %d \n " , ret ) ;
2020-05-05 03:08:29 +02:00
ok ( paths = = 1 , " got %u \n " , paths ) ;
ok ( modes = = 1 , " got %u \n " , modes ) ;
2020-05-06 19:17:30 +02:00
paths = ARRAY_SIZE ( pi ) ;
modes = ARRAY_SIZE ( mi ) ;
memset ( pi , 0xFF , sizeof ( pi ) ) ;
memset ( mi , 0xFF , sizeof ( mi ) ) ;
ret = pQueryDisplayConfig ( QDC_ONLY_ACTIVE_PATHS , & paths , pi , & modes , mi , NULL ) ;
ok ( ! ret , " got %d \n " , ret ) ;
ok ( paths > 0 & & modes > 0 , " got %u, %u \n " , paths , modes ) ;
if ( ! ret & & paths > 0 & & modes > 0 )
2020-06-30 06:55:24 +02:00
test_QueryDisplayConfig_result ( QDC_ONLY_ACTIVE_PATHS , paths , pi , modes , mi ) ;
paths = ARRAY_SIZE ( pi ) ;
modes = ARRAY_SIZE ( mi ) ;
memset ( pi , 0xFF , sizeof ( pi ) ) ;
memset ( mi , 0xFF , sizeof ( mi ) ) ;
topologyid = 0xFF ;
ret = pQueryDisplayConfig ( QDC_DATABASE_CURRENT , & paths , pi , & modes , mi , & topologyid ) ;
ok ( ! ret , " got %d \n " , ret ) ;
ok ( topologyid ! = 0xFF , " expected topologyid to be set, got %d \n " , topologyid ) ;
if ( ! ret & & paths > 0 & & modes > 0 )
test_QueryDisplayConfig_result ( QDC_DATABASE_CURRENT , paths , pi , modes , mi ) ;
2020-05-05 03:08:29 +02:00
}
2020-05-06 19:17:29 +02:00
static void test_DisplayConfigGetDeviceInfo ( void )
2020-05-05 03:08:29 +02:00
{
LONG ret ;
DISPLAYCONFIG_SOURCE_DEVICE_NAME source_name ;
DISPLAYCONFIG_TARGET_DEVICE_NAME target_name ;
DISPLAYCONFIG_TARGET_PREFERRED_MODE preferred_mode ;
DISPLAYCONFIG_ADAPTER_NAME adapter_name ;
ret = pDisplayConfigGetDeviceInfo ( NULL ) ;
ok ( ret = = ERROR_GEN_FAILURE , " got %d \n " , ret ) ;
source_name . header . type = 0xFFFF ;
source_name . header . size = 0 ;
ret = pDisplayConfigGetDeviceInfo ( & source_name . header ) ;
ok ( ret = = ERROR_GEN_FAILURE , " got %d \n " , ret ) ;
source_name . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME ;
source_name . header . size = 0 ;
ret = pDisplayConfigGetDeviceInfo ( & source_name . header ) ;
ok ( ret = = ERROR_GEN_FAILURE , " got %d \n " , ret ) ;
source_name . header . type = 0xFFFF ;
source_name . header . size = sizeof ( source_name . header ) ;
ret = pDisplayConfigGetDeviceInfo ( & source_name . header ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
source_name . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME ;
source_name . header . size = sizeof ( source_name . header ) ;
ret = pDisplayConfigGetDeviceInfo ( & source_name . header ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
source_name . header . type = 0xFFFF ;
source_name . header . size = sizeof ( source_name ) ;
ret = pDisplayConfigGetDeviceInfo ( & source_name . header ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
source_name . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME ;
source_name . header . size = sizeof ( source_name ) - 1 ;
ret = pDisplayConfigGetDeviceInfo ( & source_name . header ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
source_name . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME ;
source_name . header . size = sizeof ( source_name ) ;
source_name . header . adapterId . LowPart = 0xFFFF ;
source_name . header . adapterId . HighPart = 0xFFFF ;
source_name . header . id = 0 ;
ret = pDisplayConfigGetDeviceInfo ( & source_name . header ) ;
ok ( ret = = ERROR_GEN_FAILURE | | ret = = ERROR_NOT_SUPPORTED , " got %d \n " , ret ) ;
target_name . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME ;
target_name . header . size = sizeof ( target_name ) - 1 ;
ret = pDisplayConfigGetDeviceInfo ( & target_name . header ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
target_name . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME ;
target_name . header . size = sizeof ( target_name ) ;
target_name . header . adapterId . LowPart = 0xFFFF ;
target_name . header . adapterId . HighPart = 0xFFFF ;
target_name . header . id = 0 ;
ret = pDisplayConfigGetDeviceInfo ( & target_name . header ) ;
ok ( ret = = ERROR_GEN_FAILURE | | ret = = ERROR_NOT_SUPPORTED , " got %d \n " , ret ) ;
preferred_mode . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE ;
preferred_mode . header . size = sizeof ( preferred_mode ) - 1 ;
ret = pDisplayConfigGetDeviceInfo ( & preferred_mode . header ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
preferred_mode . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE ;
preferred_mode . header . size = sizeof ( preferred_mode ) ;
preferred_mode . header . adapterId . LowPart = 0xFFFF ;
preferred_mode . header . adapterId . HighPart = 0xFFFF ;
preferred_mode . header . id = 0 ;
ret = pDisplayConfigGetDeviceInfo ( & preferred_mode . header ) ;
ok ( ret = = ERROR_GEN_FAILURE | | ret = = ERROR_INVALID_PARAMETER | | ret = = ERROR_NOT_SUPPORTED , " got %d \n " , ret ) ;
adapter_name . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME ;
adapter_name . header . size = sizeof ( adapter_name ) - 1 ;
ret = pDisplayConfigGetDeviceInfo ( & adapter_name . header ) ;
ok ( ret = = ERROR_INVALID_PARAMETER , " got %d \n " , ret ) ;
adapter_name . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME ;
adapter_name . header . size = sizeof ( adapter_name ) ;
adapter_name . header . adapterId . LowPart = 0xFFFF ;
adapter_name . header . adapterId . HighPart = 0xFFFF ;
ret = pDisplayConfigGetDeviceInfo ( & adapter_name . header ) ;
ok ( ret = = ERROR_GEN_FAILURE | | ret = = ERROR_INVALID_PARAMETER | | ret = = ERROR_NOT_SUPPORTED , " got %d \n " , ret ) ;
}
static void test_display_config ( void )
{
if ( ! pGetDisplayConfigBufferSizes | |
! pQueryDisplayConfig | |
! pDisplayConfigGetDeviceInfo )
{
win_skip ( " DisplayConfig APIs are not supported \n " ) ;
return ;
}
2020-05-06 19:17:29 +02:00
test_GetDisplayConfigBufferSizes ( ) ;
test_QueryDisplayConfig ( ) ;
test_DisplayConfigGetDeviceInfo ( ) ;
2020-05-05 03:08:29 +02:00
}
2021-09-01 08:37:21 +02:00
static void test_DisplayConfigSetDeviceInfo ( void )
{
static const unsigned int scales [ ] = { 100 , 125 , 150 , 175 , 200 , 225 , 250 , 300 , 350 , 400 , 450 , 500 } ;
2022-01-10 08:38:20 +01:00
static const DWORD enabled = 1 ;
2021-09-01 08:37:21 +02:00
int current_scale , current_scale_idx , recommended_scale_idx , step , dpi , old_dpi ;
D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc ;
DISPLAYCONFIG_GET_SOURCE_DPI_SCALE get_scale_req ;
DISPLAYCONFIG_SET_SOURCE_DPI_SCALE set_scale_req ;
D3DKMT_CLOSEADAPTER close_adapter_desc ;
NTSTATUS status ;
2022-01-10 08:38:20 +01:00
HKEY key ;
2021-09-01 08:37:21 +02:00
LONG ret ;
# define CHECK_FUNC(func) \
if ( ! p # # func ) \
{ \
skip ( " %s() is unavailable. \n " , # func ) ; \
return ; \
}
CHECK_FUNC ( D3DKMTCloseAdapter )
CHECK_FUNC ( D3DKMTOpenAdapterFromGdiDisplayName )
CHECK_FUNC ( DisplayConfigGetDeviceInfo )
CHECK_FUNC ( DisplayConfigSetDeviceInfo )
CHECK_FUNC ( GetDpiForMonitorInternal )
CHECK_FUNC ( SetThreadDpiAwarenessContext )
# undef CHECK_FUNC
lstrcpyW ( open_adapter_gdi_desc . DeviceName , L " \\ \\ . \\ DISPLAY1 " ) ;
status = pD3DKMTOpenAdapterFromGdiDisplayName ( & open_adapter_gdi_desc ) ;
ok ( status = = STATUS_SUCCESS , " D3DKMTOpenAdapterFromGdiDisplayName failed, status %#x. \n " , status ) ;
get_scale_req . header . type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_DPI_SCALE ;
get_scale_req . header . size = sizeof ( get_scale_req ) ;
get_scale_req . header . adapterId = open_adapter_gdi_desc . AdapterLuid ;
get_scale_req . header . id = open_adapter_gdi_desc . VidPnSourceId ;
ret = pDisplayConfigGetDeviceInfo ( & get_scale_req . header ) ;
if ( ret ! = NO_ERROR )
{
skip ( " DisplayConfigGetDeviceInfo failed, returned %d. \n " , ret ) ;
goto failed ;
}
2022-01-10 08:38:20 +01:00
/* Set IgnorePerProcessSystemDPIToast to 1 to disable "fix blurry apps popup" on Windows 10,
* which may interfere other tests because it steals focus */
RegOpenKeyA ( HKEY_CURRENT_USER , " Control Panel \\ Desktop " , & key ) ;
RegSetValueExA ( key , " IgnorePerProcessSystemDPIToast " , 0 , REG_DWORD , ( const BYTE * ) & enabled ,
sizeof ( enabled ) ) ;
2021-09-01 08:37:21 +02:00
dpi = get_primary_dpi ( ) ;
old_dpi = dpi ;
current_scale = dpi * 100 / 96 ;
for ( current_scale_idx = 0 ; current_scale_idx < ARRAY_SIZE ( scales ) ; + + current_scale_idx )
{
if ( scales [ current_scale_idx ] = = current_scale )
break ;
}
ok ( scales [ current_scale_idx ] = = current_scale , " Failed to find current scale. \n " ) ;
recommended_scale_idx = current_scale_idx - get_scale_req . curRelativeScaleStep ;
set_scale_req . header . type = DISPLAYCONFIG_DEVICE_INFO_SET_SOURCE_DPI_SCALE ;
set_scale_req . header . size = sizeof ( set_scale_req ) ;
set_scale_req . header . adapterId = open_adapter_gdi_desc . AdapterLuid ;
set_scale_req . header . id = open_adapter_gdi_desc . VidPnSourceId ;
for ( step = get_scale_req . minRelativeScaleStep ; step < = get_scale_req . maxRelativeScaleStep ; + + step )
{
set_scale_req . relativeScaleStep = step ;
ret = pDisplayConfigSetDeviceInfo ( & set_scale_req . header ) ;
ok ( ret = = NO_ERROR , " DisplayConfigSetDeviceInfo failed, returned %d. \n " , ret ) ;
dpi = scales [ step + recommended_scale_idx ] * 96 / 100 ;
ok ( dpi = = get_primary_dpi ( ) , " Expected %d, got %d. \n " , get_primary_dpi ( ) , dpi ) ;
}
/* Restore to the original scale */
set_scale_req . relativeScaleStep = get_scale_req . curRelativeScaleStep ;
ret = pDisplayConfigSetDeviceInfo ( & set_scale_req . header ) ;
ok ( ret = = NO_ERROR , " DisplayConfigSetDeviceInfo failed, returned %d. \n " , ret ) ;
ok ( old_dpi = = get_primary_dpi ( ) , " Expected %d, got %d. \n " , get_primary_dpi ( ) , old_dpi ) ;
2022-01-10 08:38:20 +01:00
/* Remove IgnorePerProcessSystemDPIToast registry value */
RegDeleteValueA ( key , " IgnorePerProcessSystemDPIToast " ) ;
RegCloseKey ( key ) ;
2021-09-01 08:37:21 +02:00
failed :
close_adapter_desc . hAdapter = open_adapter_gdi_desc . hAdapter ;
status = pD3DKMTCloseAdapter ( & close_adapter_desc ) ;
ok ( status = = STATUS_SUCCESS , " Got unexpected return code %#x. \n " , status ) ;
}
2020-12-08 09:12:15 +01:00
static BOOL CALLBACK test_handle_proc ( HMONITOR full_monitor , HDC hdc , LPRECT rect , LPARAM lparam )
{
MONITORINFO monitor_info = { sizeof ( monitor_info ) } ;
HMONITOR monitor ;
BOOL ret ;
# ifdef _WIN64
if ( ( ULONG_PTR ) full_monitor > > 32 )
monitor = full_monitor ;
else
monitor = ( HMONITOR ) ( ( ULONG_PTR ) full_monitor | ( ( ULONG_PTR ) ~ 0u < < 32 ) ) ;
SetLastError ( 0xdeadbeef ) ;
ret = GetMonitorInfoW ( monitor , & monitor_info ) ;
ok ( ret , " GetMonitorInfoW failed, error %#x. \n " , GetLastError ( ) ) ;
monitor = ( HMONITOR ) ( ( ULONG_PTR ) full_monitor & 0xffffffff ) ;
SetLastError ( 0xdeadbeef ) ;
ret = GetMonitorInfoW ( monitor , & monitor_info ) ;
ok ( ret , " GetMonitorInfoW failed, error %#x. \n " , GetLastError ( ) ) ;
monitor = ( HMONITOR ) ( ( ( ULONG_PTR ) full_monitor & 0xffffffff ) | ( ( ULONG_PTR ) 0x1234 < < 32 ) ) ;
SetLastError ( 0xdeadbeef ) ;
ret = GetMonitorInfoW ( monitor , & monitor_info ) ;
ok ( ret , " GetMonitorInfoW failed, error %#x. \n " , GetLastError ( ) ) ;
monitor = ( HMONITOR ) ( ( ULONG_PTR ) full_monitor & 0xffff ) ;
SetLastError ( 0xdeadbeef ) ;
ret = GetMonitorInfoW ( monitor , & monitor_info ) ;
todo_wine ok ( ! ret , " GetMonitorInfoW succeeded. \n " ) ;
todo_wine ok ( GetLastError ( ) = = ERROR_INVALID_MONITOR_HANDLE , " Expected error code %#x, got %#x. \n " ,
ERROR_INVALID_MONITOR_HANDLE , GetLastError ( ) ) ;
monitor = ( HMONITOR ) ( ( ( ULONG_PTR ) full_monitor & 0xffff ) | ( ( ULONG_PTR ) 0x9876 < < 16 ) ) ;
SetLastError ( 0xdeadbeef ) ;
ret = GetMonitorInfoW ( monitor , & monitor_info ) ;
ok ( ! ret , " GetMonitorInfoW succeeded. \n " ) ;
ok ( GetLastError ( ) = = ERROR_INVALID_MONITOR_HANDLE , " Expected error code %#x, got %#x. \n " ,
ERROR_INVALID_MONITOR_HANDLE , GetLastError ( ) ) ;
monitor = ( HMONITOR ) ( ( ( ULONG_PTR ) full_monitor & 0xffff ) | ( ( ULONG_PTR ) 0x12345678 < < 16 ) ) ;
SetLastError ( 0xdeadbeef ) ;
ret = GetMonitorInfoW ( monitor , & monitor_info ) ;
ok ( ! ret , " GetMonitorInfoW succeeded. \n " ) ;
ok ( GetLastError ( ) = = ERROR_INVALID_MONITOR_HANDLE , " Expected error code %#x, got %#x. \n " ,
ERROR_INVALID_MONITOR_HANDLE , GetLastError ( ) ) ;
# else
if ( ( ULONG_PTR ) full_monitor > > 16 )
monitor = full_monitor ;
else
monitor = ( HMONITOR ) ( ( ULONG_PTR ) full_monitor | ( ( ULONG_PTR ) ~ 0u < < 16 ) ) ;
SetLastError ( 0xdeadbeef ) ;
ret = GetMonitorInfoW ( monitor , & monitor_info ) ;
todo_wine_if ( ( ( ULONG_PTR ) full_monitor > > 16 ) = = 0 )
ok ( ret , " GetMonitorInfoW failed, error %#x. \n " , GetLastError ( ) ) ;
monitor = ( HMONITOR ) ( ( ULONG_PTR ) full_monitor & 0xffff ) ;
SetLastError ( 0xdeadbeef ) ;
ret = GetMonitorInfoW ( monitor , & monitor_info ) ;
ok ( ret , " GetMonitorInfoW failed, error %#x. \n " , GetLastError ( ) ) ;
monitor = ( HMONITOR ) ( ( ( ULONG_PTR ) full_monitor & 0xffff ) | ( ( ULONG_PTR ) 0x1234 < < 16 ) ) ;
SetLastError ( 0xdeadbeef ) ;
ret = GetMonitorInfoW ( monitor , & monitor_info ) ;
ok ( ! ret , " GetMonitorInfoW succeeded. \n " ) ;
ok ( GetLastError ( ) = = ERROR_INVALID_MONITOR_HANDLE , " Expected error code %#x, got %#x. \n " ,
ERROR_INVALID_MONITOR_HANDLE , GetLastError ( ) ) ;
# endif
return TRUE ;
}
static void test_handles ( void )
{
BOOL ret ;
/* Test that monitor handles are user32 handles */
ret = EnumDisplayMonitors ( NULL , NULL , test_handle_proc , 0 ) ;
ok ( ret , " EnumDisplayMonitors failed, error %#x. \n " , GetLastError ( ) ) ;
}
2021-01-24 05:14:05 +01:00
# define check_display_dc(a, b, c) _check_display_dc(__LINE__, a, b, c)
static void _check_display_dc ( INT line , HDC hdc , const DEVMODEA * dm , BOOL allow_todo )
{
2021-05-17 09:20:42 +02:00
BITMAP bitmap ;
HBITMAP hbmp ;
2021-01-24 05:14:05 +01:00
INT value ;
2021-05-17 09:20:42 +02:00
BOOL ret ;
2021-01-24 05:14:05 +01:00
value = GetDeviceCaps ( hdc , HORZRES ) ;
todo_wine_if ( allow_todo & & dm - > dmPelsWidth ! = GetSystemMetrics ( SM_CXSCREEN ) )
ok_ ( __FILE__ , line ) ( value = = dm - > dmPelsWidth , " Expected HORZRES %d, got %d. \n " ,
dm - > dmPelsWidth , value ) ;
value = GetDeviceCaps ( hdc , VERTRES ) ;
todo_wine_if ( allow_todo & & dm - > dmPelsHeight ! = GetSystemMetrics ( SM_CYSCREEN ) )
ok_ ( __FILE__ , line ) ( value = = dm - > dmPelsHeight , " Expected VERTRES %d, got %d. \n " ,
dm - > dmPelsHeight , value ) ;
value = GetDeviceCaps ( hdc , DESKTOPHORZRES ) ;
todo_wine_if ( dm - > dmPelsWidth ! = GetSystemMetrics ( SM_CXVIRTUALSCREEN )
& & value = = GetSystemMetrics ( SM_CXVIRTUALSCREEN ) )
ok_ ( __FILE__ , line ) ( value = = dm - > dmPelsWidth , " Expected DESKTOPHORZRES %d, got %d. \n " ,
dm - > dmPelsWidth , value ) ;
value = GetDeviceCaps ( hdc , DESKTOPVERTRES ) ;
todo_wine_if ( dm - > dmPelsHeight ! = GetSystemMetrics ( SM_CYVIRTUALSCREEN )
& & value = = GetSystemMetrics ( SM_CYVIRTUALSCREEN ) )
ok_ ( __FILE__ , line ) ( value = = dm - > dmPelsHeight , " Expected DESKTOPVERTRES %d, got %d. \n " ,
dm - > dmPelsHeight , value ) ;
value = GetDeviceCaps ( hdc , VREFRESH ) ;
2021-01-24 05:14:32 +01:00
todo_wine_if ( allow_todo )
2021-01-24 05:14:05 +01:00
ok_ ( __FILE__ , line ) ( value = = dm - > dmDisplayFrequency , " Expected VREFRESH %d, got %d. \n " ,
dm - > dmDisplayFrequency , value ) ;
2021-05-17 09:20:42 +02:00
value = GetDeviceCaps ( hdc , BITSPIXEL ) ;
ok_ ( __FILE__ , line ) ( value = = dm - > dmBitsPerPel , " Expected BITSPIXEL %d, got %d. \n " ,
dm - > dmBitsPerPel , value ) ;
hbmp = GetCurrentObject ( hdc , OBJ_BITMAP ) ;
ok_ ( __FILE__ , line ) ( ! ! hbmp , " GetCurrentObject failed, error %#x. \n " , GetLastError ( ) ) ;
ret = GetObjectA ( hbmp , sizeof ( bitmap ) , & bitmap ) ;
/* GetObjectA fails on Win7 and older */
ok_ ( __FILE__ , line ) ( ret | | broken ( ! ret ) , " GetObjectA failed, error %d. \n " , GetLastError ( ) ) ;
if ( ret )
{
ok_ ( __FILE__ , line ) ( bitmap . bmType = = 0 , " Expected bmType %d, got %d. \n " , 0 , bitmap . bmType ) ;
todo_wine
ok_ ( __FILE__ , line ) ( bitmap . bmWidth = = GetSystemMetrics ( SM_CXVIRTUALSCREEN ) ,
" Expected bmWidth %d, got %d. \n " , GetSystemMetrics ( SM_CXVIRTUALSCREEN ) , bitmap . bmWidth ) ;
todo_wine
ok_ ( __FILE__ , line ) ( bitmap . bmHeight = = GetSystemMetrics ( SM_CYVIRTUALSCREEN ) ,
" Expected bmHeight %d, got %d. \n " , GetSystemMetrics ( SM_CYVIRTUALSCREEN ) , bitmap . bmHeight ) ;
todo_wine
ok_ ( __FILE__ , line ) ( bitmap . bmBitsPixel = = 32 , " Expected bmBitsPixel %d, got %d. \n " , 32 ,
bitmap . bmBitsPixel ) ;
ok_ ( __FILE__ , line ) ( bitmap . bmWidthBytes = = get_bitmap_stride ( bitmap . bmWidth , bitmap . bmBitsPixel ) ,
" Expected bmWidthBytes %d, got %d. \n " , get_bitmap_stride ( bitmap . bmWidth , bitmap . bmBitsPixel ) ,
bitmap . bmWidthBytes ) ;
ok_ ( __FILE__ , line ) ( bitmap . bmPlanes = = 1 , " Expected bmPlanes %d, got %d. \n " , 1 , bitmap . bmPlanes ) ;
ok_ ( __FILE__ , line ) ( bitmap . bmBits = = NULL , " Expected bmBits %p, got %p. \n " , NULL , bitmap . bmBits ) ;
}
2021-01-24 05:14:05 +01:00
}
static void test_display_dc ( void )
{
2021-12-29 08:32:42 +01:00
static const INT bpps [ ] = { 1 , 4 , 8 , 16 , 24 , 32 } ;
HBITMAP hbitmap , old_hbitmap ;
INT count , old_count , i , bpp ;
2021-01-24 05:14:05 +01:00
DWORD device_idx , mode_idx ;
DEVMODEA dm , dm2 , dm3 ;
DISPLAY_DEVICEA dd ;
2021-12-29 08:32:42 +01:00
HDC hdc , mem_dc ;
DIBSECTION dib ;
BITMAP bitmap ;
2021-01-24 05:14:05 +01:00
BOOL ret ;
LONG res ;
/* Test DCs covering the entire virtual screen */
hdc = CreateDCA ( " DISPLAY " , NULL , NULL , NULL ) ;
ok ( ! ! hdc , " CreateDCA failed. \n " ) ;
memset ( & dm , 0 , sizeof ( dm ) ) ;
dm . dmSize = sizeof ( dm ) ;
ret = EnumDisplaySettingsA ( NULL , ENUM_CURRENT_SETTINGS , & dm ) ;
ok ( ret , " EnumDisplaySettingsA failed. \n " ) ;
check_display_dc ( hdc , & dm , FALSE ) ;
2021-12-29 08:32:42 +01:00
/* Test that CreateCompatibleBitmap() for display DCs creates DDBs */
hbitmap = CreateCompatibleBitmap ( hdc , dm . dmPelsWidth , dm . dmPelsHeight ) ;
ok ( ! ! hbitmap , " CreateCompatibleBitmap failed, error %d. \n " , GetLastError ( ) ) ;
count = GetObjectW ( hbitmap , sizeof ( dib ) , & dib ) ;
ok ( count = = sizeof ( BITMAP ) , " GetObject failed, count %d. \n " , count ) ;
count = GetObjectW ( hbitmap , sizeof ( bitmap ) , & bitmap ) ;
ok ( count = = sizeof ( BITMAP ) , " GetObject failed, count %d. \n " , count ) ;
ok ( bitmap . bmBitsPixel = = dm . dmBitsPerPel , " Expected %d, got %d. \n " , dm . dmBitsPerPel ,
bitmap . bmBitsPixel ) ;
DeleteObject ( hbitmap ) ;
/* Test selecting a DDB of a different depth into a display compatible DC */
for ( i = 0 ; i < ARRAY_SIZE ( bpps ) ; + + i )
{
winetest_push_context ( " bpp %d " , bpps [ i ] ) ;
mem_dc = CreateCompatibleDC ( hdc ) ;
hbitmap = CreateBitmap ( dm . dmPelsWidth , dm . dmPelsHeight , 1 , bpps [ i ] , NULL ) ;
ok ( ! ! hbitmap , " CreateBitmap failed, error %d. \n " , GetLastError ( ) ) ;
old_hbitmap = SelectObject ( mem_dc , hbitmap ) ;
if ( bpps [ i ] ! = 1 & & bpps [ i ] ! = 32 )
ok ( ! old_hbitmap , " Selecting bitmap succeeded. \n " ) ;
else
ok ( ! ! old_hbitmap , " Failed to select bitmap. \n " ) ;
SelectObject ( mem_dc , old_hbitmap ) ;
DeleteObject ( hbitmap ) ;
DeleteDC ( mem_dc ) ;
winetest_pop_context ( ) ;
}
/* Test selecting a DDB of the same color depth into a display compatible DC */
mem_dc = CreateCompatibleDC ( hdc ) ;
bpp = GetDeviceCaps ( mem_dc , BITSPIXEL ) ;
ok ( bpp = = dm . dmBitsPerPel , " Expected bpp %d, got %d. \n " , dm . dmBitsPerPel , bpp ) ;
hbitmap = CreateCompatibleBitmap ( hdc , dm . dmPelsWidth , dm . dmPelsHeight ) ;
count = GetObjectW ( hbitmap , sizeof ( bitmap ) , & bitmap ) ;
ok ( count = = sizeof ( BITMAP ) , " GetObject failed, count %d. \n " , count ) ;
ok ( bitmap . bmBitsPixel = = dm . dmBitsPerPel , " Expected %d, got %d. \n " , dm . dmBitsPerPel , bitmap . bmBitsPixel ) ;
old_hbitmap = SelectObject ( mem_dc , hbitmap ) ;
ok ( ! ! old_hbitmap , " Failed to select bitmap. \n " ) ;
SelectObject ( mem_dc , old_hbitmap ) ;
DeleteDC ( mem_dc ) ;
2021-05-17 09:20:42 +02:00
/* Tests after mode changes to a different resolution */
2021-01-24 05:14:05 +01:00
memset ( & dm2 , 0 , sizeof ( dm2 ) ) ;
dm2 . dmSize = sizeof ( dm2 ) ;
for ( mode_idx = 0 ; EnumDisplaySettingsA ( NULL , mode_idx , & dm2 ) ; + + mode_idx )
{
if ( dm2 . dmPelsWidth ! = dm . dmPelsWidth & & dm2 . dmPelsHeight ! = dm . dmPelsHeight )
break ;
}
ok ( dm2 . dmPelsWidth & & dm2 . dmPelsWidth ! = dm . dmPelsWidth & & dm2 . dmPelsHeight ! = dm . dmPelsHeight ,
" Failed to find a different resolution. \n " ) ;
res = ChangeDisplaySettingsExA ( NULL , & dm2 , NULL , CDS_RESET , NULL ) ;
ok ( res = = DISP_CHANGE_SUCCESSFUL | | broken ( res = = DISP_CHANGE_FAILED ) , /* Win8 TestBots */
" ChangeDisplaySettingsExA returned unexpected %d. \n " , res ) ;
if ( res = = DISP_CHANGE_SUCCESSFUL )
{
check_display_dc ( hdc , & dm2 , FALSE ) ;
res = ChangeDisplaySettingsExA ( NULL , NULL , NULL , 0 , NULL ) ;
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA returned unexpected %d. \n " , res ) ;
}
2021-05-17 09:20:42 +02:00
/* Tests after mode changes to a different color depth */
memset ( & dm2 , 0 , sizeof ( dm2 ) ) ;
dm2 . dmSize = sizeof ( dm2 ) ;
for ( mode_idx = 0 ; EnumDisplaySettingsA ( NULL , mode_idx , & dm2 ) ; + + mode_idx )
{
2021-12-29 08:32:42 +01:00
if ( dm2 . dmBitsPerPel ! = dm . dmBitsPerPel & & dm2 . dmBitsPerPel ! = 1 )
2021-05-17 09:20:42 +02:00
break ;
}
if ( dm2 . dmBitsPerPel & & dm2 . dmBitsPerPel ! = dm . dmBitsPerPel )
{
res = ChangeDisplaySettingsExA ( NULL , & dm2 , NULL , CDS_RESET , NULL ) ;
/* Win8 TestBots */
ok ( res = = DISP_CHANGE_SUCCESSFUL | | broken ( res = = DISP_CHANGE_FAILED ) ,
" ChangeDisplaySettingsExA returned unexpected %d. \n " , res ) ;
if ( res = = DISP_CHANGE_SUCCESSFUL )
{
check_display_dc ( hdc , & dm2 , FALSE ) ;
2021-12-29 08:32:42 +01:00
/* Test selecting a compatible bitmap of a different color depth previously created for
* a display DC into a new compatible DC */
count = GetObjectW ( hbitmap , sizeof ( bitmap ) , & bitmap ) ;
ok ( count = = sizeof ( BITMAP ) , " GetObject failed, count %d. \n " , count ) ;
ok ( bitmap . bmBitsPixel = = dm . dmBitsPerPel , " Expected %d, got %d. \n " , dm . dmBitsPerPel ,
bitmap . bmBitsPixel ) ;
/* Note that hbitmap is of a different color depth and it can be successfully selected
* into the new compatible DC */
mem_dc = CreateCompatibleDC ( hdc ) ;
bpp = GetDeviceCaps ( mem_dc , BITSPIXEL ) ;
ok ( bpp = = dm2 . dmBitsPerPel , " Expected bpp %d, got %d. \n " , dm2 . dmBitsPerPel , bpp ) ;
old_hbitmap = SelectObject ( mem_dc , hbitmap ) ;
ok ( ! ! old_hbitmap , " Failed to select bitmap. \n " ) ;
bpp = GetDeviceCaps ( mem_dc , BITSPIXEL ) ;
ok ( bpp = = dm2 . dmBitsPerPel , " Expected bpp %d, got %d. \n " , dm2 . dmBitsPerPel , bpp ) ;
SelectObject ( mem_dc , old_hbitmap ) ;
DeleteDC ( mem_dc ) ;
DeleteObject ( hbitmap ) ;
/* Test selecting a DDB of a different color depth into a display compatible DC */
for ( i = 0 ; i < ARRAY_SIZE ( bpps ) ; + + i )
{
winetest_push_context ( " bpp %d " , bpps [ i ] ) ;
mem_dc = CreateCompatibleDC ( hdc ) ;
hbitmap = CreateBitmap ( dm2 . dmPelsWidth , dm2 . dmPelsHeight , 1 , bpps [ i ] , NULL ) ;
ok ( ! ! hbitmap , " CreateBitmap failed, error %d. \n " , GetLastError ( ) ) ;
old_hbitmap = SelectObject ( mem_dc , hbitmap ) ;
/* On Win7 dual-QXL test bot and XP, only 1-bit DDBs and DDBs with the same color
* depth can be selected to the compatible DC . On newer versions of Windows , only
* 1 - bit and 32 - bit DDBs can be selected into the compatible DC even if
* GetDeviceCaps ( BITSPIXEL ) reports a different color depth , for example , 16 - bit .
* It ' s most likely due to the fact that lower color depth are emulated on newer
* versions of Windows as the real color depth is still 32 - bit */
if ( bpps [ i ] ! = 1 & & bpps [ i ] ! = 32 )
todo_wine_if ( bpps [ i ] = = dm2 . dmBitsPerPel )
ok ( ! old_hbitmap | | broken ( ! ! old_hbitmap ) /* Win7 dual-QXL test bot and XP */ ,
" Selecting bitmap succeeded. \n " ) ;
else
ok ( ! ! old_hbitmap | | broken ( ! old_hbitmap ) /* Win7 dual-QXL test bot and XP */ ,
" Failed to select bitmap. \n " ) ;
SelectObject ( mem_dc , old_hbitmap ) ;
DeleteObject ( hbitmap ) ;
DeleteDC ( mem_dc ) ;
winetest_pop_context ( ) ;
}
hbitmap = NULL ;
2021-05-17 09:20:42 +02:00
res = ChangeDisplaySettingsExA ( NULL , NULL , NULL , 0 , NULL ) ;
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA returned unexpected %d. \n " , res ) ;
}
}
else
{
win_skip ( " Failed to find a different color depth other than %u. \n " , dm . dmBitsPerPel ) ;
}
2021-12-29 08:32:42 +01:00
if ( hbitmap )
DeleteObject ( hbitmap ) ;
2021-01-24 05:14:05 +01:00
DeleteDC ( hdc ) ;
/* Test DCs covering a specific monitor */
dd . cb = sizeof ( dd ) ;
for ( device_idx = 0 ; EnumDisplayDevicesA ( NULL , device_idx , & dd , 0 ) ; + + device_idx )
{
if ( ! ( dd . StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP ) )
continue ;
memset ( & dm , 0 , sizeof ( dm ) ) ;
dm . dmSize = sizeof ( dm ) ;
ret = EnumDisplaySettingsA ( dd . DeviceName , ENUM_CURRENT_SETTINGS , & dm ) ;
ok ( ret , " EnumDisplaySettingsA %s failed. \n " , dd . DeviceName ) ;
hdc = CreateDCA ( dd . DeviceName , NULL , NULL , NULL ) ;
ok ( ! ! hdc , " CreateDCA %s failed. \n " , dd . DeviceName ) ;
2021-01-24 05:14:20 +01:00
check_display_dc ( hdc , & dm , FALSE ) ;
2021-01-24 05:14:05 +01:00
2021-05-17 09:20:42 +02:00
/* Tests after mode changes to a different resolution */
2021-01-24 05:14:05 +01:00
memset ( & dm2 , 0 , sizeof ( dm2 ) ) ;
dm2 . dmSize = sizeof ( dm2 ) ;
for ( mode_idx = 0 ; EnumDisplaySettingsA ( dd . DeviceName , mode_idx , & dm2 ) ; + + mode_idx )
{
if ( dm2 . dmPelsWidth ! = dm . dmPelsWidth & & dm2 . dmPelsHeight ! = dm . dmPelsHeight )
break ;
}
ok ( dm2 . dmPelsWidth & & dm2 . dmPelsWidth ! = dm . dmPelsWidth & & dm2 . dmPelsHeight ! = dm . dmPelsHeight ,
" Failed to find a different resolution for %s. \n " , dd . DeviceName ) ;
res = ChangeDisplaySettingsExA ( dd . DeviceName , & dm2 , NULL , CDS_RESET , NULL ) ;
ok ( res = = DISP_CHANGE_SUCCESSFUL | | broken ( res = = DISP_CHANGE_FAILED ) , /* Win8 TestBots */
" ChangeDisplaySettingsExA %s returned unexpected %d. \n " , dd . DeviceName , res ) ;
if ( res ! = DISP_CHANGE_SUCCESSFUL )
{
win_skip ( " Failed to change display mode for %s. \n " , dd . DeviceName ) ;
DeleteDC ( hdc ) ;
continue ;
}
2021-01-24 05:14:20 +01:00
check_display_dc ( hdc , & dm2 , FALSE ) ;
2021-01-24 05:14:05 +01:00
2021-05-17 09:20:42 +02:00
/* Tests after mode changes to a different color depth */
memset ( & dm2 , 0 , sizeof ( dm2 ) ) ;
dm2 . dmSize = sizeof ( dm2 ) ;
for ( mode_idx = 0 ; EnumDisplaySettingsA ( dd . DeviceName , mode_idx , & dm2 ) ; + + mode_idx )
{
if ( dm2 . dmBitsPerPel ! = dm . dmBitsPerPel )
break ;
}
if ( dm2 . dmBitsPerPel & & dm2 . dmBitsPerPel ! = dm . dmBitsPerPel )
{
res = ChangeDisplaySettingsExA ( dd . DeviceName , & dm2 , NULL , CDS_RESET , NULL ) ;
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA returned unexpected %d. \n " , res ) ;
check_display_dc ( hdc , & dm2 , FALSE ) ;
res = ChangeDisplaySettingsExA ( NULL , NULL , NULL , 0 , NULL ) ;
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA returned unexpected %d. \n " , res ) ;
}
else
{
win_skip ( " Failed to find a different color depth other than %u. \n " , dm . dmBitsPerPel ) ;
}
2021-01-24 05:14:05 +01:00
/* Tests after monitor detach */
2021-05-17 09:20:42 +02:00
ret = EnumDisplaySettingsA ( dd . DeviceName , ENUM_CURRENT_SETTINGS , & dm2 ) ;
ok ( ret , " EnumDisplaySettingsA %s failed. \n " , dd . DeviceName ) ;
2021-01-24 05:14:05 +01:00
if ( ! ( dd . StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE ) )
{
old_count = GetSystemMetrics ( SM_CMONITORS ) ;
memset ( & dm3 , 0 , sizeof ( dm3 ) ) ;
dm3 . dmSize = sizeof ( dm3 ) ;
ret = EnumDisplaySettingsA ( dd . DeviceName , ENUM_CURRENT_SETTINGS , & dm3 ) ;
ok ( ret , " EnumDisplaySettingsA %s failed. \n " , dd . DeviceName ) ;
dm3 . dmFields = DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT ;
dm3 . dmPelsWidth = 0 ;
dm3 . dmPelsHeight = 0 ;
res = ChangeDisplaySettingsExA ( dd . DeviceName , & dm3 , NULL , CDS_UPDATEREGISTRY | CDS_NORESET , NULL ) ;
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA %s returned unexpected %d. \n " ,
dd . DeviceName , res ) ;
res = ChangeDisplaySettingsExA ( dd . DeviceName , NULL , NULL , 0 , NULL ) ;
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA %s returned unexpected %d. \n " ,
dd . DeviceName , res ) ;
count = GetSystemMetrics ( SM_CMONITORS ) ;
ok ( count = = old_count - 1 , " Expected monitor count %d, got %d. \n " , old_count - 1 , count ) ;
/* Should report the same values before detach */
check_display_dc ( hdc , & dm2 , TRUE ) ;
}
res = ChangeDisplaySettingsExA ( dd . DeviceName , & dm , NULL , CDS_UPDATEREGISTRY | CDS_NORESET , NULL ) ;
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA %s returned unexpected %d. \n " ,
dd . DeviceName , res ) ;
res = ChangeDisplaySettingsExA ( NULL , NULL , NULL , 0 , NULL ) ;
ok ( res = = DISP_CHANGE_SUCCESSFUL , " ChangeDisplaySettingsExA %s returned unexpected %d. \n " ,
dd . DeviceName , res ) ;
DeleteDC ( hdc ) ;
}
}
2005-09-28 12:17:13 +02:00
START_TEST ( monitor )
{
2005-10-11 22:27:27 +02:00
init_function_pointers ( ) ;
2005-09-28 12:17:13 +02:00
test_enumdisplaydevices ( ) ;
2008-05-18 11:47:14 +02:00
test_ChangeDisplaySettingsEx ( ) ;
2021-09-01 08:37:21 +02:00
test_DisplayConfigSetDeviceInfo ( ) ;
2020-05-05 14:30:30 +02:00
test_EnumDisplayMonitors ( ) ;
2008-08-26 13:40:58 +02:00
test_monitors ( ) ;
test_work_area ( ) ;
2015-10-23 20:40:50 +02:00
test_display_config ( ) ;
2020-12-08 09:12:15 +01:00
test_handles ( ) ;
2021-01-24 05:14:05 +01:00
test_display_dc ( ) ;
2005-09-28 12:17:13 +02:00
}