<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <br>
    <br>
    <div class="moz-cite-prefix">On 11/25/21 09:34, Jacek Caban wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:406e6e24-5937-743d-7f1e-a4b0b9660ab7@codeweavers.com">Signed-off-by:
      Jacek Caban <a class="moz-txt-link-rfc2396E" href="mailto:jacek@codeweavers.com"><jacek@codeweavers.com></a>
      <br>
      ---
      <br>
      The idea is to provide a way to drivers to do the registration
      instead of duplicating it in each driver. The new way also allows
      drivers to set those without SetupAPI, which is problematic for
      unix libs.
      <br>
      <br>
       dlls/user32/driver.c      |  1 +
      <br>
       dlls/win32u/driver.c      | 13 +++++++
      <br>
       dlls/win32u/sysparams.c   | 75
      ++++++++++++++++++++++++++++++++++++++-
      <br>
       include/wine/gdi_driver.h | 37 +++++++++++++++++++
      <br>
       4 files changed, 125 insertions(+), 1 deletion(-)
      <br>
      <br>
      <br>
      <br>
      <fieldset class="mimeAttachmentHeader"><legend
          class="mimeAttachmentHeaderName">0002-win32u-Introduce-UpdateDisplayDevice-user-driver-entry.txt</legend></fieldset>
      <pre class="moz-quote-pre" wrap="">diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c
index a1a64f42b6f..9ff676aca22 100644
--- a/dlls/user32/driver.c
+++ b/dlls/user32/driver.c
@@ -347,6 +347,7 @@ static struct user_driver_funcs lazy_load_driver =
     loaderdrv_EnumDisplayMonitors,
     loaderdrv_EnumDisplaySettingsEx,
     loaderdrv_GetMonitorInfo,
+    NULL,
     /* windowing functions */
     loaderdrv_CreateDesktopWindow,
     loaderdrv_CreateWindow,
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c
index 9f682fa8eea..93c2ff1da4c 100644
--- a/dlls/win32u/driver.c
+++ b/dlls/win32u/driver.c
@@ -832,6 +832,11 @@ static BOOL CDECL nulldrv_GetMonitorInfo( HMONITOR handle, MONITORINFO *info )
     return FALSE;
 }
 
+static void CDECL nulldrv_UpdateDisplayDevices( const struct gdi_device_manager *manager,
+                                                BOOL force, void *param )
+{
+}
+
 static BOOL CDECL nulldrv_CreateDesktopWindow( HWND hwnd )
 {
     return TRUE;
@@ -1044,6 +1049,12 @@ static void CDECL loaderdrv_UpdateClipboard(void)
     load_driver()->pUpdateClipboard();
 }
 
+static void CDECL loaderdrv_UpdateDisplayDevices( const struct gdi_device_manager *manager,
+                                                  BOOL force, void *param )
+{
+    load_driver()->pUpdateDisplayDevices( manager, force, param );
+}
+
 static const struct user_driver_funcs lazy_load_driver =
 {
     .pActivateKeyboardLayout = loaderdrv_ActivateKeyboardLayout,
@@ -1053,6 +1064,7 @@ static const struct user_driver_funcs lazy_load_driver =
     .pToUnicodeEx = loaderdrv_ToUnicodeEx,
     .pUnregisterHotKey = loaderdrv_UnregisterHotKey,
     .pVkKeyScanEx = loaderdrv_VkKeyScanEx,
+    .pUpdateDisplayDevices = loaderdrv_UpdateDisplayDevices,
     .pUpdateClipboard = loaderdrv_UpdateClipboard,
     .pScrollDC = nulldrv_ScrollDC,
 };
