[PATCH v6 4/7] winex11.drv: Initialize monitor registry data.
Zhiyi Zhang
zzhang at codeweavers.com
Wed May 22 04:17:05 CDT 2019
Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
dlls/winex11.drv/display.c | 120 ++++++++++++++++++++++++++++++++++--
dlls/winex11.drv/x11drv.h | 22 +++++++
dlls/winex11.drv/xinerama.c | 53 ++++++++++++++++
3 files changed, 190 insertions(+), 5 deletions(-)
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c
index 300a05e8c0..2cc36763db 100644
--- a/dlls/winex11.drv/display.c
+++ b/dlls/winex11.drv/display.c
@@ -39,11 +39,19 @@
WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
+/* Wine specific monitor properties */
+DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_STATEFLAGS, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 2);
+DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_RCMONITOR, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 3);
+DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_RCWORK, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 4);
+DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 5);
+
static const WCHAR driver_descW[] = {'D','r','i','v','e','r','D','e','s','c',0};
static const WCHAR graphics_driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
static const WCHAR video_idW[] = {'V','i','d','e','o','I','D',0};
static const WCHAR symbolic_link_valueW[]= {'S','y','m','b','o','l','i','c','L','i','n','k','V','a','l','u','e',0};
static const WCHAR gpu_idW[] = {'G','P','U','I','D',0};
+static const WCHAR mointor_id_fmtW[] = {'M','o','n','i','t','o','r','I','D','%','d',0};
+static const WCHAR adapter_name_fmtW[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y','%','d',0};
static const WCHAR state_flagsW[] = {'S','t','a','t','e','F','l','a','g','s',0};
static const WCHAR guid_fmtW[] = {
'{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0','2','x','%','0','2','x','-',
@@ -90,6 +98,13 @@ static const WCHAR nt_classW[] = {
'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
'C','o','n','t','r','o','l','\\',
'C','l','a','s','s','\\',0};
+static const WCHAR monitor_instance_fmtW[] = {
+ 'D','I','S','P','L','A','Y','\\',
+ 'D','e','f','a','u','l','t','_','M','o','n','i','t','o','r','\\',
+ '%','0','4','X','&','%','0','4','X',0};
+static const WCHAR monitor_hardware_idW[] = {
+ 'M','O','N','I','T','O','R','\\',
+ 'D','e','f','a','u','l','t','_','M','o','n','i','t','o','r',0,0};
static struct x11drv_display_device_handler handler;
@@ -185,7 +200,7 @@ fail:
return ret;
}
-static BOOL X11DRV_InitAdapter(HKEY video_hkey, INT video_index, INT gpu_index, INT adapter_index,
+static BOOL X11DRV_InitAdapter(HKEY video_hkey, INT video_index, INT gpu_index, INT adapter_index, INT monitor_count,
const struct x11drv_gpu *gpu, const WCHAR *guid_string,
const WCHAR *gpu_driver, const struct x11drv_adapter *adapter)
{
@@ -195,6 +210,7 @@ static BOOL X11DRV_InitAdapter(HKEY video_hkey, INT video_index, INT gpu_index,
HKEY hkey = NULL;
BOOL ret = FALSE;
LSTATUS ls;
+ INT i;
sprintfW(key_nameW, device_video_fmtW, video_index);
strcpyW(bufferW, machine_prefixW);
@@ -229,6 +245,15 @@ static BOOL X11DRV_InitAdapter(HKEY video_hkey, INT video_index, INT gpu_index,
if (RegSetValueExW(hkey, gpu_idW, 0, REG_SZ, (const BYTE *)bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR)))
goto fail;
+ /* Write all monitor instances paths under this adapter */
+ for (i = 0; i < monitor_count; i++)
+ {
+ sprintfW(key_nameW, mointor_id_fmtW, i);
+ sprintfW(bufferW, monitor_instance_fmtW, video_index, i);
+ if (RegSetValueExW(hkey, key_nameW, 0, REG_SZ, (const BYTE *)bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR)))
+ goto fail;
+ }
+
/* Write StateFlags */
if (RegSetValueExW(hkey, state_flagsW, 0, REG_DWORD, (const BYTE *)&adapter->state_flags,
sizeof(adapter->state_flags)))
@@ -242,6 +267,64 @@ fail:
return ret;
}
+static BOOL X11DRV_InitMonitor(HDEVINFO devinfo, const struct x11drv_monitor *monitor, int monitor_index,
+ int video_index)
+{
+ WCHAR bufferW[MAX_PATH];
+ SP_DEVINFO_DATA device_data = {sizeof(SP_DEVINFO_DATA)};
+ HKEY hkey = NULL;
+ BOOL ret = FALSE;
+
+ /* Create GUID_DEVCLASS_MONITOR instance */
+ sprintfW(bufferW, monitor_instance_fmtW, video_index, monitor_index);
+ SetupDiCreateDeviceInfoW(devinfo, bufferW, &GUID_DEVCLASS_MONITOR, monitor->name, NULL, 0, &device_data);
+ if (!SetupDiRegisterDeviceInfo(devinfo, &device_data, 0, NULL, NULL, NULL))
+ goto fail;
+
+ /* Write HaredwareID registry property */
+ if (!SetupDiSetDeviceRegistryPropertyW(devinfo, &device_data, SPDRP_HARDWAREID,
+ (const BYTE *)monitor_hardware_idW, sizeof(monitor_hardware_idW)))
+ goto fail;
+
+ /* Open driver key */
+ hkey = SetupDiOpenDevRegKey(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
+ if (hkey == INVALID_HANDLE_VALUE)
+ hkey = SetupDiCreateDevRegKeyW(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
+
+ /* Write DriverDesc value */
+ if (RegSetValueExW(hkey, driver_descW, 0, REG_SZ, (const BYTE *)monitor->name,
+ (strlenW(monitor->name) + 1) * sizeof(WCHAR)))
+ goto fail;
+
+ /* FIXME:
+ * Following properties are Wine specific, see comments in X11DRV_InitAdapter for details */
+ /* StateFlags */
+ if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_STATEFLAGS, DEVPROP_TYPE_UINT32,
+ (const BYTE *)&monitor->state_flags, sizeof(monitor->state_flags), 0))
+ goto fail;
+ /* RcMonitor */
+ if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_RCMONITOR, DEVPROP_TYPE_BINARY,
+ (const BYTE *)&monitor->rc_monitor, sizeof(monitor->rc_monitor), 0))
+ goto fail;
+ /* RcWork */
+ if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_RCWORK, DEVPROP_TYPE_BINARY,
+ (const BYTE *)&monitor->rc_work, sizeof(monitor->rc_work), 0))
+ goto fail;
+
+ sprintfW(bufferW, adapter_name_fmtW, video_index + 1);
+ /* Adapter name */
+ if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, DEVPROP_TYPE_STRING,
+ (const BYTE *)bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR), 0))
+ goto fail;
+
+ ret = TRUE;
+fail:
+ RegCloseKey(hkey);
+ if (!ret)
+ ERR("Failed to initialize monitor\n");
+ return ret;
+}
+
static void prepare_devices(void)
{
static const BOOL not_present = FALSE;
@@ -249,8 +332,18 @@ static void prepare_devices(void)
HDEVINFO devinfo;
DWORD i = 0;
+ /* Remove all monitors */
+ devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_MONITOR, NULL, NULL, 0);
+ while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data))
+ {
+ if (!SetupDiRemoveDevice(devinfo, &device_data))
+ ERR("Failed to remove monitor\n");
+ }
+ SetupDiDestroyDeviceInfoList(devinfo);
+
/* Set all GPUs as not present. We can't simply delete them because we need to keep the GUID consistent with
* each initialization run. We clean up non present GPUs at the end of initialization */
+ i = 0;
devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, 0);
while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data))
{
@@ -285,9 +378,10 @@ void X11DRV_DisplayDevices_Init(void)
{
struct x11drv_gpu *gpus = NULL;
struct x11drv_adapter *adapters = NULL;
- INT gpu_count, adapter_count;
- INT gpu, adapter;
- HDEVINFO gpu_devinfo = NULL;
+ struct x11drv_monitor *monitors = NULL;
+ INT gpu_count, adapter_count, monitor_count;
+ INT gpu, adapter, monitor;
+ HDEVINFO gpu_devinfo = NULL, monitor_devinfo = NULL;
HKEY video_hkey = NULL;
INT video_index = 0;
DWORD disposition = 0;
@@ -316,6 +410,7 @@ void X11DRV_DisplayDevices_Init(void)
prepare_devices();
gpu_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_DISPLAY, NULL);
+ monitor_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_MONITOR, NULL);
/* Initialize GPUs */
if (!handler.pGetGpus(&gpus, &gpu_count))
@@ -332,10 +427,22 @@ void X11DRV_DisplayDevices_Init(void)
for (adapter = 0; adapter < adapter_count; adapter++)
{
- if (!X11DRV_InitAdapter(video_hkey, video_index, gpu, adapter,
+ if (!handler.pGetMonitors(adapters[adapter].id, &monitors, &monitor_count))
+ goto fail;
+
+ if (!X11DRV_InitAdapter(video_hkey, video_index, gpu, adapter, monitor_count,
&gpus[gpu], guidW, driverW, &adapters[adapter]))
goto fail;
+ /* Initialize monitors */
+ for (monitor = 0; monitor < monitor_count; monitor++)
+ {
+ if (!X11DRV_InitMonitor(monitor_devinfo, &monitors[monitor], monitor, video_index))
+ goto fail;
+ }
+
+ handler.pFreeMonitors(monitors);
+ monitors = NULL;
video_index++;
}
@@ -346,12 +453,15 @@ void X11DRV_DisplayDevices_Init(void)
success = TRUE;
fail:
cleanup_devices();
+ SetupDiDestroyDeviceInfoList(monitor_devinfo);
SetupDiDestroyDeviceInfoList(gpu_devinfo);
RegCloseKey(video_hkey);
if (gpus)
handler.pFreeGpus(gpus);
if (adapters)
handler.pFreeAdapters(adapters);
+ if (monitors)
+ handler.pFreeMonitors(monitors);
if (!success)
ERR("Failed to initialize display devices\n");
}
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 5d99d69eff..40392b03c0 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -690,6 +690,19 @@ struct x11drv_adapter
DWORD state_flags;
};
+/* Represent a monitor in EnumDisplayDevices context */
+struct x11drv_monitor
+{
+ /* Name */
+ WCHAR name[128];
+ /* as RcMonitor in MONITORINFO struct */
+ RECT rc_monitor;
+ /* as RcWork in MONITORINFO struct */
+ RECT rc_work;
+ /* StateFlags in DISPLAY_DEVICE struct */
+ DWORD state_flags;
+};
+
/* Required functions for display device registry initialization */
struct x11drv_display_device_handler
{
@@ -710,11 +723,20 @@ struct x11drv_display_device_handler
* Return FALSE on failure with parameters unchanged */
BOOL (*pGetAdapters)(ULONG_PTR gpu_id, struct x11drv_adapter **adapters, int *count);
+ /* pGetMonitors will be called to get a list of monitors in EnumDisplayDevices context under an adapter.
+ * The first monitor has to be primary if adapter is primary.
+ *
+ * Return FALSE on failure with parameters unchanged */
+ BOOL (*pGetMonitors)(ULONG_PTR adapter_id, struct x11drv_monitor **monitors, int *count);
+
/* pFreeGpus will be called to free a GPU list from pGetGpus */
void (*pFreeGpus)(struct x11drv_gpu *gpus);
/* pFreeAdapters will be called to free an adapter list from pGetAdapters */
void (*pFreeAdapters)(struct x11drv_adapter *adapters);
+
+ /* pFreeMonitors will be called to free a monitor list from pGetMonitors */
+ void (*pFreeMonitors)(struct x11drv_monitor *monitors);
};
extern void X11DRV_DisplayDevices_SetHandler(const struct x11drv_display_device_handler *handler) DECLSPEC_HIDDEN;
diff --git a/dlls/winex11.drv/xinerama.c b/dlls/winex11.drv/xinerama.c
index 3f6fdebb1e..49427890cb 100644
--- a/dlls/winex11.drv/xinerama.c
+++ b/dlls/winex11.drv/xinerama.c
@@ -291,6 +291,57 @@ static void xinerama_free_adapters( struct x11drv_adapter *adapters )
heap_free( adapters );
}
+static BOOL xinerama_get_monitors( ULONG_PTR adapter_id, struct x11drv_monitor **new_monitors, int *count )
+{
+ static const WCHAR generic_nonpnp_monitorW[] = {
+ 'G','e','n','e','r','i','c',' ',
+ 'N','o','n','-','P','n','P',' ','M','o','n','i','t','o','r',0};
+ struct x11drv_monitor *monitor;
+ INT first = (INT)adapter_id;
+ INT monitor_count = 0;
+ INT index = 0;
+ INT i;
+
+ for (i = first; i < nb_monitors; i++)
+ {
+ if (i == first
+ || (EqualRect( &monitors[i].rcMonitor, &monitors[first].rcMonitor )
+ && !IsRectEmpty( &monitors[first].rcMonitor )))
+ monitor_count++;
+ }
+
+ monitor = heap_calloc( monitor_count, sizeof(*monitor) );
+ if (!monitor)
+ return FALSE;
+
+ for (i = first; i < nb_monitors; i++)
+ {
+ if (i == first
+ || (EqualRect( &monitors[i].rcMonitor, &monitors[first].rcMonitor )
+ && !IsRectEmpty( &monitors[first].rcMonitor )))
+ {
+ strcpyW( monitor[index].name, generic_nonpnp_monitorW );
+ monitor[index].rc_monitor = monitors[i].rcMonitor;
+ monitor[index].rc_work = monitors[i].rcWork;
+ /* Xinerama only reports monitors already attached */
+ monitor[index].state_flags = DISPLAY_DEVICE_ATTACHED;
+ if (!IsRectEmpty( &monitors[i].rcMonitor ))
+ monitor[index].state_flags |= DISPLAY_DEVICE_ACTIVE;
+
+ index++;
+ }
+ }
+
+ *new_monitors = monitor;
+ *count = monitor_count;
+ return TRUE;
+}
+
+static void xinerama_free_monitors( struct x11drv_monitor *monitors )
+{
+ heap_free( monitors );
+}
+
void xinerama_init( unsigned int width, unsigned int height )
{
struct x11drv_display_device_handler handler;
@@ -331,8 +382,10 @@ void xinerama_init( unsigned int width, unsigned int height )
handler.priority = 100;
handler.pGetGpus = xinerama_get_gpus;
handler.pGetAdapters = xinerama_get_adapters;
+ handler.pGetMonitors = xinerama_get_monitors;
handler.pFreeGpus = xinerama_free_gpus;
handler.pFreeAdapters = xinerama_free_adapters;
+ handler.pFreeMonitors = xinerama_free_monitors;
X11DRV_DisplayDevices_SetHandler( &handler );
TRACE( "virtual size: %s primary: %s\n",
--
2.20.1
More information about the wine-devel
mailing list