From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57504 --- dlls/win32u/sysparams.c | 48 +++++++++++++++++++++++++++++------- dlls/win32u/win32u_private.h | 1 + dlls/win32u/winstation.c | 2 ++ 3 files changed, 42 insertions(+), 9 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 8ae3823fd53..df3f9aa639b 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -156,6 +156,7 @@ static struct list gpus = LIST_INIT(gpus); static struct list sources = LIST_INIT(sources); static struct list monitors = LIST_INIT(monitors); static INT64 last_query_display_time; +static UINT64 monitor_update_serial; static pthread_mutex_t display_lock = PTHREAD_MUTEX_INITIALIZER;
static BOOL emulate_modeset; @@ -1850,7 +1851,7 @@ static void monitor_get_info( struct monitor *monitor, MONITORINFO *info, UINT d }
/* display_lock must be held */ -static void set_winstation_monitors(void) +static void set_winstation_monitors( BOOL increment ) { struct monitor_info *infos, *info; struct monitor *monitor; @@ -1872,8 +1873,9 @@ static void set_winstation_monitors(void)
SERVER_START_REQ( set_winstation_monitors ) { + req->increment = increment; wine_server_add_data( req, infos, count * sizeof(*infos) ); - wine_server_call( req ); + if (!wine_server_call( req )) monitor_update_serial = reply->serial; } SERVER_END_REQ;
@@ -1965,7 +1967,7 @@ static struct monitor *find_monitor_from_path( const char *path ) return NULL; }
-static BOOL update_display_cache_from_registry(void) +static BOOL update_display_cache_from_registry( UINT64 serial ) { char path[MAX_PATH]; DWORD source_id, monitor_id, monitor_count = 0, size; @@ -1989,7 +1991,11 @@ static BOOL update_display_cache_from_registry(void) if (status && status != STATUS_BUFFER_OVERFLOW) return FALSE;
- if (key.LastWriteTime.QuadPart <= last_query_display_time) return TRUE; + if (key.LastWriteTime.QuadPart <= last_query_display_time) + { + monitor_update_serial = serial; + return TRUE; + }
mutex = get_display_device_init_mutex();
@@ -2046,7 +2052,7 @@ static BOOL update_display_cache_from_registry(void) if ((ret = !list_empty( &sources ) && !list_empty( &monitors ))) last_query_display_time = key.LastWriteTime.QuadPart;
- set_winstation_monitors(); + set_winstation_monitors( FALSE ); release_display_device_init_mutex( mutex ); return ret; } @@ -2230,7 +2236,27 @@ static void commit_display_devices( struct device_manager_ctx *ctx ) add_gpu( gpu->name, &gpu->pci_id, &gpu->uuid, ctx ); }
- set_winstation_monitors(); + set_winstation_monitors( TRUE ); +} + +static UINT64 get_monitor_update_serial(void) +{ + struct object_lock lock = OBJECT_LOCK_INIT; + const desktop_shm_t *desktop_shm; + UINT64 serial = 0; + NTSTATUS status; + + while ((status = get_shared_desktop( &lock, &desktop_shm )) == STATUS_PENDING) + serial = desktop_shm->monitor_serial; + + return status ? 0 : serial; +} + +void reset_monitor_update_serial(void) +{ + pthread_mutex_lock( &display_lock ); + monitor_update_serial = 0; + pthread_mutex_unlock( &display_lock ); }
static BOOL lock_display_devices( BOOL force ) @@ -2238,6 +2264,7 @@ static BOOL lock_display_devices( BOOL force ) static const WCHAR wine_service_station_name[] = {'_','_','w','i','n','e','s','e','r','v','i','c','e','_','w','i','n','s','t','a','t','i','o','n',0}; struct device_manager_ctx ctx = {.vulkan_gpus = LIST_INIT(ctx.vulkan_gpus)}; + UINT64 serial; UINT status; WCHAR name[MAX_PATH]; BOOL ret = TRUE; @@ -2246,17 +2273,20 @@ static BOOL lock_display_devices( BOOL force )
pthread_mutex_lock( &display_lock );
+ serial = get_monitor_update_serial(); + if (!force && monitor_update_serial >= serial) return TRUE; + /* services do not have any adapters, only a virtual monitor */ if (NtUserGetObjectInformation( NtUserGetProcessWindowStation(), UOI_NAME, name, sizeof(name), NULL ) && !wcscmp( name, wine_service_station_name )) { clear_display_devices(); list_add_tail( &monitors, &virtual_monitor.entry ); - set_winstation_monitors(); + set_winstation_monitors( TRUE ); return TRUE; }
- if (!force && !update_display_cache_from_registry()) force = TRUE; + if (!force && !update_display_cache_from_registry( serial )) force = TRUE; if (force) { if (!get_vulkan_gpus( &ctx.vulkan_gpus )) WARN( "Failed to find any vulkan GPU\n" ); @@ -2264,7 +2294,7 @@ static BOOL lock_display_devices( BOOL force ) else WARN( "Failed to update display devices, status %#x\n", status ); release_display_manager_ctx( &ctx );
- ret = update_display_cache_from_registry(); + ret = update_display_cache_from_registry( serial ); }
if (!ret) diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index dde9d9ec1de..f1e286b74e7 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -198,6 +198,7 @@ extern MONITORINFO monitor_info_from_rect( RECT rect, UINT dpi ); extern MONITORINFO monitor_info_from_window( HWND hwnd, UINT flags ); extern UINT monitor_dpi_from_rect( RECT rect, UINT dpi, UINT *raw_dpi ); extern BOOL update_display_cache( BOOL force ); +extern void reset_monitor_update_serial(void); extern void user_lock(void); extern void user_unlock(void); extern void user_check_not_lock(void); diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index 0d61f645c46..d774cd2c986 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -433,6 +433,8 @@ BOOL WINAPI NtUserSetProcessWindowStation( HWINSTA handle ) ret = !wine_server_call_err( req ); } SERVER_END_REQ; + + reset_monitor_update_serial(); return ret; }