Split from https://gitlab.winehq.org/wine/wine/-/merge_requests/576, for which I'll then add modes sorting, and move support for stretched / interlaced modes from winemac to win32u.
-- v3: win32u: Only read/write valid mode fields from/to the registry. win32u: Use current mode position if desired mode doesn't specify it. win32u: Always copy devmode in validate_display_settings. win32u: Read registry or current mode when validation needs it. win32u: Do not keep display modes driver extra in the registry.
From: R��mi Bernon rbernon@codeweavers.com
It's not always serializable and cannot be shared across processes. --- dlls/win32u/sysparams.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 52665f7a641..85ffd2f69e9 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -178,7 +178,6 @@ static const WCHAR x_panningW[] = {'X','P','a','n','n','i','n','g',0}; static const WCHAR y_panningW[] = {'Y','P','a','n','n','i','n','g',0}; static const WCHAR orientationW[] = {'O','r','i','e','n','t','a','t','i','o','n',0}; static const WCHAR fixed_outputW[] = {'F','i','x','e','d','O','u','t','p','u','t',0}; -static const WCHAR driver_extraW[] = {'D','r','i','v','e','r','E','x','t','r','a',0}; static const WCHAR mode_countW[] = {'M','o','d','e','C','o','u','n','t',0};
static const char guid_devclass_displayA[] = "{4D36E968-E325-11CE-BFC1-08002BE10318}"; @@ -453,7 +452,6 @@ static BOOL write_adapter_mode( HKEY adapter_key, DWORD index, const DEVMODEW *m set_mode_field( x_panningW, dmPosition.x, DM_POSITION ); set_mode_field( y_panningW, dmPosition.y, DM_POSITION ); } - ret = set_reg_value( hkey, driver_extraW, REG_BINARY, mode + 1, mode->dmDriverExtra );
#undef set_mode_field
@@ -500,11 +498,6 @@ static BOOL read_adapter_mode( HKEY adapter_key, DWORD index, DEVMODEW *mode )
#undef query_mode_field
- ret = query_reg_value( hkey, driver_extraW, value, sizeof(value_buf) ) && - value->Type == REG_BINARY; - if (ret && value->DataLength <= mode->dmDriverExtra) - memcpy( mode + 1, value->Data, mode->dmDriverExtra ); - done: NtClose( hkey ); return TRUE; @@ -555,8 +548,8 @@ static BOOL read_display_adapter_settings( unsigned int index, struct adapter *i char buffer[4096]; KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer; WCHAR *value_str = (WCHAR *)value->Data; - DWORD i, driver_extra = 0, size; DEVMODEW *mode; + DWORD i, size; HKEY hkey;
if (!enum_key && !(enum_key = reg_open_key( NULL, enum_keyW, sizeof(enum_keyW) ))) @@ -596,19 +589,16 @@ static BOOL read_display_adapter_settings( unsigned int index, struct adapter *i /* Interface name */ info->dev.interface_name[0] = 0;
- /* ModeCount / DriverExtra */ + /* ModeCount */ if (query_reg_value( hkey, mode_countW, value, sizeof(buffer) ) && value->Type == REG_DWORD) info->mode_count = *(const DWORD *)value->Data; - if (query_reg_value( hkey, driver_extraW, value, sizeof(buffer) ) && value->Type == REG_DWORD) - driver_extra = *(const DWORD *)value->Data;
/* Modes */ - if ((info->modes = calloc( info->mode_count, sizeof(DEVMODEW) + driver_extra ))) + if ((info->modes = calloc( info->mode_count, sizeof(DEVMODEW) ))) { for (i = 0, mode = info->modes; i < info->mode_count; i++) { mode->dmSize = offsetof(DEVMODEW, dmICMMethod); - mode->dmDriverExtra = driver_extra; if (!read_adapter_mode( hkey, i, mode )) break; mode = NEXT_DEVMODEW(mode); } @@ -1349,8 +1339,7 @@ static void add_mode( const DEVMODEW *mode, void *param )
if (write_adapter_mode( ctx->adapter_key, ctx->mode_count, mode )) { - if (!ctx->mode_count++) set_reg_value( ctx->adapter_key, driver_extraW, REG_DWORD, - &mode->dmDriverExtra, sizeof(mode->dmDriverExtra) ); + ctx->mode_count++; set_reg_value( ctx->adapter_key, mode_countW, REG_DWORD, &ctx->mode_count, sizeof(ctx->mode_count) ); } }
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 85ffd2f69e9..514585a0988 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2026,7 +2026,7 @@ static BOOL is_detached_mode( const DEVMODEW *mode ) mode->dmPelsHeight == 0; }
-static DEVMODEW *validate_display_settings( DEVMODEW *default_mode, DEVMODEW *current_mode, DEVMODEW *devmode ) +static DEVMODEW *validate_display_settings( const WCHAR *adapter_path, const WCHAR *device_name, DEVMODEW *devmode, DEVMODEW *temp_mode ) { if (devmode) { @@ -2043,9 +2043,9 @@ static DEVMODEW *validate_display_settings( DEVMODEW *default_mode, DEVMODEW *cu
if (!devmode) { - if (!default_mode->dmSize) return NULL; + if (!read_registry_settings( adapter_path, temp_mode )) return NULL; TRACE( "Return to original display mode\n" ); - devmode = default_mode; + devmode = temp_mode; }
if ((devmode->dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) != (DM_PELSWIDTH | DM_PELSHEIGHT)) @@ -2056,9 +2056,10 @@ static DEVMODEW *validate_display_settings( DEVMODEW *default_mode, DEVMODEW *cu
if (!is_detached_mode( devmode ) && (!devmode->dmPelsWidth || !devmode->dmPelsHeight)) { - if (!current_mode->dmSize) return NULL; - if (!devmode->dmPelsWidth) devmode->dmPelsWidth = current_mode->dmPelsWidth; - if (!devmode->dmPelsHeight) devmode->dmPelsHeight = current_mode->dmPelsHeight; + DEVMODEW current_mode = {.dmSize = sizeof(DEVMODEW)}; + if (!user_driver->pGetCurrentDisplaySettings( device_name, ¤t_mode )) return NULL; + if (!devmode->dmPelsWidth) devmode->dmPelsWidth = current_mode.dmPelsWidth; + if (!devmode->dmPelsHeight) devmode->dmPelsHeight = current_mode.dmPelsHeight; }
return devmode; @@ -2070,8 +2071,8 @@ static DEVMODEW *validate_display_settings( DEVMODEW *default_mode, DEVMODEW *cu LONG WINAPI NtUserChangeDisplaySettings( UNICODE_STRING *devname, DEVMODEW *devmode, HWND hwnd, DWORD flags, void *lparam ) { - DEVMODEW default_mode = {.dmSize = sizeof(DEVMODEW)}, current_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;
@@ -2099,10 +2100,7 @@ LONG WINAPI NtUserChangeDisplaySettings( UNICODE_STRING *devname, DEVMODEW *devm return DISP_CHANGE_BADPARAM; }
- if (!read_registry_settings( adapter_path, &default_mode )) default_mode.dmSize = 0; - if (!NtUserEnumDisplaySettings( devname, ENUM_CURRENT_SETTINGS, ¤t_mode, 0 )) current_mode.dmSize = 0; - - if (!(devmode = validate_display_settings( &default_mode, ¤t_mode, devmode ))) ret = DISP_CHANGE_BADMODE; + 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; 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;
From: R��mi Bernon rbernon@codeweavers.com
So that updating dmPelsWidth / dmPelsHeight doesn't modify user devmode. --- dlls/win32u/sysparams.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 514585a0988..fb5b90af414 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2041,12 +2041,13 @@ static DEVMODEW *validate_display_settings( const WCHAR *adapter_path, const WCH devmode = NULL; }
- if (!devmode) + if (devmode) memcpy( temp_mode, devmode, devmode->dmSize ); + else { if (!read_registry_settings( adapter_path, temp_mode )) return NULL; TRACE( "Return to original display mode\n" ); - devmode = temp_mode; } + devmode = temp_mode;
if ((devmode->dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) != (DM_PELSWIDTH | DM_PELSHEIGHT)) {
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 7 ++++++- dlls/winex11.drv/display.c | 10 ---------- 2 files changed, 6 insertions(+), 11 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index fb5b90af414..edf094cd1e7 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2055,12 +2055,17 @@ static DEVMODEW *validate_display_settings( const WCHAR *adapter_path, const WCH return NULL; }
- if (!is_detached_mode( devmode ) && (!devmode->dmPelsWidth || !devmode->dmPelsHeight)) + if (!is_detached_mode( devmode ) && (!devmode->dmPelsWidth || !devmode->dmPelsHeight || !(devmode->dmFields & DM_POSITION))) { DEVMODEW current_mode = {.dmSize = sizeof(DEVMODEW)}; if (!user_driver->pGetCurrentDisplaySettings( device_name, ¤t_mode )) return NULL; if (!devmode->dmPelsWidth) devmode->dmPelsWidth = current_mode.dmPelsWidth; if (!devmode->dmPelsHeight) devmode->dmPelsHeight = current_mode.dmPelsHeight; + if (!(devmode->dmFields & DM_POSITION)) + { + devmode->dmPosition = current_mode.dmPosition; + devmode->dmFields |= DM_POSITION; + } }
return devmode; diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 32ed1bf3032..c9f2da7e163 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -498,16 +498,6 @@ static LONG get_display_settings(DEVMODEW **new_displays, const WCHAR *dev_name, else if (!wcsicmp(dev_name, display_device.DeviceName)) { *mode = *dev_mode; - if (!(dev_mode->dmFields & DM_POSITION)) - { - memset(¤t_mode, 0, sizeof(current_mode)); - current_mode.dmSize = sizeof(current_mode); - if (!NtUserEnumDisplaySettings( &device_name, ENUM_CURRENT_SETTINGS, ¤t_mode, 0 )) - goto done; - - mode->dmFields |= DM_POSITION; - mode->dmPosition = current_mode.dmPosition; - } } else {
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index edf094cd1e7..7f69d71e80e 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -429,16 +429,20 @@ static BOOL write_adapter_mode( HKEY adapter_key, DWORD index, const DEVMODEW *m { WCHAR bufferW[MAX_PATH]; char buffer[MAX_PATH]; + BOOL ret = TRUE; HKEY hkey; - BOOL ret;
sprintf( buffer, "Modes\%08X", index ); + reg_delete_tree( adapter_key, bufferW, asciiz_to_unicode( bufferW, buffer ) - sizeof(WCHAR) ); if (!(hkey = reg_create_key( adapter_key, bufferW, asciiz_to_unicode( bufferW, buffer ) - sizeof(WCHAR), REG_OPTION_VOLATILE, NULL ))) return FALSE;
-#define set_mode_field( name, field, flag ) \ - if (!(ret = set_reg_value( hkey, (name), REG_DWORD, &mode->field, sizeof(mode->field) ))) goto done; +#define set_mode_field( name, field, flag ) \ + if ((mode->dmFields & (flag)) && \ + !(ret = set_reg_value( hkey, (name), REG_DWORD, &mode->field, \ + sizeof(mode->field) ))) \ + goto done
set_mode_field( bits_per_pelW, dmBitsPerPel, DM_BITSPERPEL ); set_mode_field( x_resolutionW, dmPelsWidth, DM_PELSWIDTH ); @@ -467,7 +471,6 @@ static BOOL read_adapter_mode( HKEY adapter_key, DWORD index, DEVMODEW *mode ) WCHAR bufferW[MAX_PATH]; char buffer[MAX_PATH]; HKEY hkey; - BOOL ret;
sprintf( buffer, "Modes\%08X", index ); if (!(hkey = reg_open_key( adapter_key, bufferW, asciiz_to_unicode( bufferW, buffer ) - sizeof(WCHAR) ))) @@ -476,11 +479,12 @@ static BOOL read_adapter_mode( HKEY adapter_key, DWORD index, DEVMODEW *mode ) #define query_mode_field( name, field, flag ) \ do \ { \ - ret = query_reg_value( hkey, (name), value, sizeof(value_buf) ) && \ - value->Type == REG_DWORD; \ - if (!ret) goto done; \ - mode->field = *(const DWORD *)value->Data; \ - mode->dmFields |= (flag); \ + if (query_reg_value( hkey, (name), value, sizeof(value_buf) ) && \ + value->Type == REG_DWORD) \ + { \ + mode->field = *(const DWORD *)value->Data; \ + mode->dmFields |= (flag); \ + } \ } while (0)
query_mode_field( bits_per_pelW, dmBitsPerPel, DM_BITSPERPEL ); @@ -488,17 +492,16 @@ static BOOL read_adapter_mode( HKEY adapter_key, DWORD index, DEVMODEW *mode ) query_mode_field( y_resolutionW, dmPelsHeight, DM_PELSHEIGHT ); query_mode_field( v_refreshW, dmDisplayFrequency, DM_DISPLAYFREQUENCY ); query_mode_field( flagsW, dmDisplayFlags, DM_DISPLAYFLAGS ); + query_mode_field( orientationW, dmDisplayOrientation, DM_DISPLAYORIENTATION ); + query_mode_field( fixed_outputW, dmDisplayFixedOutput, DM_DISPLAYFIXEDOUTPUT ); if (index == ENUM_CURRENT_SETTINGS || index == ENUM_REGISTRY_SETTINGS) { query_mode_field( x_panningW, dmPosition.x, DM_POSITION ); query_mode_field( y_panningW, dmPosition.y, DM_POSITION ); } - query_mode_field( orientationW, dmDisplayOrientation, DM_DISPLAYORIENTATION ); - query_mode_field( fixed_outputW, dmDisplayFixedOutput, 0 );
#undef query_mode_field
-done: NtClose( hkey ); return TRUE; }
On Mon Aug 22 07:33:07 2022 +0000, R��mi Bernon wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/665/diffs?diff_id=8393&start_sha=2e1a6737d4d6fad617fb506217c32c66665fc399#85770a8b187bd82db4dbb9a2b8a5f34616049d0f_494_497)
I've kept it both for read and write, I think the symmetry is important and it makes it obvious that current and registry modes never have these fields.
This merge request was approved by Zhiyi Zhang.