Jacek Caban : win32u: Handle invisible winstations in lock_display_devices.

Alexandre Julliard julliard at winehq.org
Thu Dec 2 15:30:17 CST 2021


Module: wine
Branch: master
Commit: c4b258eff75d54fdc0eb9b1843db5f77318f836c
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=c4b258eff75d54fdc0eb9b1843db5f77318f836c

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Dec  2 01:14:04 2021 +0100

win32u: Handle invisible winstations in lock_display_devices.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/win32u/sysparams.c | 139 ++++++++++++++++++++++++++++--------------------
 1 file changed, 80 insertions(+), 59 deletions(-)

diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c
index d0eda54cde7..195756acea1 100644
--- a/dlls/win32u/sysparams.c
+++ b/dlls/win32u/sysparams.c
@@ -224,6 +224,17 @@ static struct list monitors = LIST_INIT(monitors);
 static INT64 last_query_display_time;
 static pthread_mutex_t display_lock = PTHREAD_MUTEX_INITIALIZER;
 
+static struct monitor virtual_monitor =
+{
+    .handle = NULLDRV_DEFAULT_HMONITOR,
+    .flags = MONITORINFOF_PRIMARY,
+    .rc_monitor.right = 1024,
+    .rc_monitor.bottom = 768,
+    .rc_work.right = 1024,
+    .rc_work.bottom = 768,
+    .dev.state_flags = DISPLAY_DEVICE_ACTIVE | DISPLAY_DEVICE_ATTACHED,
+};
+
 static HANDLE get_display_device_init_mutex( void )
 {
     static const WCHAR display_device_initW[] =
@@ -1045,6 +1056,32 @@ static void release_display_manager_ctx( struct device_manager_ctx *ctx )
     if (ctx->gpu_count) cleanup_devices();
 }
 
