Instead of checking the winstation name and registry on every lock_display_devices call, which is now called on every mouse input to get monitor dpi. This would perhaps be better implemented with a shared memory winstation object instead of putting the flag on the desktop objects, but it would be a larger and riskier change.
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57504 --- dlls/win32u/sysparams.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 2ae72397bc5..8ae3823fd53 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2237,7 +2237,6 @@ 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}; - HWINSTA winstation = NtUserGetProcessWindowStation(); struct device_manager_ctx ctx = {.vulkan_gpus = LIST_INIT(ctx.vulkan_gpus)}; UINT status; WCHAR name[MAX_PATH]; @@ -2245,19 +2244,18 @@ static BOOL lock_display_devices( BOOL force )
init_display_driver(); /* make sure to load the driver before anything else */
+ pthread_mutex_lock( &display_lock ); + /* services do not have any adapters, only a virtual monitor */ - if (NtUserGetObjectInformation( winstation, UOI_NAME, name, sizeof(name), NULL ) + if (NtUserGetObjectInformation( NtUserGetProcessWindowStation(), UOI_NAME, name, sizeof(name), NULL ) && !wcscmp( name, wine_service_station_name )) { - pthread_mutex_lock( &display_lock ); clear_display_devices(); list_add_tail( &monitors, &virtual_monitor.entry ); set_winstation_monitors(); return TRUE; }
- pthread_mutex_lock( &display_lock ); - if (!force && !update_display_cache_from_registry()) force = TRUE; if (force) {
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57504 --- server/protocol.def | 4 ++++ server/user.h | 1 + server/winstation.c | 21 +++++++++++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def index 4b9c4dc8e5c..37e7cffa748 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -979,6 +979,7 @@ typedef volatile struct unsigned int flags; /* desktop flags */ struct shared_cursor cursor; /* global cursor information */ unsigned char keystate[256]; /* asynchronous key state */ + unsigned __int64 monitor_serial; /* winstation monitor update counter */ } desktop_shm_t;
typedef volatile struct @@ -2882,7 +2883,10 @@ enum coords_relative
/* Update the process current window station monitors */ @REQ(set_winstation_monitors) + int increment; /* force increment the monitor update counter */ VARARG(infos,monitor_infos); /* window station monitors */ +@REPLY + unsigned __int64 serial; /* winstation monitor update counter */ @END
diff --git a/server/user.h b/server/user.h index 892f746739a..ce463b9395d 100644 --- a/server/user.h +++ b/server/user.h @@ -57,6 +57,7 @@ struct winstation struct namespace *desktop_names; /* namespace for desktops of this winstation */ unsigned int monitor_count; /* number of monitors */ struct monitor_info *monitors; /* window station monitors */ + unsigned __int64 monitor_serial; /* winstation monitor update counter */ };
struct key_repeat diff --git a/server/winstation.c b/server/winstation.c index 8611c893cde..b3746090ccf 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -149,6 +149,7 @@ static struct winstation *create_winstation( struct object *root, const struct u winstation->atom_table = NULL; winstation->monitors = NULL; winstation->monitor_count = 0; + winstation->monitor_serial = 1; list_add_tail( &winstation_list, &winstation->entry ); list_init( &winstation->desktops ); if (!(winstation->desktop_names = create_namespace( 7 ))) @@ -322,6 +323,7 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned shared->cursor.clip.right = 0; shared->cursor.clip.bottom = 0; memset( (void *)shared->keystate, 0, sizeof(shared->keystate) ); + shared->monitor_serial = winstation->monitor_serial; } SHARED_WRITE_END; } @@ -643,19 +645,34 @@ DECL_HANDLER(close_winstation) DECL_HANDLER(set_winstation_monitors) { struct winstation *winstation; - unsigned int size; + struct desktop *desktop; + unsigned int size = get_req_data_size();
if (!(winstation = (struct winstation *)get_handle_obj( current->process, current->process->winstation, 0, &winstation_ops ))) return;
+ if (req->increment || winstation->monitor_count != size / sizeof(*winstation->monitors) || + !winstation->monitors || memcmp( winstation->monitors, get_req_data(), size )) + winstation->monitor_serial++; + free( winstation->monitors ); winstation->monitors = NULL; winstation->monitor_count = 0;
- if ((size = get_req_data_size()) && (winstation->monitors = memdup( get_req_data(), size ))) + LIST_FOR_EACH_ENTRY(desktop, &winstation->desktops, struct desktop, entry) + { + SHARED_WRITE_BEGIN( desktop->shared, desktop_shm_t ) + { + shared->monitor_serial = winstation->monitor_serial; + } + SHARED_WRITE_END; + } + + if (size && (winstation->monitors = memdup( get_req_data(), size ))) winstation->monitor_count = size / sizeof(*winstation->monitors);
+ reply->serial = winstation->monitor_serial; release_object( winstation ); }
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; }