From: R��mi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 46 +++++++++++++++++++++++++++++++++----- dlls/winemac.drv/display.c | 3 +-- dlls/winex11.drv/display.c | 30 +------------------------ 3 files changed, 43 insertions(+), 36 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 36434877c93..ec7ca4734d1 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2026,7 +2026,34 @@ static BOOL is_detached_mode( const DEVMODEW *mode ) mode->dmPelsHeight == 0; }
-static DEVMODEW *validate_display_settings( const WCHAR *adapter_path, const WCHAR *device_name, DEVMODEW *devmode, DEVMODEW *temp_mode ) +static DEVMODEW *find_display_mode( DEVMODEW *modes, DEVMODEW *devmode ) +{ + DEVMODEW *mode; + + if (is_detached_mode( devmode )) return devmode; + + for (mode = modes; mode && mode->dmSize; mode = NEXT_DEVMODEW(mode)) + { + if ((devmode->dmFields & DM_BITSPERPEL) && devmode->dmBitsPerPel && devmode->dmBitsPerPel != mode->dmBitsPerPel) + continue; + if ((devmode->dmFields & DM_PELSWIDTH) && devmode->dmPelsWidth != mode->dmPelsWidth) + continue; + if ((devmode->dmFields & DM_PELSHEIGHT) && devmode->dmPelsHeight != mode->dmPelsHeight) + continue; + if ((devmode->dmFields & DM_DISPLAYFREQUENCY) && devmode->dmDisplayFrequency && mode->dmDisplayFrequency && + devmode->dmDisplayFrequency != 1 && devmode->dmDisplayFrequency != mode->dmDisplayFrequency) + continue; + if ((devmode->dmFields & DM_DISPLAYORIENTATION) && devmode->dmDisplayOrientation != mode->dmDisplayOrientation) + continue; + + return mode; + } + + return NULL; +} + +static DEVMODEW *get_full_mode( const WCHAR *adapter_path, const WCHAR *device_name, DEVMODEW *modes, + DEVMODEW *devmode, DEVMODEW *temp_mode ) { if (devmode) { @@ -2068,6 +2095,12 @@ static DEVMODEW *validate_display_settings( const WCHAR *adapter_path, const WCH } }
+ if ((devmode = find_display_mode( modes, devmode )) && devmode != temp_mode) + { + devmode->dmFields |= DM_POSITION; + devmode->dmPosition = temp_mode->dmPosition; + } + return devmode; }
@@ -2077,8 +2110,8 @@ static DEVMODEW *validate_display_settings( const WCHAR *adapter_path, const WCH LONG WINAPI NtUserChangeDisplaySettings( UNICODE_STRING *devname, DEVMODEW *devmode, HWND hwnd, DWORD flags, void *lparam ) { + DEVMODEW *modes, temp_mode = {.dmSize = sizeof(DEVMODEW)}; WCHAR device_name[CCHDEVICENAME], adapter_path[MAX_PATH]; - DEVMODEW temp_mode = {.dmSize = sizeof(DEVMODEW)}; LONG ret = DISP_CHANGE_SUCCESSFUL; struct adapter *adapter;
@@ -2098,19 +2131,22 @@ LONG WINAPI NtUserChangeDisplaySettings( UNICODE_STRING *devname, DEVMODEW *devm { lstrcpyW( device_name, adapter->dev.device_name ); lstrcpyW( adapter_path, adapter->config_key ); + /* allocate an extra mode to make iteration easier */ + modes = calloc( adapter->mode_count + 1, sizeof(DEVMODEW) ); + if (modes) memcpy( modes, adapter->modes, adapter->mode_count * sizeof(DEVMODEW) ); } unlock_display_devices(); - if (!adapter) + if (!adapter || !modes) { WARN( "Invalid device name %s.\n", debugstr_us(devname) ); return DISP_CHANGE_BADPARAM; }
- if (!(devmode = validate_display_settings( adapter_path, device_name, devmode, &temp_mode ))) ret = DISP_CHANGE_BADMODE; - else if (user_driver->pChangeDisplaySettingsEx( device_name, devmode, hwnd, flags | CDS_TEST, lparam )) ret = DISP_CHANGE_BADMODE; + if (!(devmode = get_full_mode( adapter_path, device_name, modes, devmode, &temp_mode ))) ret = DISP_CHANGE_BADMODE; else if ((flags & CDS_UPDATEREGISTRY) && !write_registry_settings( adapter_path, devmode )) ret = DISP_CHANGE_NOTUPDATED; else if (flags & (CDS_TEST | CDS_NORESET)) ret = DISP_CHANGE_SUCCESSFUL; else ret = user_driver->pChangeDisplaySettingsEx( device_name, devmode, hwnd, flags, lparam ); + free( modes );
if (ret) ERR( "Changing %s display settings returned %d.\n", debugstr_us(devname), ret ); return ret; diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 8baa4b6df83..52c4b8846f1 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -881,8 +881,7 @@ LONG macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode,
if (best_display_mode) { - if (flags & (CDS_TEST | CDS_NORESET)) ret = DISP_CHANGE_SUCCESSFUL; - else if (wcsicmp(primary_adapter, devname)) + if (wcsicmp(primary_adapter, devname)) { FIXME("Changing non-primary adapter settings is currently unsupported.\n"); ret = DISP_CHANGE_SUCCESSFUL; diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 34fd0136fc3..5304a2c0ecb 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -774,41 +774,13 @@ static BOOL all_detached_settings(const DEVMODEW *displays) LONG X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode, HWND hwnd, DWORD flags, LPVOID lpvoid ) { - DEVMODEW *displays, *mode, *full_mode; + DEVMODEW *displays; LONG ret;
ret = get_display_settings( &displays, devname, devmode ); if (ret != DISP_CHANGE_SUCCESSFUL) return ret;
- if (flags & CDS_UPDATEREGISTRY && devname && devmode) - { - for (mode = displays; mode->dmSize; mode = NEXT_DEVMODEW(mode)) - { - ULONG_PTR *id = (ULONG_PTR *)(mode + 1); - - if (!wcsicmp(mode->dmDeviceName, devname)) - { - full_mode = get_full_mode(*id, mode); - if (!full_mode) - { - free(displays); - return DISP_CHANGE_BADMODE; - } - - memcpy( &devmode->dmFields, &full_mode->dmFields, devmode->dmSize - offsetof(DEVMODEW, dmFields) ); - free_full_mode(full_mode); - break; - } - } - } - - if (flags & (CDS_TEST | CDS_NORESET)) - { - free(displays); - return DISP_CHANGE_SUCCESSFUL; - } - if (all_detached_settings( displays )) { WARN("Detaching all displays is not permitted.\n");