+static void clear_display_devices(void)
+{
+    struct adapter *adapter;
+    struct monitor *monitor;
+
+    if (list_head( &monitors ) == &virtual_monitor.entry)
+    {
+        list_init( &monitors );
+        return;
+    }
+
+    while (!list_empty( &monitors ))
+    {
+        monitor = LIST_ENTRY( list_head( &monitors ), struct monitor, entry );
+        list_remove( &monitor->entry );
+        free( monitor );
+    }
+
+    while (!list_empty( &adapters ))
+    {
+        adapter = LIST_ENTRY( list_head( &adapters ), struct adapter, entry );
+        list_remove( &adapter->entry );
+        free( adapter );
+    }
+}
+
 static BOOL update_display_cache_from_registry(void)
 {
     DWORD adapter_id, monitor_id, monitor_count = 0, size;
@@ -1069,19 +1106,7 @@ static BOOL update_display_cache_from_registry(void)
     mutex = get_display_device_init_mutex();
     pthread_mutex_lock( &display_lock );
 
-    while (!list_empty( &monitors ))
-    {
-        monitor = LIST_ENTRY( list_head( &monitors ), struct monitor, entry );
-        list_remove( &monitor->entry );
-        free( monitor );
-    }
-
-    while (!list_empty( &adapters ))
-    {
-        adapter = LIST_ENTRY( list_head( &adapters ), struct adapter, entry );
-        list_remove( &adapter->entry );
-        free( adapter );
-    }
+    clear_display_devices();
 
     for (adapter_id = 0;; adapter_id++)
     {
@@ -1161,8 +1186,27 @@ static BOOL update_display_cache(void)
 
 static BOOL lock_display_devices(void)
 {
-    if (!update_display_cache()) return FALSE;
+    USEROBJECTFLAGS flags;
+    HWINSTA winstation;
+
     pthread_mutex_lock( &display_lock );
+
+    /* Report physical monitor information only if window station has visible display surfaces */
+    winstation = NtUserGetProcessWindowStation();
+    if (NtUserGetObjectInformation( winstation, UOI_FLAGS, &flags, sizeof(flags), NULL ) &&
+        (flags.dwFlags & WSF_VISIBLE))
+    {
+        pthread_mutex_unlock( &display_lock );
+        if (!update_display_cache()) return FALSE;
+        pthread_mutex_lock( &display_lock );
+    }
+    else
+    {
+        clear_display_devices();
+        list_add_tail( &monitors, &virtual_monitor.entry );
+        last_query_display_time = 0;
+    }
+
     return TRUE;
 }
 
@@ -1334,46 +1378,30 @@ BOOL WINAPI NtUserEnumDisplayMonitors( HDC hdc, RECT *rect, MONITORENUMPROC proc
     struct monitor_enum_info enum_buf[8], *enum_info = enum_buf;
     struct enum_display_monitor_params params;
     struct monitor *monitor;
-    ULONG count = 0, i;
-    USEROBJECTFLAGS flags;
-    HWINSTA winstation;
+    unsigned int count = 0, i;
     BOOL ret = TRUE;
 
-    /* Report physical monitor information only if window station has visible display surfaces */
-    winstation = NtUserGetProcessWindowStation();
-    if (NtUserGetObjectInformation( winstation, UOI_FLAGS, &flags, sizeof(flags), NULL ) &&
-        (flags.dwFlags & WSF_VISIBLE))
-    {
-        if (!lock_display_devices()) return FALSE;
-
-        count = list_count( &monitors );
-        if (!count || (count > ARRAYSIZE(enum_buf) &&
-                       !(enum_info = malloc( count * sizeof(*enum_info) ))))
-        {
-            unlock_display_devices();
-            return FALSE;
-        }
-
-        count = 0;
-        LIST_FOR_EACH_ENTRY(monitor, &monitors, struct monitor, entry)
-        {
-            if (!(monitor->dev.state_flags & DISPLAY_DEVICE_ACTIVE)) continue;
-            enum_info[count].handle = monitor->handle;
-            enum_info[count].rect = monitor->rc_monitor;
-            count++;
-        }
+    if (!lock_display_devices()) return FALSE;
 
+    count = list_count( &monitors );
+    if (!count || (count > ARRAYSIZE(enum_buf) &&
+                   !(enum_info = malloc( count * sizeof(*enum_info) ))))
+    {
         unlock_display_devices();
-        if (!count) return FALSE;
+        return FALSE;
     }
-    else
+
+    count = 0;
+    LIST_FOR_EACH_ENTRY(monitor, &monitors, struct monitor, entry)
     {
-        if (!(enum_info = malloc( sizeof(*enum_info) ))) return FALSE;
-        enum_info->handle = NULLDRV_DEFAULT_HMONITOR;
-        SetRect( &enum_info->rect, 0, 0, 1024, 768 );
-        count = 1;
+        if (!(monitor->dev.state_flags & DISPLAY_DEVICE_ACTIVE)) continue;
+        enum_info[count].handle = monitor->handle;
+        enum_info[count].rect = monitor->rc_monitor;
+        count++;
     }
 
+    unlock_display_devices();
+
     params.proc = proc;
     params.hdc = hdc;
     params.lparam = lparam;
@@ -1397,18 +1425,6 @@ static BOOL get_monitor_info( HMONITOR handle, MONITORINFO *info )
 
     if (info->cbSize != sizeof(MONITORINFOEXW) && info->cbSize != sizeof(MONITORINFO)) return FALSE;
 
-    /* Fallback to report one monitor */
-    if (handle == NULLDRV_DEFAULT_HMONITOR)
-    {
-        RECT default_rect = {0, 0, 1024, 768};
-        info->rcMonitor = default_rect;
-        info->rcWork = default_rect;
-        info->dwFlags = MONITORINFOF_PRIMARY;
-        if (info->cbSize >= sizeof(MONITORINFOEXW))
-            asciiz_to_unicode( ((MONITORINFOEXW *)info)->szDevice, "WinDisc" );
-        return TRUE;
-    }
-
     if (!lock_display_devices()) return FALSE;
 
     LIST_FOR_EACH_ENTRY( monitor, &monitors, struct monitor, entry )
@@ -1421,7 +1437,12 @@ static BOOL get_monitor_info( HMONITOR handle, MONITORINFO *info )
         info->rcWork = monitor->rc_work;
         info->dwFlags = monitor->flags;
         if (info->cbSize >= sizeof(MONITORINFOEXW))
-            lstrcpyW( ((MONITORINFOEXW *)info)->szDevice, monitor->adapter->dev.device_name );
+        {
+            if (monitor->adapter)
+                lstrcpyW( ((MONITORINFOEXW *)info)->szDevice, monitor->adapter->dev.device_name );
+            else
+                asciiz_to_unicode( ((MONITORINFOEXW *)info)->szDevice, "WinDisc" );
+        }
         unlock_display_devices();
         return TRUE;
     }




More information about the wine-cvs mailing list