@@ -1093,6 +1105,7 @@ void CDECL __wine_set_display_driver( struct user_driver_funcs *driver, UINT ver
     SET_USER_FUNC(EnumDisplayMonitors);
     SET_USER_FUNC(EnumDisplaySettingsEx);
     SET_USER_FUNC(GetMonitorInfo);
+    SET_USER_FUNC(UpdateDisplayDevices);
     SET_USER_FUNC(CreateDesktopWindow);
     SET_USER_FUNC(CreateWindow);
     SET_USER_FUNC(DestroyWindow);
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c
index 2a1e3e679ca..fc77bf1ab63 100644
--- a/dlls/win32u/sysparams.c
+++ b/dlls/win32u/sysparams.c
@@ -335,7 +335,40 @@ static BOOL read_monitor_settings( struct adapter *adapter, DWORD index, struct
     return TRUE;
 }
 
-static BOOL update_display_cache(void)
+struct device_manager_ctx
+{
+    unsigned int gpu_count;
+};
+
+static void add_gpu( const struct gdi_gpu *gpu, void *param )
+{
+    struct device_manager_ctx *ctx = param;
+    FIXME( "\n" );
+    ctx->gpu_count++;
+}
+
+static void add_adapter( const struct gdi_adapter *adapter, void *param )
+{
+    FIXME( "\n" );
+}
+
+static void add_monitor( const struct gdi_monitor *monitor, void *param )
+{
+    FIXME( "\n" );
+}
+
+static const struct gdi_device_manager device_manager =
+{
+    add_gpu,
+    add_adapter,
+    add_monitor,
+};
+
+static void release_display_manager_ctx( struct device_manager_ctx *ctx )
+{
+}
+
+static BOOL update_display_cache_from_registry(void)
 {
     DWORD adapter_id, monitor_id, size;
     KEY_FULL_INFORMATION key;
@@ -408,6 +441,46 @@ static BOOL update_display_cache(void)
     return ret;
 }
 
+static BOOL update_display_cache(void)
+{
+    struct device_manager_ctx ctx = { 0 };
+
+    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;
+    }
+
+    user_driver->pUpdateDisplayDevices( &device_manager, TRUE, &ctx );
+    if (!ctx.gpu_count)
+    {
+        static const struct gdi_monitor default_monitor =
+        {
+            .rc_work.right = 1024,
+            .rc_work.bottom = 768,
+            .rc_monitor.right = 1024,
+            .rc_monitor.bottom = 768,
+            .state_flags = DISPLAY_DEVICE_ACTIVE,</pre>
    </blockquote>
    <br>
    You probably should add DISPLAY_DEVICE_ATTACHED as well.
    And there should be a name, e.g., "Generic Non-PnP Monitor".
    <style type="text/css">p, li { white-space: pre-wrap; }</style>
    <style type="text/css">p, li { white-space: pre-wrap; }</style><br>
    <br>
    <blockquote type="cite"
      cite="mid:406e6e24-5937-743d-7f1e-a4b0b9660ab7@codeweavers.com">
      <pre class="moz-quote-pre" wrap="">
+        };
+
+        TRACE( "adding default fake monitor\n ");
+        add_monitor( &default_monitor, &ctx );
+    }
+    release_display_manager_ctx( &ctx );
+
+    if (!update_display_cache_from_registry())
+    {
+        ERR( "failed to read display config\n" );
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
 static BOOL lock_display_devices(void)
 {
     if (!update_display_cache()) return FALSE;
diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h
index 994b082d5b4..87969b297d4 100644
--- a/include/wine/gdi_driver.h
+++ b/include/wine/gdi_driver.h
@@ -229,6 +229,42 @@ static inline ULONG window_surface_release( struct window_surface *surface )
     return ret;
 }
 
+/* display manager interface, used to initialize display device registry data */
+
+struct gdi_gpu
+{
+    ULONG_PTR id;
+    WCHAR name[128];      /* name */
+    UINT vendor_id;       /* PCI ID */
+    UINT device_id;
+    UINT subsys_id;
+    UINT revision_id;
+    GUID vulkan_uuid;     /* Vulkan device UUID */
+};
+
+struct gdi_adapter
+{
+    ULONG_PTR id;
+    DWORD state_flags;
+};
+
+struct gdi_monitor
+{
+    WCHAR name[128];      /* name */
+    RECT rc_monitor;      /* RcMonitor in MONITORINFO struct */
+    RECT rc_work;         /* RcWork in MONITORINFO struct */
+    DWORD state_flags;    /* StateFlags in DISPLAY_DEVICE struct */
+    unsigned char *edid;  /* Extended Device Identification Data */
+    UINT edid_len;
+};
+
+struct gdi_device_manager
+{
+    void (*add_gpu)( const struct gdi_gpu *gpu, void *param );
+    void (*add_adapter)( const struct gdi_adapter *adapter, void *param );
+    void (*add_monitor)( const struct gdi_monitor *monitor, void *param );
+};
+
 struct tagUPDATELAYEREDWINDOWINFO;
 
 struct user_driver_funcs
@@ -258,6 +294,7 @@ struct user_driver_funcs
     BOOL    (CDECL *pEnumDisplayMonitors)(HDC,LPRECT,MONITORENUMPROC,LPARAM);
     BOOL    (CDECL *pEnumDisplaySettingsEx)(LPCWSTR,DWORD,LPDEVMODEW,DWORD);
     BOOL    (CDECL *pGetMonitorInfo)(HMONITOR,MONITORINFO*);
+    void    (CDECL *pUpdateDisplayDevices)(const struct gdi_device_manager *,BOOL,void*);
     /* windowing functions */
     BOOL    (CDECL *pCreateDesktopWindow)(HWND);
     BOOL    (CDECL *pCreateWindow)(HWND);

</pre>
    </blockquote>
    <br>
  </body>
</html>