With this series it's now possible to run and pass `user32:monitor` and `user32:sysparams` tests with nulldrv, and so most `user32` tests (except for a few desktop cursor position tests). This still requires some prefix configuration to enable the nulldrv driver, or a change like https://gitlab.winehq.org/rbernon/wine/-/commit/753368ad0ec52f03f8d6e78ca794... to enable it when `DISPLAY` environment variable is unset.
This then shows that some of the user32 tests are failing with winex11 but passing with nulldrv, as in https://gitlab.winehq.org/rbernon/wine/-/commit/6d5f4109a514a0dc266899fcacfa....
-- v5: win32u: Read mode from the registry if GetCurrentDisplaySettings fails. win32u: Write display settings to the registry in apply_display_settings. win32u: Lock display devices while applying display settings. win32u: Force update display cache after NtUserChangeDisplaySettingsEx. win32u: Introduce a new VirtualScreenRectChanged display driver callback. win32u: Add a BOOL force parameter to update_display_cache.
From: Rémi Bernon rbernon@codeweavers.com
And call it recursively with force = TRUE instead of calling graphics driver pUpdateDisplayDevices separately. --- dlls/win32u/sysparams.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 494bb94c7f1..efa17aec825 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1552,7 +1552,7 @@ static BOOL update_display_cache_from_registry(void) return ret; }
-static BOOL update_display_cache(void) +static BOOL update_display_cache( BOOL force ) { HWINSTA winstation = NtUserGetProcessWindowStation(); struct device_manager_ctx ctx = {0}; @@ -1569,17 +1569,7 @@ static BOOL update_display_cache(void) return TRUE; }
- user_driver->pUpdateDisplayDevices( &device_manager, FALSE, &ctx ); - release_display_manager_ctx( &ctx ); - - if (update_display_cache_from_registry()) return TRUE; - if (ctx.gpu_count) - { - ERR( "driver reported devices, but we failed to read them\n" ); - return FALSE; - } - - if (!user_driver->pUpdateDisplayDevices( &device_manager, TRUE, &ctx )) + if (!user_driver->pUpdateDisplayDevices( &device_manager, force, &ctx ) && force) { static const DEVMODEW modes[] = { @@ -1618,15 +1608,27 @@ static BOOL update_display_cache(void)
if (!update_display_cache_from_registry()) { - ERR( "failed to read display config\n" ); - return FALSE; + if (force) + { + ERR( "Failed to read display config.\n" ); + return FALSE; + } + + if (ctx.gpu_count) + { + ERR( "Driver reported devices, but we failed to read them.\n" ); + return FALSE; + } + + return update_display_cache( TRUE ); } + return TRUE; }
static BOOL lock_display_devices(void) { - if (!update_display_cache()) return FALSE; + if (!update_display_cache( FALSE )) return FALSE; pthread_mutex_lock( &display_lock ); return TRUE; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/driver.c | 11 +++++++++++ dlls/win32u/sysparams.c | 11 +++++++++++ dlls/winex11.drv/display.c | 13 +++++-------- dlls/winex11.drv/init.c | 1 + dlls/winex11.drv/x11drv.h | 2 +- dlls/winex11.drv/xrandr.c | 2 +- include/wine/gdi_driver.h | 1 + 7 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index ee4a6534b50..d9c1f0d6f6d 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -769,6 +769,10 @@ static BOOL nulldrv_UpdateDisplayDevices( const struct gdi_device_manager *manag return FALSE; }
+static void nulldrv_VirtualScreenRectChanged( RECT *old_rect, RECT *new_rect ) +{ +} + static BOOL nulldrv_CreateDesktopWindow( HWND hwnd ) { return TRUE; @@ -1112,6 +1116,11 @@ static BOOL loaderdrv_UpdateDisplayDevices( const struct gdi_device_manager *man return load_driver()->pUpdateDisplayDevices( manager, force, param ); }
+static void loaderdrv_VirtualScreenRectChanged( RECT *old_rect, RECT *new_rect ) +{ + return load_driver()->pVirtualScreenRectChanged( old_rect, new_rect ); +} + static BOOL loaderdrv_CreateDesktopWindow( HWND hwnd ) { return load_driver()->pCreateDesktopWindow( hwnd ); @@ -1180,6 +1189,7 @@ static const struct user_driver_funcs lazy_load_driver = loaderdrv_ChangeDisplaySettings, loaderdrv_GetCurrentDisplaySettings, loaderdrv_UpdateDisplayDevices, + loaderdrv_VirtualScreenRectChanged, /* windowing functions */ loaderdrv_CreateDesktopWindow, loaderdrv_CreateWindow, @@ -1255,6 +1265,7 @@ void __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT version SET_USER_FUNC(ChangeDisplaySettings); SET_USER_FUNC(GetCurrentDisplaySettings); SET_USER_FUNC(UpdateDisplayDevices); + SET_USER_FUNC(VirtualScreenRectChanged); SET_USER_FUNC(CreateDesktopWindow); SET_USER_FUNC(CreateWindow); SET_USER_FUNC(DesktopWindowProc); diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index efa17aec825..0d0d3648b38 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1555,7 +1555,9 @@ static BOOL update_display_cache_from_registry(void) static BOOL update_display_cache( BOOL force ) { HWINSTA winstation = NtUserGetProcessWindowStation(); + RECT old_virtual_rect = {0}, new_virtual_rect = {0}; struct device_manager_ctx ctx = {0}; + struct monitor *monitor; USEROBJECTFLAGS flags;
/* services do not have any adapters, only a virtual monitor */ @@ -1569,6 +1571,9 @@ static BOOL update_display_cache( BOOL force ) return TRUE; }
+ LIST_FOR_EACH_ENTRY( monitor, &monitors, struct monitor, entry ) + union_rect( &old_virtual_rect, &old_virtual_rect, &monitor->rc_monitor ); + if (!user_driver->pUpdateDisplayDevices( &device_manager, force, &ctx ) && force) { static const DEVMODEW modes[] = @@ -1623,6 +1628,12 @@ static BOOL update_display_cache( BOOL force ) return update_display_cache( TRUE ); }
+ LIST_FOR_EACH_ENTRY( monitor, &monitors, struct monitor, entry ) + union_rect( &new_virtual_rect, &new_virtual_rect, &monitor->rc_monitor ); + + if (!IsRectEmpty( &old_virtual_rect ) && !EqualRect( &old_virtual_rect, &new_virtual_rect )) + user_driver->pVirtualScreenRectChanged( &old_virtual_rect, &new_virtual_rect ); + return TRUE; }
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 76defa7f0e8..b80ec825980 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -419,7 +419,7 @@ LONG X11DRV_ChangeDisplaySettings( LPDEVMODEW displays, HWND hwnd, DWORD flags, if (ret == DISP_CHANGE_SUCCESSFUL) ret = apply_display_settings( displays, ids, TRUE ); if (ret == DISP_CHANGE_SUCCESSFUL) - X11DRV_DisplayDevices_Update(); + X11DRV_DisplayDevices_Init(TRUE);
done: free( ids ); @@ -558,22 +558,19 @@ void X11DRV_DisplayDevices_RegisterEventHandlers(void) handler->register_event_handlers(); }
-void X11DRV_DisplayDevices_Update(void) +void X11DRV_VirtualScreenRectChanged( RECT *old_rect, RECT *new_rect ) { - RECT old_virtual_rect, new_virtual_rect; DWORD tid, pid; HWND foreground; UINT mask = 0, i; HWND *list;
- old_virtual_rect = NtUserGetVirtualScreenRect(); - X11DRV_DisplayDevices_Init(TRUE); - new_virtual_rect = NtUserGetVirtualScreenRect(); + TRACE( "old_rect %s, new_rect %s.\n", wine_dbgstr_rect(old_rect), wine_dbgstr_rect(new_rect) );
/* Calculate XReconfigureWMWindow() mask */ - if (old_virtual_rect.left != new_virtual_rect.left) + if (old_rect->left != new_rect->left) mask |= CWX; - if (old_virtual_rect.top != new_virtual_rect.top) + if (old_rect->top != new_rect->top) mask |= CWY;
X11DRV_resize_desktop(); diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index 4ebe3a16367..6d7614a45da 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -406,6 +406,7 @@ static const struct user_driver_funcs x11drv_funcs = .pChangeDisplaySettings = X11DRV_ChangeDisplaySettings, .pGetCurrentDisplaySettings = X11DRV_GetCurrentDisplaySettings, .pUpdateDisplayDevices = X11DRV_UpdateDisplayDevices, + .pVirtualScreenRectChanged = X11DRV_VirtualScreenRectChanged, .pCreateDesktopWindow = X11DRV_CreateDesktopWindow, .pCreateWindow = X11DRV_CreateWindow, .pDesktopWindowProc = X11DRV_DesktopWindowProc, diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index d1a70da9998..5c17d15047b 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -215,6 +215,7 @@ extern BOOL X11DRV_GetCursorPos( LPPOINT pos ) DECLSPEC_HIDDEN; extern BOOL X11DRV_ClipCursor( LPCRECT clip ) DECLSPEC_HIDDEN; extern LONG X11DRV_ChangeDisplaySettings( LPDEVMODEW displays, HWND hwnd, DWORD flags, LPVOID lpvoid ) DECLSPEC_HIDDEN; extern BOOL X11DRV_GetCurrentDisplaySettings( LPCWSTR name, LPDEVMODEW devmode ) DECLSPEC_HIDDEN; +extern void X11DRV_VirtualScreenRectChanged( RECT *old_rect, RECT *new_rect ) DECLSPEC_HIDDEN; extern BOOL X11DRV_UpdateDisplayDevices( const struct gdi_device_manager *device_manager, BOOL force, void *param ) DECLSPEC_HIDDEN; extern BOOL X11DRV_CreateDesktopWindow( HWND hwnd ) DECLSPEC_HIDDEN; @@ -804,7 +805,6 @@ extern BOOL get_host_primary_gpu(struct gdi_gpu *gpu) DECLSPEC_HIDDEN; extern void X11DRV_DisplayDevices_SetHandler(const struct x11drv_display_device_handler *handler) DECLSPEC_HIDDEN; extern void X11DRV_DisplayDevices_Init(BOOL force) DECLSPEC_HIDDEN; extern void X11DRV_DisplayDevices_RegisterEventHandlers(void) DECLSPEC_HIDDEN; -extern void X11DRV_DisplayDevices_Update(void) DECLSPEC_HIDDEN; /* Display device handler used in virtual desktop mode */ extern struct x11drv_display_device_handler desktop_handler DECLSPEC_HIDDEN;
diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c index a0ac2cb5ec1..3d1b6a917cf 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -1198,7 +1198,7 @@ static BOOL xrandr14_device_change_handler( HWND hwnd, XEvent *event ) xrandr14_invalidate_current_mode_cache(); if (hwnd == NtUserGetDesktopWindow() && NtUserGetWindowThread( hwnd, NULL ) == GetCurrentThreadId()) { - X11DRV_DisplayDevices_Update(); + X11DRV_DisplayDevices_Init(TRUE); init_registry_display_settings(); } return FALSE; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 596d27156af..27f5ce27d58 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -300,6 +300,7 @@ struct user_driver_funcs LONG (*pChangeDisplaySettings)(LPDEVMODEW,HWND,DWORD,LPVOID); BOOL (*pGetCurrentDisplaySettings)(LPCWSTR,LPDEVMODEW); BOOL (*pUpdateDisplayDevices)(const struct gdi_device_manager *,BOOL,void*); + void (*pVirtualScreenRectChanged)(RECT*,RECT*); /* windowing functions */ BOOL (*pCreateDesktopWindow)(HWND); BOOL (*pCreateWindow)(HWND);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 2 ++ dlls/winemac.drv/display.c | 3 --- dlls/winex11.drv/display.c | 2 -- 3 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 0d0d3648b38..b7ab0a6880d 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2494,6 +2494,8 @@ static LONG apply_display_settings( const WCHAR *devname, const DEVMODEW *devmod free( displays ); if (ret) return ret;
+ if (!update_display_cache( TRUE )) WARN( "Failed to update display cache after mode change.\n" ); + if ((adapter = find_adapter( NULL ))) { DEVMODEW current_mode = {.dmSize = sizeof(DEVMODEW)}; diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 977949fc47f..ff8cf51754c 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -831,10 +831,7 @@ LONG macdrv_ChangeDisplaySettings(LPDEVMODEW displays, HWND hwnd, DWORD flags, L ret = DISP_CHANGE_BADMODE; } else if (macdrv_set_display_mode(&macdrv_displays[0], best_display_mode)) - { - macdrv_init_display_devices(TRUE); send_message(NtUserGetDesktopWindow(), WM_MACDRV_UPDATE_DESKTOP_RECT, 0, 0); - } else { WARN("Failed to set display mode\n"); diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index b80ec825980..78ab5dcf8be 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -418,8 +418,6 @@ LONG X11DRV_ChangeDisplaySettings( LPDEVMODEW displays, HWND hwnd, DWORD flags, ret = apply_display_settings( displays, ids, FALSE ); if (ret == DISP_CHANGE_SUCCESSFUL) ret = apply_display_settings( displays, ids, TRUE ); - if (ret == DISP_CHANGE_SUCCESSFUL) - X11DRV_DisplayDevices_Init(TRUE);
done: free( ids );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index b7ab0a6880d..4be1e0b9a3b 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2252,10 +2252,8 @@ static DEVMODEW *get_display_settings( const WCHAR *devname, const DEVMODEW *dev struct adapter *adapter; BOOL ret;
- if (!lock_display_devices()) return NULL; - /* allocate an extra mode for easier iteration */ - if (!(displays = calloc( list_count( &adapters ) + 1, sizeof(DEVMODEW) ))) goto done; + if (!(displays = calloc( list_count( &adapters ) + 1, sizeof(DEVMODEW) ))) return NULL; mode = displays;
LIST_FOR_EACH_ENTRY( adapter, &adapters, struct adapter, entry ) @@ -2267,20 +2265,18 @@ static DEVMODEW *get_display_settings( const WCHAR *devname, const DEVMODEW *dev { if (!devname) ret = adapter_get_registry_settings( adapter, mode ); else ret = user_driver->pGetCurrentDisplaySettings( adapter->dev.device_name, mode ); - if (!ret) goto done; + if (!ret) + { + free( displays ); + return NULL; + } }
lstrcpyW( mode->dmDeviceName, adapter->dev.device_name ); mode = NEXT_DEVMODEW(mode); }
- unlock_display_devices(); return displays; - -done: - unlock_display_devices(); - free( displays ); - return NULL; }
static INT offset_length( POINT offset ) @@ -2477,11 +2473,16 @@ static LONG apply_display_settings( const WCHAR *devname, const DEVMODEW *devmod DEVMODEW *displays; LONG ret;
- displays = get_display_settings( devname, devmode ); - if (!displays) return DISP_CHANGE_FAILED; + if (!lock_display_devices()) return DISP_CHANGE_FAILED; + if (!(displays = get_display_settings( devname, devmode ))) + { + unlock_display_devices(); + return DISP_CHANGE_FAILED; + }
if (all_detached_settings( displays )) { + unlock_display_devices(); WARN( "Detaching all modes is not permitted.\n" ); free( displays ); return DISP_CHANGE_SUCCESSFUL; @@ -2490,7 +2491,7 @@ static LONG apply_display_settings( const WCHAR *devname, const DEVMODEW *devmod place_all_displays( displays );
ret = user_driver->pChangeDisplaySettings( displays, hwnd, flags, lparam ); - + unlock_display_devices(); free( displays ); if (ret) return ret;
From: Rémi Bernon rbernon@codeweavers.com
As a fallback if ChangeDisplaySettings returns E_NOTIMPL. --- dlls/win32u/driver.c | 2 +- dlls/win32u/sysparams.c | 50 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 5 deletions(-)
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index d9c1f0d6f6d..5341dafac6d 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -756,7 +756,7 @@ static void nulldrv_UpdateClipboard(void) static LONG nulldrv_ChangeDisplaySettings( LPDEVMODEW displays, HWND hwnd, DWORD flags, LPVOID lparam ) { - return DISP_CHANGE_FAILED; + return E_NOTIMPL; }
static BOOL nulldrv_GetCurrentDisplaySettings( LPCWSTR name, LPDEVMODEW mode ) diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 4be1e0b9a3b..d74c9bfbf5b 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -562,6 +562,26 @@ static BOOL adapter_set_registry_settings( const struct adapter *adapter, const return ret; }
+static BOOL adapter_set_current_settings( const struct adapter *adapter, const DEVMODEW *mode ) +{ + HANDLE mutex; + HKEY hkey; + BOOL ret; + + mutex = get_display_device_init_mutex(); + + if (!config_key && !(config_key = reg_open_key( NULL, config_keyW, sizeof(config_keyW) ))) ret = FALSE; + if (!(hkey = reg_open_key( config_key, adapter->config_key, lstrlenW( adapter->config_key ) * sizeof(WCHAR) ))) ret = FALSE; + else + { + ret = write_adapter_mode( hkey, ENUM_CURRENT_SETTINGS, mode ); + NtClose( hkey ); + } + + release_display_device_init_mutex( mutex ); + return ret; +} + static int mode_compare(const void *p1, const void *p2) { BOOL a_interlaced, b_interlaced, a_stretched, b_stretched; @@ -1599,13 +1619,24 @@ static BOOL update_display_cache( BOOL force ) struct gdi_monitor monitor = { .state_flags = DISPLAY_DEVICE_ACTIVE | DISPLAY_DEVICE_ATTACHED, - .rc_monitor = {.right = modes[2].dmPelsWidth, .bottom = modes[2].dmPelsHeight}, - .rc_work = {.right = modes[2].dmPelsWidth, .bottom = modes[2].dmPelsHeight}, }; + DEVMODEW mode = {{0}}; UINT i;
add_gpu( &gpu, &ctx ); add_adapter( &adapter, &ctx ); + + if (!read_adapter_mode( ctx.adapter_key, ENUM_CURRENT_SETTINGS, &mode )) + { + mode = modes[2]; + mode.dmFields |= DM_POSITION; + write_adapter_mode( ctx.adapter_key, ENUM_CURRENT_SETTINGS, &mode ); + } + monitor.rc_monitor.right = mode.dmPelsWidth; + monitor.rc_monitor.bottom = mode.dmPelsHeight; + monitor.rc_work.right = mode.dmPelsWidth; + monitor.rc_work.bottom = mode.dmPelsHeight; + add_monitor( &monitor, &ctx ); for (i = 0; i < ARRAY_SIZE(modes); ++i) add_mode( modes + i, &ctx ); } @@ -2469,8 +2500,8 @@ static BOOL all_detached_settings( const DEVMODEW *displays ) static LONG apply_display_settings( const WCHAR *devname, const DEVMODEW *devmode, HWND hwnd, DWORD flags, void *lparam ) { + DEVMODEW *mode, *displays; struct adapter *adapter; - DEVMODEW *displays; LONG ret;
if (!lock_display_devices()) return DISP_CHANGE_FAILED; @@ -2490,8 +2521,19 @@ static LONG apply_display_settings( const WCHAR *devname, const DEVMODEW *devmod
place_all_displays( displays );
- ret = user_driver->pChangeDisplaySettings( displays, hwnd, flags, lparam ); + if ((ret = user_driver->pChangeDisplaySettings( displays, hwnd, flags, lparam )) == E_NOTIMPL) + { + mode = displays; + LIST_FOR_EACH_ENTRY( adapter, &adapters, struct adapter, entry ) + { + if (!adapter_set_current_settings( adapter, mode )) + WARN( "Failed to write adapter %s current mode.\n", debugstr_w(adapter->dev.device_name) ); + mode = NEXT_DEVMODEW(mode); + } + ret = DISP_CHANGE_SUCCESSFUL; + } unlock_display_devices(); + free( displays ); if (ret) return ret;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index d74c9bfbf5b..9039373c254 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -542,6 +542,28 @@ static BOOL adapter_get_registry_settings( const struct adapter *adapter, DEVMOD return ret; }
+static BOOL adapter_get_current_settings( const struct adapter *adapter, DEVMODEW *mode ) +{ + BOOL ret = FALSE; + HANDLE mutex; + HKEY hkey; + + if (user_driver->pGetCurrentDisplaySettings( adapter->dev.device_name, mode )) return TRUE; + + mutex = get_display_device_init_mutex(); + + if (!config_key && !(config_key = reg_open_key( NULL, config_keyW, sizeof(config_keyW) ))) ret = FALSE; + else if (!(hkey = reg_open_key( config_key, adapter->config_key, lstrlenW( adapter->config_key ) * sizeof(WCHAR) ))) ret = FALSE; + else + { + ret = read_adapter_mode( hkey, ENUM_CURRENT_SETTINGS, mode ); + NtClose( hkey ); + } + + release_display_device_init_mutex( mutex ); + return ret; +} + static BOOL adapter_set_registry_settings( const struct adapter *adapter, const DEVMODEW *mode ) { HANDLE mutex; @@ -2256,7 +2278,7 @@ static BOOL adapter_get_full_mode( const struct adapter *adapter, const DEVMODEW if (!is_detached_mode( full_mode ) && (!full_mode->dmPelsWidth || !full_mode->dmPelsHeight || !(full_mode->dmFields & DM_POSITION))) { DEVMODEW current_mode = {.dmSize = sizeof(DEVMODEW)}; - if (!user_driver->pGetCurrentDisplaySettings( adapter->dev.device_name, ¤t_mode )) return FALSE; + if (!adapter_get_current_settings( adapter, ¤t_mode )) return FALSE; if (!full_mode->dmPelsWidth) full_mode->dmPelsWidth = current_mode.dmPelsWidth; if (!full_mode->dmPelsHeight) full_mode->dmPelsHeight = current_mode.dmPelsHeight; if (!(full_mode->dmFields & DM_POSITION)) @@ -2295,7 +2317,7 @@ static DEVMODEW *get_display_settings( const WCHAR *devname, const DEVMODEW *dev else { if (!devname) ret = adapter_get_registry_settings( adapter, mode ); - else ret = user_driver->pGetCurrentDisplaySettings( adapter->dev.device_name, mode ); + else ret = adapter_get_current_settings( adapter, mode ); if (!ret) { free( displays ); @@ -2542,7 +2564,7 @@ static LONG apply_display_settings( const WCHAR *devname, const DEVMODEW *devmod if ((adapter = find_adapter( NULL ))) { DEVMODEW current_mode = {.dmSize = sizeof(DEVMODEW)}; - user_driver->pGetCurrentDisplaySettings( adapter->dev.device_name, ¤t_mode ); + if (!adapter_get_current_settings( adapter, ¤t_mode )) WARN( "Failed to get primary adapter current display settings.\n" ); adapter_release( adapter );
send_message_timeout( HWND_BROADCAST, WM_DISPLAYCHANGE, current_mode.dmBitsPerPel, @@ -2585,7 +2607,7 @@ static BOOL adapter_enum_display_settings( const struct adapter *adapter, DWORD DEVMODEW current_mode = {.dmSize = sizeof(DEVMODEW)}; const DEVMODEW *adapter_mode;
- if (!(flags & EDS_ROTATEDMODE) && !user_driver->pGetCurrentDisplaySettings( adapter->dev.device_name, ¤t_mode )) + if (!(flags & EDS_ROTATEDMODE) && !adapter_get_current_settings( adapter, ¤t_mode )) { WARN( "Failed to query current display mode for EDS_ROTATEDMODE flag.\n" ); return FALSE; @@ -2633,7 +2655,7 @@ BOOL WINAPI NtUserEnumDisplaySettings( UNICODE_STRING *device, DWORD index, DEVM devmode->dmDriverExtra = 0;
if (index == ENUM_REGISTRY_SETTINGS) ret = adapter_get_registry_settings( adapter, devmode ); - else if (index == ENUM_CURRENT_SETTINGS) ret = user_driver->pGetCurrentDisplaySettings( adapter->dev.device_name, devmode ); + else if (index == ENUM_CURRENT_SETTINGS) ret = adapter_get_current_settings( adapter, devmode ); else ret = adapter_enum_display_settings( adapter, index, devmode, flags ); adapter_release( adapter );
On Mon Sep 26 18:08:46 2022 +0000, Rémi Bernon wrote:
changed this line in [version 5 of the diff](/wine/wine/-/merge_requests/551/diffs?diff_id=12173&start_sha=b6ae8845ed5bd5b28bca6e5a05da58a16a2f0104#85770a8b187bd82db4dbb9a2b8a5f34616049d0f_1656_1657)
Yeah I guess, thanks.
Zhiyi Zhang (@zhiyi) commented about dlls/win32u/driver.c:
return load_driver()->pUpdateDisplayDevices( manager, force, param );
}
+static void loaderdrv_VirtualScreenRectChanged( RECT *old_rect, RECT *new_rect ) +{
- return load_driver()->pVirtualScreenRectChanged( old_rect, new_rect );
No need to use return.
Zhiyi Zhang (@zhiyi) commented about dlls/win32u/sysparams.c:
return TRUE; }
- LIST_FOR_EACH_ENTRY( monitor, &monitors, struct monitor, entry )
Shouldn't you take the display_lock while accessing monitors?
On Tue Sep 27 03:01:49 2022 +0000, Zhiyi Zhang wrote:
Shouldn't you take the display_lock while accessing monitors?
I guess... though I'm thinking that we may need to make sure the cache update and virtual screen notification are kept atomic.
FWIW, I'm also considering changing the `VirtualScreenRectChanged` call to always call it, and only pass the new virtual screen rect and primary monitor rects. That way display drivers could keep them internally, to get the old rects, and remove the need for `NtUserGetVirtualScreenRect` / `NtUserGetPrimaryScreenRect` callbacks entirely.
Then all of this is going to be difficult because some of the calls may need to enter the display lock recursively. This is already the case when loading the display driver, as the lazy initialization will need to load icons for builtin window classes and get the lock for the display DC, but also for some of the things winex11 does when virtual screen is resized (like moving windows, etc).
Is there any reason not to use a recursive mutex for the display lock? It would solve the problem more easily. @jacek maybe has an opinion?
Alternatively I can acquire the display lock just for the monitor enumeration but it makes the cache update and notification racy.
On Tue Sep 27 12:04:45 2022 +0000, Rémi Bernon wrote:
I guess... though I'm thinking that we may need to make sure the cache update and virtual screen notification are kept atomic. FWIW, I'm also considering changing the `VirtualScreenRectChanged` call to always call it, and only pass the new virtual screen rect and primary monitor rects. That way display drivers could keep them internally, to get the old rects, and remove the need for `NtUserGetVirtualScreenRect` / `NtUserGetPrimaryMonitorRect` callbacks entirely. Then all of this is going to be difficult because some of the calls may need to enter the display lock recursively. This is already the case when loading the display driver, as the lazy initialization will need to load icons for builtin window classes and get the lock for the display DC, but also for some of the things winex11 does when virtual screen is resized (like moving windows, etc). Is there any reason not to use a recursive mutex for the display lock? It would solve the problem more easily. @jacek maybe has an opinion? Alternatively I can acquire the display lock just for the monitor enumeration but it makes the cache update and notification racy.
I'll try something else. I think that the desktop resize logic doesn't need to be synchronous, as long as it's done after each display mode change.
We can later add the entry point to notify of virtual screen / monitor rect changes, and be able to remove the `NtUser` callbacks, but it's possibly not necessary for this.