From fbf21ad70ca80cfa222a11dfe97da5ae3ce77a86 Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Sat, 1 Apr 2023 16:54:02 -0400 Subject: [PATCH 01/16] Implement the feature --- src/win32_monitor.c | 384 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 384 insertions(+) diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 2935ac28..ef36c394 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -37,6 +37,381 @@ #include +#if WINVER < 0x0601 // To be able to compile on windows Vista and XP even though the feature won't be used. + +typedef struct DISPLAYCONFIG_PATH_SOURCE_INFO +{ + LUID adapterId; + UINT32 id; + union + { + UINT32 modeInfoIdx; + struct + { + UINT32 cloneGroupId : 16; + UINT32 sourceModeInfoIdx : 16; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + UINT32 statusFlags; +} DISPLAYCONFIG_PATH_SOURCE_INFO; + +typedef enum +{ + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER = -1, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15 = 0, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO = 1, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO = 2, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO = 3, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI = 4, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI = 5, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS = 6, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN = 8, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI = 9, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = 10, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = 11, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL = 12, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED = 13, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE = 14, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST = 15, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INDIRECT_WIRED = 16, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INDIRECT_VIRTUAL = 17, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_USB_TUNNEL, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL = (int)0x80000000, // Cast required to enforce 4 byte enum. + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32 = (int)0xFFFFFFFF // Cast required to enforce 4 byte enum. +} DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY; + +typedef enum +{ + DISPLAYCONFIG_ROTATION_IDENTITY = 1, + DISPLAYCONFIG_ROTATION_ROTATE90 = 2, + DISPLAYCONFIG_ROTATION_ROTATE180 = 3, + DISPLAYCONFIG_ROTATION_ROTATE270 = 4, + DISPLAYCONFIG_ROTATION_FORCE_UINT32 = 0xFFFFFFFF +} DISPLAYCONFIG_ROTATION; + +typedef enum +{ + DISPLAYCONFIG_SCALING_IDENTITY = 1, + DISPLAYCONFIG_SCALING_CENTERED = 2, + DISPLAYCONFIG_SCALING_STRETCHED = 3, + DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4, + DISPLAYCONFIG_SCALING_CUSTOM = 5, + DISPLAYCONFIG_SCALING_PREFERRED = 128, + DISPLAYCONFIG_SCALING_FORCE_UINT32 = 0xFFFFFFFF +} DISPLAYCONFIG_SCALING; + +typedef struct DISPLAYCONFIG_RATIONAL +{ + UINT32 Numerator; + UINT32 Denominator; +} DISPLAYCONFIG_RATIONAL; + +typedef enum +{ + DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED = 0, + DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE = 1, + DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED = 2, + DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST, + DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3, + DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32 = 0xFFFFFFFF +} DISPLAYCONFIG_SCANLINE_ORDERING; + +typedef struct DISPLAYCONFIG_PATH_TARGET_INFO +{ + LUID adapterId; + UINT32 id; + union + { + UINT32 modeInfoIdx; + struct + { + UINT32 desktopModeInfoIdx : 16; + UINT32 targetModeInfoIdx : 16; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology; + DISPLAYCONFIG_ROTATION rotation; + DISPLAYCONFIG_SCALING scaling; + DISPLAYCONFIG_RATIONAL refreshRate; + DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering; + BOOL targetAvailable; + UINT32 statusFlags; +} DISPLAYCONFIG_PATH_TARGET_INFO; + +typedef struct DISPLAYCONFIG_PATH_INFO +{ + DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo; + DISPLAYCONFIG_PATH_TARGET_INFO targetInfo; + UINT32 flags; +} DISPLAYCONFIG_PATH_INFO; + +typedef enum +{ + DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE = 1, + DISPLAYCONFIG_MODE_INFO_TYPE_TARGET = 2, + DISPLAYCONFIG_MODE_INFO_TYPE_DESKTOP_IMAGE = 3, + DISPLAYCONFIG_MODE_INFO_TYPE_FORCE_UINT32 = 0xFFFFFFFF +} DISPLAYCONFIG_MODE_INFO_TYPE; + +typedef struct DISPLAYCONFIG_2DREGION +{ + UINT32 cx; + UINT32 cy; +} DISPLAYCONFIG_2DREGION; + +typedef struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO +{ + UINT64 pixelRate; + DISPLAYCONFIG_RATIONAL hSyncFreq; + DISPLAYCONFIG_RATIONAL vSyncFreq; + DISPLAYCONFIG_2DREGION activeSize; + DISPLAYCONFIG_2DREGION totalSize; + union + { + struct + { + UINT32 videoStandard : 16; + UINT32 vSyncFreqDivider : 6; + UINT32 reserved : 10; + } AdditionalSignalInfo; + UINT32 videoStandard; + } DUMMYUNIONNAME; + DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering; +} DISPLAYCONFIG_VIDEO_SIGNAL_INFO; + +typedef struct DISPLAYCONFIG_TARGET_MODE +{ + DISPLAYCONFIG_VIDEO_SIGNAL_INFO targetVideoSignalInfo; +} DISPLAYCONFIG_TARGET_MODE; + +typedef enum +{ + DISPLAYCONFIG_PIXELFORMAT_8BPP = 1, + DISPLAYCONFIG_PIXELFORMAT_16BPP = 2, + DISPLAYCONFIG_PIXELFORMAT_24BPP = 3, + DISPLAYCONFIG_PIXELFORMAT_32BPP = 4, + DISPLAYCONFIG_PIXELFORMAT_NONGDI = 5, + DISPLAYCONFIG_PIXELFORMAT_FORCE_UINT32 = 0xffffffff +} DISPLAYCONFIG_PIXELFORMAT; + +typedef struct DISPLAYCONFIG_SOURCE_MODE +{ + UINT32 width; + UINT32 height; + DISPLAYCONFIG_PIXELFORMAT pixelFormat; + POINTL position; +} DISPLAYCONFIG_SOURCE_MODE; + +typedef struct DISPLAYCONFIG_DESKTOP_IMAGE_INFO +{ + POINTL PathSourceSize; + RECTL DesktopImageRegion; + RECTL DesktopImageClip; +} DISPLAYCONFIG_DESKTOP_IMAGE_INFO; + +typedef struct DISPLAYCONFIG_MODE_INFO +{ + DISPLAYCONFIG_MODE_INFO_TYPE infoType; + UINT32 id; + LUID adapterId; + union + { + DISPLAYCONFIG_TARGET_MODE targetMode; + DISPLAYCONFIG_SOURCE_MODE sourceMode; + DISPLAYCONFIG_DESKTOP_IMAGE_INFO desktopImageInfo; + } DUMMYUNIONNAME; +} DISPLAYCONFIG_MODE_INFO; + +const UINT32 QDC_ONLY_ACTIVE_PATHS = 0x00000002; + +typedef enum +{ + DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1, + DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2, + DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3, + DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME = 4, + DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE = 5, + DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE = 6, + DISPLAYCONFIG_DEVICE_INFO_GET_SUPPORT_VIRTUAL_RESOLUTION = 7, + DISPLAYCONFIG_DEVICE_INFO_SET_SUPPORT_VIRTUAL_RESOLUTION = 8, + DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO = 9, + DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE = 10, + DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL = 11, + DISPLAYCONFIG_DEVICE_INFO_GET_MONITOR_SPECIALIZATION, + DISPLAYCONFIG_DEVICE_INFO_SET_MONITOR_SPECIALIZATION, + DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32 = 0xFFFFFFFF +} DISPLAYCONFIG_DEVICE_INFO_TYPE; + +typedef struct DISPLAYCONFIG_DEVICE_INFO_HEADER { + DISPLAYCONFIG_DEVICE_INFO_TYPE type; + UINT32 size; + LUID adapterId; + UINT32 id; +} DISPLAYCONFIG_DEVICE_INFO_HEADER; + +typedef struct DISPLAYCONFIG_SOURCE_DEVICE_NAME +{ + DISPLAYCONFIG_DEVICE_INFO_HEADER header; + WCHAR viewGdiDeviceName[CCHDEVICENAME]; +} DISPLAYCONFIG_SOURCE_DEVICE_NAME; + +typedef struct DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS +{ + union + { + struct + { + UINT32 friendlyNameFromEdid : 1; + UINT32 friendlyNameForced : 1; + UINT32 edidIdsValid : 1; + UINT32 reserved : 29; + } DUMMYSTRUCTNAME; + UINT32 value; + } DUMMYUNIONNAME; +} DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS; + +typedef struct DISPLAYCONFIG_TARGET_DEVICE_NAME +{ + DISPLAYCONFIG_DEVICE_INFO_HEADER header; + DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS flags; + DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology; + UINT16 edidManufactureId; + UINT16 edidProductCodeId; + UINT32 connectorInstance; + WCHAR monitorFriendlyDeviceName[64]; + WCHAR monitorDevicePath[128]; +} DISPLAYCONFIG_TARGET_DEVICE_NAME; + +typedef enum DISPLAYCONFIG_TOPOLOGY_ID +{ + DISPLAYCONFIG_TOPOLOGY_INTERNAL = 0x00000001, + DISPLAYCONFIG_TOPOLOGY_CLONE = 0x00000002, + DISPLAYCONFIG_TOPOLOGY_EXTEND = 0x00000004, + DISPLAYCONFIG_TOPOLOGY_EXTERNAL = 0x00000008, + DISPLAYCONFIG_TOPOLOGY_FORCE_UINT32 = 0xFFFFFFFF +} DISPLAYCONFIG_TOPOLOGY_ID; + +#endif //#if WINVER < 0x0601 + +typedef LONG (*pGetDisplayConfigBufferSizes)(UINT32 flags, UINT32 *numPathArrayElements, UINT32 *numModeInfoArrayElements); +typedef LONG (*pQueryDisplayConfig)(UINT32 flags, UINT32 *numPathArrayElements, DISPLAYCONFIG_PATH_INFO *pathArray, UINT32 *numModeInfoArrayElements, DISPLAYCONFIG_MODE_INFO *modeInfoArray, DISPLAYCONFIG_TOPOLOGY_ID *currentTopologyId); +typedef LONG (*pDisplayConfigGetDeviceInfo)(DISPLAYCONFIG_DEVICE_INFO_HEADER* requestPacket); + +typedef struct AccurateNameRequiredData +{ + HMODULE m_dll; + pGetDisplayConfigBufferSizes m_GetDisplayConfigBufferSizes; + pQueryDisplayConfig m_QueryDisplayConfig; + pDisplayConfigGetDeviceInfo m_DisplayConfigGetDeviceInfo; +} AccurateNameRequiredData; + +BOOL loadWin7MonitorPointers(AccurateNameRequiredData *io_ptrs) +{ + if(!IsWindows7OrGreater()) + return 0; + + io_ptrs->m_dll = LoadLibrary(L"User32.dll"); + if (io_ptrs == NULL) + return 0; + + io_ptrs->m_GetDisplayConfigBufferSizes = (pGetDisplayConfigBufferSizes)GetProcAddress(io_ptrs->m_dll, "GetDisplayConfigBufferSizes"); + if(io_ptrs->m_GetDisplayConfigBufferSizes == NULL) + return 0; + + io_ptrs->m_QueryDisplayConfig = (pQueryDisplayConfig)GetProcAddress(io_ptrs->m_dll, "QueryDisplayConfig"); + if(io_ptrs->m_QueryDisplayConfig == NULL) + return 0; + + io_ptrs->m_DisplayConfigGetDeviceInfo = (pDisplayConfigGetDeviceInfo)GetProcAddress(io_ptrs->m_dll, "DisplayConfigGetDeviceInfo"); + if(io_ptrs->m_DisplayConfigGetDeviceInfo == NULL) + return 0; + + return 1; +} + +// If the returned pointer is valid (not NULL) the caller of this function is in charge of freeing the memory when he is done. +static char * GetAccurateMonitorName(const WCHAR *deviceName) +{ + AccurateNameRequiredData dllPointers; + if(loadWin7MonitorPointers(&dllPointers) == 0) + return NULL; + + DISPLAYCONFIG_PATH_INFO *paths = NULL; + DISPLAYCONFIG_MODE_INFO *modes = NULL; + char *retval = NULL; + UINT32 pathCount = 0; + UINT32 modeCount = 0; + UINT32 i; + LONG rc; + + do { + rc = dllPointers.m_GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount); + if (rc != ERROR_SUCCESS) { + goto GET_ACCURATE_MONITOR_NAME_FAILURE; + } + + free(paths); + free(modes); + + paths = (DISPLAYCONFIG_PATH_INFO *) malloc(sizeof (DISPLAYCONFIG_PATH_INFO) * pathCount); + modes = (DISPLAYCONFIG_MODE_INFO *) malloc(sizeof (DISPLAYCONFIG_MODE_INFO) * modeCount); + if ((paths == NULL) || (modes == NULL)) { + goto GET_ACCURATE_MONITOR_NAME_FAILURE; + } + + rc = dllPointers.m_QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, paths, &modeCount, modes, 0); + } while (rc == ERROR_INSUFFICIENT_BUFFER); + + if (rc == ERROR_SUCCESS) { + for (i = 0; i < pathCount; i++) { + DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName; + DISPLAYCONFIG_TARGET_DEVICE_NAME targetName; + + ZeroMemory(&sourceName, sizeof(sourceName)); + sourceName.header.adapterId = paths[i].targetInfo.adapterId; + sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME; + sourceName.header.size = sizeof (sourceName); + sourceName.header.id = paths[i].sourceInfo.id; + rc = dllPointers.m_DisplayConfigGetDeviceInfo(&sourceName.header); + if (rc != ERROR_SUCCESS) { + break; + } else if (wcscmp(deviceName, sourceName.viewGdiDeviceName) != 0) { + continue; + } + + ZeroMemory(&targetName, sizeof(targetName)); + targetName.header.adapterId = paths[i].targetInfo.adapterId; + targetName.header.id = paths[i].targetInfo.id; + targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; + targetName.header.size = sizeof (targetName); + rc = dllPointers.m_DisplayConfigGetDeviceInfo(&targetName.header); + if (rc == ERROR_SUCCESS) { + retval = _glfwCreateUTF8FromWideStringWin32(targetName.monitorFriendlyDeviceName); + /* if we got an empty string, treat it as failure so we'll fallback + to getting the generic name. */ + if (retval && (*retval == '\0')) { + free(retval); + retval = NULL; + } + } + break; + } + } + + FreeLibrary(dllPointers.m_dll); + free(paths); + free(modes); + return retval; + +GET_ACCURATE_MONITOR_NAME_FAILURE: + FreeLibrary(dllPointers.m_dll); + free(retval); + free(paths); + free(modes); + return NULL; +} + + // Callback for EnumDisplayMonitors in createMonitor // static BOOL CALLBACK monitorCallback(HMONITOR handle, @@ -52,7 +427,16 @@ static BOOL CALLBACK monitorCallback(HMONITOR handle, { _GLFWmonitor* monitor = (_GLFWmonitor*) data; if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0) + { monitor->win32.handle = handle; + char *possibleBetterDisplayName = GetAccurateMonitorName(mi.szDevice); + if(possibleBetterDisplayName != NULL) + { + strncpy(monitor->name, possibleBetterDisplayName, sizeof(monitor->name) - 1); + free(possibleBetterDisplayName); + possibleBetterDisplayName = NULL; + } + } } return TRUE; From 7cd353f3af74ac9717f7e523d0063d1faa99f520 Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Sat, 1 Apr 2023 16:58:40 -0400 Subject: [PATCH 02/16] Rename struct to follow GLFW terminology --- src/win32_monitor.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/win32_monitor.c b/src/win32_monitor.c index ef36c394..013ab28d 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -297,15 +297,15 @@ typedef LONG (*pGetDisplayConfigBufferSizes)(UINT32 flags, UINT32 *numPathArrayE typedef LONG (*pQueryDisplayConfig)(UINT32 flags, UINT32 *numPathArrayElements, DISPLAYCONFIG_PATH_INFO *pathArray, UINT32 *numModeInfoArrayElements, DISPLAYCONFIG_MODE_INFO *modeInfoArray, DISPLAYCONFIG_TOPOLOGY_ID *currentTopologyId); typedef LONG (*pDisplayConfigGetDeviceInfo)(DISPLAYCONFIG_DEVICE_INFO_HEADER* requestPacket); -typedef struct AccurateNameRequiredData +typedef struct AccurateMonitorNameRequiredData { HMODULE m_dll; pGetDisplayConfigBufferSizes m_GetDisplayConfigBufferSizes; pQueryDisplayConfig m_QueryDisplayConfig; pDisplayConfigGetDeviceInfo m_DisplayConfigGetDeviceInfo; -} AccurateNameRequiredData; +} AccurateMonitorNameRequiredData; -BOOL loadWin7MonitorPointers(AccurateNameRequiredData *io_ptrs) +BOOL loadWin7MonitorPointers(AccurateMonitorNameRequiredData *io_ptrs) { if(!IsWindows7OrGreater()) return 0; @@ -332,7 +332,7 @@ BOOL loadWin7MonitorPointers(AccurateNameRequiredData *io_ptrs) // If the returned pointer is valid (not NULL) the caller of this function is in charge of freeing the memory when he is done. static char * GetAccurateMonitorName(const WCHAR *deviceName) { - AccurateNameRequiredData dllPointers; + AccurateMonitorNameRequiredData dllPointers; if(loadWin7MonitorPointers(&dllPointers) == 0) return NULL; From f1ee946007b687057c0e2b304b5364e235877c8c Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Sat, 1 Apr 2023 17:01:13 -0400 Subject: [PATCH 03/16] Rename variable to better reflect its purpose --- src/win32_monitor.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 013ab28d..88c958c7 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -429,12 +429,12 @@ static BOOL CALLBACK monitorCallback(HMONITOR handle, if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0) { monitor->win32.handle = handle; - char *possibleBetterDisplayName = GetAccurateMonitorName(mi.szDevice); - if(possibleBetterDisplayName != NULL) + char *possiblyMoreAccurateMonitorName = GetAccurateMonitorName(mi.szDevice); + if(possiblyMoreAccurateMonitorName != NULL) { - strncpy(monitor->name, possibleBetterDisplayName, sizeof(monitor->name) - 1); - free(possibleBetterDisplayName); - possibleBetterDisplayName = NULL; + strncpy(monitor->name, possiblyMoreAccurateMonitorName, sizeof(monitor->name) - 1); + free(possiblyMoreAccurateMonitorName); + possiblyMoreAccurateMonitorName = NULL; } } } From 6404b1bba49e9b9fa69cf18adb3106184041f469 Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Sat, 1 Apr 2023 17:13:23 -0400 Subject: [PATCH 04/16] ISO C90 - Split variable initialisation and declaration --- src/win32_monitor.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 88c958c7..d67085cf 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -336,11 +336,16 @@ static char * GetAccurateMonitorName(const WCHAR *deviceName) if(loadWin7MonitorPointers(&dllPointers) == 0) return NULL; - DISPLAYCONFIG_PATH_INFO *paths = NULL; - DISPLAYCONFIG_MODE_INFO *modes = NULL; - char *retval = NULL; - UINT32 pathCount = 0; - UINT32 modeCount = 0; + DISPLAYCONFIG_PATH_INFO *paths; + paths = NULL; + DISPLAYCONFIG_MODE_INFO *modes; + modes = NULL; + char *retval; + retval = NULL; + UINT32 pathCount; + pathCount = 0; + UINT32 modeCount; + modeCount = 0; UINT32 i; LONG rc; @@ -429,7 +434,8 @@ static BOOL CALLBACK monitorCallback(HMONITOR handle, if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0) { monitor->win32.handle = handle; - char *possiblyMoreAccurateMonitorName = GetAccurateMonitorName(mi.szDevice); + char *possiblyMoreAccurateMonitorName; + possiblyMoreAccurateMonitorName = GetAccurateMonitorName(mi.szDevice); if(possiblyMoreAccurateMonitorName != NULL) { strncpy(monitor->name, possiblyMoreAccurateMonitorName, sizeof(monitor->name) - 1); From 648bf7a5fba1ff857f7c510e16c1b16e0a928ac1 Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Sat, 1 Apr 2023 17:19:05 -0400 Subject: [PATCH 05/16] ISO C90 - Mixed declaration and code. --- src/win32_monitor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/win32_monitor.c b/src/win32_monitor.c index d67085cf..aa242837 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -425,6 +425,8 @@ static BOOL CALLBACK monitorCallback(HMONITOR handle, LPARAM data) { MONITORINFOEXW mi; + char *possiblyMoreAccurateMonitorName = NULL; + ZeroMemory(&mi, sizeof(mi)); mi.cbSize = sizeof(mi); @@ -434,7 +436,6 @@ static BOOL CALLBACK monitorCallback(HMONITOR handle, if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0) { monitor->win32.handle = handle; - char *possiblyMoreAccurateMonitorName; possiblyMoreAccurateMonitorName = GetAccurateMonitorName(mi.szDevice); if(possiblyMoreAccurateMonitorName != NULL) { From c87d0ea52bfcebd6226849aa06d5d5290e26d310 Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Sat, 1 Apr 2023 17:22:08 -0400 Subject: [PATCH 06/16] ISO C90 - Mixed declaration and code --- src/win32_monitor.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/win32_monitor.c b/src/win32_monitor.c index aa242837..48af698f 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -337,17 +337,20 @@ static char * GetAccurateMonitorName(const WCHAR *deviceName) return NULL; DISPLAYCONFIG_PATH_INFO *paths; - paths = NULL; DISPLAYCONFIG_MODE_INFO *modes; - modes = NULL; char *retval; - retval = NULL; UINT32 pathCount; - pathCount = 0; UINT32 modeCount; - modeCount = 0; UINT32 i; LONG rc; + + paths = NULL; + modes = NULL; + retval = NULL; + pathCount = 0; + modeCount = 0; + int i = 0; + rc = 0; do { rc = dllPointers.m_GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount); From ec5fbcd07df0e274ca92d8964fc044d39ac3c0cf Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Sat, 1 Apr 2023 17:25:23 -0400 Subject: [PATCH 07/16] Buildfix - Github.dev tricked me with autocomplete... --- src/win32_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 48af698f..1e92782e 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -349,7 +349,7 @@ static char * GetAccurateMonitorName(const WCHAR *deviceName) retval = NULL; pathCount = 0; modeCount = 0; - int i = 0; + i = 0; rc = 0; do { From ffae283e416a7ab689991584aeca7482e9a2707f Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Sat, 1 Apr 2023 17:27:26 -0400 Subject: [PATCH 08/16] ISO C90 again --- src/win32_monitor.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 1e92782e..8679402b 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -332,10 +332,6 @@ BOOL loadWin7MonitorPointers(AccurateMonitorNameRequiredData *io_ptrs) // If the returned pointer is valid (not NULL) the caller of this function is in charge of freeing the memory when he is done. static char * GetAccurateMonitorName(const WCHAR *deviceName) { - AccurateMonitorNameRequiredData dllPointers; - if(loadWin7MonitorPointers(&dllPointers) == 0) - return NULL; - DISPLAYCONFIG_PATH_INFO *paths; DISPLAYCONFIG_MODE_INFO *modes; char *retval; @@ -352,6 +348,10 @@ static char * GetAccurateMonitorName(const WCHAR *deviceName) i = 0; rc = 0; + AccurateMonitorNameRequiredData dllPointers; + if(loadWin7MonitorPointers(&dllPointers) == 0) + return NULL; + do { rc = dllPointers.m_GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount); if (rc != ERROR_SUCCESS) { From 8fe887fe0095936390dd46dcb0136362d3f0a0fc Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Sat, 1 Apr 2023 17:29:06 -0400 Subject: [PATCH 09/16] ISO C90 --- src/win32_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 8679402b..b351f543 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -332,6 +332,7 @@ BOOL loadWin7MonitorPointers(AccurateMonitorNameRequiredData *io_ptrs) // If the returned pointer is valid (not NULL) the caller of this function is in charge of freeing the memory when he is done. static char * GetAccurateMonitorName(const WCHAR *deviceName) { + AccurateMonitorNameRequiredData dllPointers; DISPLAYCONFIG_PATH_INFO *paths; DISPLAYCONFIG_MODE_INFO *modes; char *retval; @@ -348,7 +349,6 @@ static char * GetAccurateMonitorName(const WCHAR *deviceName) i = 0; rc = 0; - AccurateMonitorNameRequiredData dllPointers; if(loadWin7MonitorPointers(&dllPointers) == 0) return NULL; From 6f08e09191dfc311316d104ac40be0cee40a0c8a Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Thu, 6 Apr 2023 19:31:46 -0400 Subject: [PATCH 10/16] Fixed naming according to coding convention Made a function camelCase. --- src/win32_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win32_monitor.c b/src/win32_monitor.c index b351f543..85fe675e 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -330,7 +330,7 @@ BOOL loadWin7MonitorPointers(AccurateMonitorNameRequiredData *io_ptrs) } // If the returned pointer is valid (not NULL) the caller of this function is in charge of freeing the memory when he is done. -static char * GetAccurateMonitorName(const WCHAR *deviceName) +static char * getAccurateMonitorName(const WCHAR *deviceName) { AccurateMonitorNameRequiredData dllPointers; DISPLAYCONFIG_PATH_INFO *paths; From 741ad809b121fd4a5dffe2b0186c0296cefea838 Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Thu, 6 Apr 2023 19:35:37 -0400 Subject: [PATCH 11/16] Fixed some indentations to be consistent with rest of file --- src/win32_monitor.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 85fe675e..e1f1c942 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -352,26 +352,27 @@ static char * getAccurateMonitorName(const WCHAR *deviceName) if(loadWin7MonitorPointers(&dllPointers) == 0) return NULL; - do { + do + { rc = dllPointers.m_GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount); - if (rc != ERROR_SUCCESS) { + if (rc != ERROR_SUCCESS) goto GET_ACCURATE_MONITOR_NAME_FAILURE; - } free(paths); free(modes); paths = (DISPLAYCONFIG_PATH_INFO *) malloc(sizeof (DISPLAYCONFIG_PATH_INFO) * pathCount); modes = (DISPLAYCONFIG_MODE_INFO *) malloc(sizeof (DISPLAYCONFIG_MODE_INFO) * modeCount); - if ((paths == NULL) || (modes == NULL)) { + if ((paths == NULL) || (modes == NULL)) goto GET_ACCURATE_MONITOR_NAME_FAILURE; - } rc = dllPointers.m_QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, paths, &modeCount, modes, 0); } while (rc == ERROR_INSUFFICIENT_BUFFER); - if (rc == ERROR_SUCCESS) { - for (i = 0; i < pathCount; i++) { + if (rc == ERROR_SUCCESS) + { + for (i = 0; i < pathCount; i++) + { DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName; DISPLAYCONFIG_TARGET_DEVICE_NAME targetName; @@ -381,11 +382,10 @@ static char * getAccurateMonitorName(const WCHAR *deviceName) sourceName.header.size = sizeof (sourceName); sourceName.header.id = paths[i].sourceInfo.id; rc = dllPointers.m_DisplayConfigGetDeviceInfo(&sourceName.header); - if (rc != ERROR_SUCCESS) { + if (rc != ERROR_SUCCESS) break; - } else if (wcscmp(deviceName, sourceName.viewGdiDeviceName) != 0) { + else if (wcscmp(deviceName, sourceName.viewGdiDeviceName) != 0) continue; - } ZeroMemory(&targetName, sizeof(targetName)); targetName.header.adapterId = paths[i].targetInfo.adapterId; @@ -393,11 +393,13 @@ static char * getAccurateMonitorName(const WCHAR *deviceName) targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; targetName.header.size = sizeof (targetName); rc = dllPointers.m_DisplayConfigGetDeviceInfo(&targetName.header); - if (rc == ERROR_SUCCESS) { + if (rc == ERROR_SUCCESS) + { retval = _glfwCreateUTF8FromWideStringWin32(targetName.monitorFriendlyDeviceName); /* if we got an empty string, treat it as failure so we'll fallback to getting the generic name. */ - if (retval && (*retval == '\0')) { + if (retval && (*retval == '\0')) + { free(retval); retval = NULL; } From 7e2f1e4c5e56f4c39340dc1bcca625880e7fbd29 Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Thu, 6 Apr 2023 19:36:53 -0400 Subject: [PATCH 12/16] Forgot to rename an reference to a function after I modified the function name --- src/win32_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win32_monitor.c b/src/win32_monitor.c index e1f1c942..8b1683e3 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -441,7 +441,7 @@ static BOOL CALLBACK monitorCallback(HMONITOR handle, if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0) { monitor->win32.handle = handle; - possiblyMoreAccurateMonitorName = GetAccurateMonitorName(mi.szDevice); + possiblyMoreAccurateMonitorName = getAccurateMonitorName(mi.szDevice); if(possiblyMoreAccurateMonitorName != NULL) { strncpy(monitor->name, possiblyMoreAccurateMonitorName, sizeof(monitor->name) - 1); From 72b19e307032fbac22fcc854f27c7a502f380aef Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Sun, 3 Sep 2023 02:03:22 -0400 Subject: [PATCH 13/16] Refactor my code by reusing some facilities provided by GLFW --- src/win32_init.c | 36 ++- src/win32_monitor.c | 512 ++++++++++++------------------------------- src/win32_platform.h | 263 ++++++++++++++++++++++ 3 files changed, 430 insertions(+), 381 deletions(-) diff --git a/src/win32_init.c b/src/win32_init.c index ef2615f1..a60fe8cf 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -83,6 +83,14 @@ static GLFWbool loadLibraries(void) return GLFW_FALSE; } + // ntdll needs to be initialised before user32 because user32 needs IsWindows7OrGreater which depends on ntdll. + _glfw.win32.ntdll.instance = _glfwPlatformLoadModule("ntdll.dll"); + if (_glfw.win32.ntdll.instance) + { + _glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo) + _glfwPlatformGetModuleSymbol(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo"); + } + _glfw.win32.user32.instance = _glfwPlatformLoadModule("user32.dll"); if (!_glfw.win32.user32.instance) { @@ -106,6 +114,27 @@ static GLFWbool loadLibraries(void) _glfw.win32.user32.GetSystemMetricsForDpi_ = (PFN_GetSystemMetricsForDpi) _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "GetSystemMetricsForDpi"); + // Strictly speaking only QueryDisplayConfig requires Windows 7. + // The others two require Windows Vista but we use them in conjunction so I put them all here. + // If down the road someone needs them separately feel free to put the others two in if(IsWindowsVistaOrGreater()) + // You will also probably need to move the structures defined in win32_platform.h #ifdef WINVER < 0x0601 to another + // block with WINVER < 0x0600 aka _WIN32_WINNT_VISTA + if(IsWindows7OrGreater()) + { + _glfw.win32.user32.GetDisplayConfigBufferSizes_ = (PFN_GetDisplayConfigBufferSizes) + _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "GetDisplayConfigBufferSizes"); + _glfw.win32.user32.QueryDisplayConfig_ = (PFN_QueryDisplayConfig) + _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "QueryDisplayConfig"); + _glfw.win32.user32.DisplayConfigGetDeviceInfo_ = (PFN_DisplayConfigGetDeviceInfo) + _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "DisplayConfigGetDeviceInfo"); + } + else + { + _glfw.win32.user32.GetDisplayConfigBufferSizes_ = NULL; + _glfw.win32.user32.QueryDisplayConfig_ = NULL; + _glfw.win32.user32.DisplayConfigGetDeviceInfo_ = NULL; + } + _glfw.win32.dinput8.instance = _glfwPlatformLoadModule("dinput8.dll"); if (_glfw.win32.dinput8.instance) { @@ -162,13 +191,6 @@ static GLFWbool loadLibraries(void) _glfwPlatformGetModuleSymbol(_glfw.win32.shcore.instance, "GetDpiForMonitor"); } - _glfw.win32.ntdll.instance = _glfwPlatformLoadModule("ntdll.dll"); - if (_glfw.win32.ntdll.instance) - { - _glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo) - _glfwPlatformGetModuleSymbol(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo"); - } - return GLFW_TRUE; } diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 8b1683e3..9b137272 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -31,396 +31,156 @@ #if defined(_GLFW_WIN32) +#include #include #include #include #include - -#if WINVER < 0x0601 // To be able to compile on windows Vista and XP even though the feature won't be used. - -typedef struct DISPLAYCONFIG_PATH_SOURCE_INFO -{ - LUID adapterId; - UINT32 id; - union - { - UINT32 modeInfoIdx; - struct - { - UINT32 cloneGroupId : 16; - UINT32 sourceModeInfoIdx : 16; - } DUMMYSTRUCTNAME; - } DUMMYUNIONNAME; - UINT32 statusFlags; -} DISPLAYCONFIG_PATH_SOURCE_INFO; - -typedef enum -{ - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER = -1, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15 = 0, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO = 1, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO = 2, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO = 3, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI = 4, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI = 5, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS = 6, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN = 8, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI = 9, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = 10, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = 11, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL = 12, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED = 13, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE = 14, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST = 15, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INDIRECT_WIRED = 16, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INDIRECT_VIRTUAL = 17, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_USB_TUNNEL, - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL = (int)0x80000000, // Cast required to enforce 4 byte enum. - DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32 = (int)0xFFFFFFFF // Cast required to enforce 4 byte enum. -} DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY; - -typedef enum -{ - DISPLAYCONFIG_ROTATION_IDENTITY = 1, - DISPLAYCONFIG_ROTATION_ROTATE90 = 2, - DISPLAYCONFIG_ROTATION_ROTATE180 = 3, - DISPLAYCONFIG_ROTATION_ROTATE270 = 4, - DISPLAYCONFIG_ROTATION_FORCE_UINT32 = 0xFFFFFFFF -} DISPLAYCONFIG_ROTATION; - -typedef enum -{ - DISPLAYCONFIG_SCALING_IDENTITY = 1, - DISPLAYCONFIG_SCALING_CENTERED = 2, - DISPLAYCONFIG_SCALING_STRETCHED = 3, - DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4, - DISPLAYCONFIG_SCALING_CUSTOM = 5, - DISPLAYCONFIG_SCALING_PREFERRED = 128, - DISPLAYCONFIG_SCALING_FORCE_UINT32 = 0xFFFFFFFF -} DISPLAYCONFIG_SCALING; - -typedef struct DISPLAYCONFIG_RATIONAL -{ - UINT32 Numerator; - UINT32 Denominator; -} DISPLAYCONFIG_RATIONAL; - -typedef enum -{ - DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED = 0, - DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE = 1, - DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED = 2, - DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST, - DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3, - DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32 = 0xFFFFFFFF -} DISPLAYCONFIG_SCANLINE_ORDERING; - -typedef struct DISPLAYCONFIG_PATH_TARGET_INFO -{ - LUID adapterId; - UINT32 id; - union - { - UINT32 modeInfoIdx; - struct - { - UINT32 desktopModeInfoIdx : 16; - UINT32 targetModeInfoIdx : 16; - } DUMMYSTRUCTNAME; - } DUMMYUNIONNAME; - DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology; - DISPLAYCONFIG_ROTATION rotation; - DISPLAYCONFIG_SCALING scaling; - DISPLAYCONFIG_RATIONAL refreshRate; - DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering; - BOOL targetAvailable; - UINT32 statusFlags; -} DISPLAYCONFIG_PATH_TARGET_INFO; - -typedef struct DISPLAYCONFIG_PATH_INFO -{ - DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo; - DISPLAYCONFIG_PATH_TARGET_INFO targetInfo; - UINT32 flags; -} DISPLAYCONFIG_PATH_INFO; - -typedef enum -{ - DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE = 1, - DISPLAYCONFIG_MODE_INFO_TYPE_TARGET = 2, - DISPLAYCONFIG_MODE_INFO_TYPE_DESKTOP_IMAGE = 3, - DISPLAYCONFIG_MODE_INFO_TYPE_FORCE_UINT32 = 0xFFFFFFFF -} DISPLAYCONFIG_MODE_INFO_TYPE; - -typedef struct DISPLAYCONFIG_2DREGION -{ - UINT32 cx; - UINT32 cy; -} DISPLAYCONFIG_2DREGION; - -typedef struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO -{ - UINT64 pixelRate; - DISPLAYCONFIG_RATIONAL hSyncFreq; - DISPLAYCONFIG_RATIONAL vSyncFreq; - DISPLAYCONFIG_2DREGION activeSize; - DISPLAYCONFIG_2DREGION totalSize; - union - { - struct - { - UINT32 videoStandard : 16; - UINT32 vSyncFreqDivider : 6; - UINT32 reserved : 10; - } AdditionalSignalInfo; - UINT32 videoStandard; - } DUMMYUNIONNAME; - DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering; -} DISPLAYCONFIG_VIDEO_SIGNAL_INFO; - -typedef struct DISPLAYCONFIG_TARGET_MODE -{ - DISPLAYCONFIG_VIDEO_SIGNAL_INFO targetVideoSignalInfo; -} DISPLAYCONFIG_TARGET_MODE; - -typedef enum -{ - DISPLAYCONFIG_PIXELFORMAT_8BPP = 1, - DISPLAYCONFIG_PIXELFORMAT_16BPP = 2, - DISPLAYCONFIG_PIXELFORMAT_24BPP = 3, - DISPLAYCONFIG_PIXELFORMAT_32BPP = 4, - DISPLAYCONFIG_PIXELFORMAT_NONGDI = 5, - DISPLAYCONFIG_PIXELFORMAT_FORCE_UINT32 = 0xffffffff -} DISPLAYCONFIG_PIXELFORMAT; - -typedef struct DISPLAYCONFIG_SOURCE_MODE -{ - UINT32 width; - UINT32 height; - DISPLAYCONFIG_PIXELFORMAT pixelFormat; - POINTL position; -} DISPLAYCONFIG_SOURCE_MODE; - -typedef struct DISPLAYCONFIG_DESKTOP_IMAGE_INFO -{ - POINTL PathSourceSize; - RECTL DesktopImageRegion; - RECTL DesktopImageClip; -} DISPLAYCONFIG_DESKTOP_IMAGE_INFO; - -typedef struct DISPLAYCONFIG_MODE_INFO -{ - DISPLAYCONFIG_MODE_INFO_TYPE infoType; - UINT32 id; - LUID adapterId; - union - { - DISPLAYCONFIG_TARGET_MODE targetMode; - DISPLAYCONFIG_SOURCE_MODE sourceMode; - DISPLAYCONFIG_DESKTOP_IMAGE_INFO desktopImageInfo; - } DUMMYUNIONNAME; -} DISPLAYCONFIG_MODE_INFO; - +#if WINVER < 0x0601 // Windows 7 const UINT32 QDC_ONLY_ACTIVE_PATHS = 0x00000002; +#endif -typedef enum +DISPLAYCONFIG_PATH_INFO* getDisplayPaths(UINT32 *out_pathsCount) { - DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1, - DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2, - DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3, - DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME = 4, - DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE = 5, - DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE = 6, - DISPLAYCONFIG_DEVICE_INFO_GET_SUPPORT_VIRTUAL_RESOLUTION = 7, - DISPLAYCONFIG_DEVICE_INFO_SET_SUPPORT_VIRTUAL_RESOLUTION = 8, - DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO = 9, - DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE = 10, - DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL = 11, - DISPLAYCONFIG_DEVICE_INFO_GET_MONITOR_SPECIALIZATION, - DISPLAYCONFIG_DEVICE_INFO_SET_MONITOR_SPECIALIZATION, - DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32 = 0xFFFFFFFF -} DISPLAYCONFIG_DEVICE_INFO_TYPE; - -typedef struct DISPLAYCONFIG_DEVICE_INFO_HEADER { - DISPLAYCONFIG_DEVICE_INFO_TYPE type; - UINT32 size; - LUID adapterId; - UINT32 id; -} DISPLAYCONFIG_DEVICE_INFO_HEADER; - -typedef struct DISPLAYCONFIG_SOURCE_DEVICE_NAME -{ - DISPLAYCONFIG_DEVICE_INFO_HEADER header; - WCHAR viewGdiDeviceName[CCHDEVICENAME]; -} DISPLAYCONFIG_SOURCE_DEVICE_NAME; - -typedef struct DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS -{ - union - { - struct - { - UINT32 friendlyNameFromEdid : 1; - UINT32 friendlyNameForced : 1; - UINT32 edidIdsValid : 1; - UINT32 reserved : 29; - } DUMMYSTRUCTNAME; - UINT32 value; - } DUMMYUNIONNAME; -} DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS; - -typedef struct DISPLAYCONFIG_TARGET_DEVICE_NAME -{ - DISPLAYCONFIG_DEVICE_INFO_HEADER header; - DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS flags; - DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology; - UINT16 edidManufactureId; - UINT16 edidProductCodeId; - UINT32 connectorInstance; - WCHAR monitorFriendlyDeviceName[64]; - WCHAR monitorDevicePath[128]; -} DISPLAYCONFIG_TARGET_DEVICE_NAME; - -typedef enum DISPLAYCONFIG_TOPOLOGY_ID -{ - DISPLAYCONFIG_TOPOLOGY_INTERNAL = 0x00000001, - DISPLAYCONFIG_TOPOLOGY_CLONE = 0x00000002, - DISPLAYCONFIG_TOPOLOGY_EXTEND = 0x00000004, - DISPLAYCONFIG_TOPOLOGY_EXTERNAL = 0x00000008, - DISPLAYCONFIG_TOPOLOGY_FORCE_UINT32 = 0xFFFFFFFF -} DISPLAYCONFIG_TOPOLOGY_ID; - -#endif //#if WINVER < 0x0601 - -typedef LONG (*pGetDisplayConfigBufferSizes)(UINT32 flags, UINT32 *numPathArrayElements, UINT32 *numModeInfoArrayElements); -typedef LONG (*pQueryDisplayConfig)(UINT32 flags, UINT32 *numPathArrayElements, DISPLAYCONFIG_PATH_INFO *pathArray, UINT32 *numModeInfoArrayElements, DISPLAYCONFIG_MODE_INFO *modeInfoArray, DISPLAYCONFIG_TOPOLOGY_ID *currentTopologyId); -typedef LONG (*pDisplayConfigGetDeviceInfo)(DISPLAYCONFIG_DEVICE_INFO_HEADER* requestPacket); - -typedef struct AccurateMonitorNameRequiredData -{ - HMODULE m_dll; - pGetDisplayConfigBufferSizes m_GetDisplayConfigBufferSizes; - pQueryDisplayConfig m_QueryDisplayConfig; - pDisplayConfigGetDeviceInfo m_DisplayConfigGetDeviceInfo; -} AccurateMonitorNameRequiredData; - -BOOL loadWin7MonitorPointers(AccurateMonitorNameRequiredData *io_ptrs) -{ - if(!IsWindows7OrGreater()) - return 0; - - io_ptrs->m_dll = LoadLibrary(L"User32.dll"); - if (io_ptrs == NULL) - return 0; - - io_ptrs->m_GetDisplayConfigBufferSizes = (pGetDisplayConfigBufferSizes)GetProcAddress(io_ptrs->m_dll, "GetDisplayConfigBufferSizes"); - if(io_ptrs->m_GetDisplayConfigBufferSizes == NULL) - return 0; - - io_ptrs->m_QueryDisplayConfig = (pQueryDisplayConfig)GetProcAddress(io_ptrs->m_dll, "QueryDisplayConfig"); - if(io_ptrs->m_QueryDisplayConfig == NULL) - return 0; - - io_ptrs->m_DisplayConfigGetDeviceInfo = (pDisplayConfigGetDeviceInfo)GetProcAddress(io_ptrs->m_dll, "DisplayConfigGetDeviceInfo"); - if(io_ptrs->m_DisplayConfigGetDeviceInfo == NULL) - return 0; - - return 1; -} - -// If the returned pointer is valid (not NULL) the caller of this function is in charge of freeing the memory when he is done. -static char * getAccurateMonitorName(const WCHAR *deviceName) -{ - AccurateMonitorNameRequiredData dllPointers; DISPLAYCONFIG_PATH_INFO *paths; DISPLAYCONFIG_MODE_INFO *modes; - char *retval; - UINT32 pathCount; UINT32 modeCount; - UINT32 i; + UINT32 pathsCount; LONG rc; - + paths = NULL; modes = NULL; - retval = NULL; - pathCount = 0; modeCount = 0; - i = 0; + pathsCount = 0; rc = 0; - if(loadWin7MonitorPointers(&dllPointers) == 0) - return NULL; - do { - rc = dllPointers.m_GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount); + rc = GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathsCount, &modeCount); if (rc != ERROR_SUCCESS) - goto GET_ACCURATE_MONITOR_NAME_FAILURE; + break; - free(paths); - free(modes); - - paths = (DISPLAYCONFIG_PATH_INFO *) malloc(sizeof (DISPLAYCONFIG_PATH_INFO) * pathCount); + assert(paths == NULL); + assert(modes == NULL); + paths = (DISPLAYCONFIG_PATH_INFO *) malloc(sizeof (DISPLAYCONFIG_PATH_INFO) * pathsCount); modes = (DISPLAYCONFIG_MODE_INFO *) malloc(sizeof (DISPLAYCONFIG_MODE_INFO) * modeCount); - if ((paths == NULL) || (modes == NULL)) - goto GET_ACCURATE_MONITOR_NAME_FAILURE; - rc = dllPointers.m_QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, paths, &modeCount, modes, 0); - } while (rc == ERROR_INSUFFICIENT_BUFFER); - - if (rc == ERROR_SUCCESS) - { - for (i = 0; i < pathCount; i++) + if (paths == NULL) { - DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName; - DISPLAYCONFIG_TARGET_DEVICE_NAME targetName; - - ZeroMemory(&sourceName, sizeof(sourceName)); - sourceName.header.adapterId = paths[i].targetInfo.adapterId; - sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME; - sourceName.header.size = sizeof (sourceName); - sourceName.header.id = paths[i].sourceInfo.id; - rc = dllPointers.m_DisplayConfigGetDeviceInfo(&sourceName.header); - if (rc != ERROR_SUCCESS) - break; - else if (wcscmp(deviceName, sourceName.viewGdiDeviceName) != 0) - continue; - - ZeroMemory(&targetName, sizeof(targetName)); - targetName.header.adapterId = paths[i].targetInfo.adapterId; - targetName.header.id = paths[i].targetInfo.id; - targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; - targetName.header.size = sizeof (targetName); - rc = dllPointers.m_DisplayConfigGetDeviceInfo(&targetName.header); - if (rc == ERROR_SUCCESS) - { - retval = _glfwCreateUTF8FromWideStringWin32(targetName.monitorFriendlyDeviceName); - /* if we got an empty string, treat it as failure so we'll fallback - to getting the generic name. */ - if (retval && (*retval == '\0')) - { - free(retval); - retval = NULL; - } - } + free(modes); + modes = NULL; break; } - } - FreeLibrary(dllPointers.m_dll); - free(paths); - free(modes); - return retval; + if(modes == NULL) + { + free(paths); + paths = NULL; + break; + } -GET_ACCURATE_MONITOR_NAME_FAILURE: - FreeLibrary(dllPointers.m_dll); - free(retval); - free(paths); - free(modes); - return NULL; + rc = QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathsCount, paths, &modeCount, modes, 0); + if (rc == ERROR_SUCCESS) + { + free(modes); // We won't use it. + modes = NULL; + } + else + { + free(paths); + paths = NULL; + free(modes); + modes = NULL; + } + + } while (rc == ERROR_INSUFFICIENT_BUFFER); + + assert(modes == NULL); + + *out_pathsCount = pathsCount; + return paths; } +char* getMonitorNameFromPath(const WCHAR *deviceName, const DISPLAYCONFIG_PATH_INFO *paths, const UINT32 pathCount) +{ + UINT32 i; + LONG rc; + char *monitorName; + + i = 0; + rc = 0; + monitorName = NULL; + + for (i = 0; i < pathCount; i++) + { + DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName; + DISPLAYCONFIG_TARGET_DEVICE_NAME targetName; + + ZeroMemory(&sourceName, sizeof(sourceName)); + sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME; + sourceName.header.size = sizeof (sourceName); + sourceName.header.adapterId = paths[i].sourceInfo.adapterId; + sourceName.header.id = paths[i].sourceInfo.id; + + rc = DisplayConfigGetDeviceInfo(&sourceName.header); + if (rc != ERROR_SUCCESS) + break; + + if (wcscmp(deviceName, sourceName.viewGdiDeviceName) != 0) + continue; + + ZeroMemory(&targetName, sizeof(targetName)); + targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; + targetName.header.size = sizeof (targetName); + targetName.header.adapterId = paths[i].targetInfo.adapterId; + targetName.header.id = paths[i].targetInfo.id; + + rc = DisplayConfigGetDeviceInfo(&targetName.header); + if (rc != ERROR_SUCCESS) + break; + + monitorName = _glfwCreateUTF8FromWideStringWin32(targetName.monitorFriendlyDeviceName); + if (monitorName && (*monitorName == '\0')) // If we got an empty string, treat it as failure so we'll fallback to getting the generic name. + { + free(monitorName); + monitorName = NULL; + } + break; + } + + return monitorName; +} + +// Returns NULL if an error happens or the OS doesn't provide the needed feature (anything below Win7) +// If the pointer is valid, the caller takes ownership of the underlying memory and has to free it when done. +// +char* tryGetAccurateMonitorName(const WCHAR *deviceName) +{ + char *monitorName; + DISPLAYCONFIG_PATH_INFO *paths; + UINT32 pathCount; + + monitorName = NULL; + paths = NULL; + pathCount = 0; + + if(QueryDisplayConfig == NULL) + return NULL; + + // If QueryDisplayConfig is present then GetDisplayConfigBufferSizes and DisplayConfigGetDeviceInfo also should be present. + assert(GetDisplayConfigBufferSizes != NULL); + assert(DisplayConfigGetDeviceInfo != NULL); + + paths = getDisplayPaths(&pathCount); + if (paths == NULL) + return NULL; + + monitorName = getMonitorNameFromPath(deviceName, paths, pathCount); + + free(paths); + return monitorName; +} // Callback for EnumDisplayMonitors in createMonitor // @@ -430,25 +190,29 @@ static BOOL CALLBACK monitorCallback(HMONITOR handle, LPARAM data) { MONITORINFOEXW mi; - char *possiblyMoreAccurateMonitorName = NULL; + char* accurateMonitorName = NULL; ZeroMemory(&mi, sizeof(mi)); mi.cbSize = sizeof(mi); - if (GetMonitorInfoW(handle, (MONITORINFO*) &mi)) + if (GetMonitorInfoW(handle, (MONITORINFO*) &mi) == 0) + return TRUE; + + _GLFWmonitor* monitor = (_GLFWmonitor*) data; + if (wcscmp(mi.szDevice, monitor->win32.adapterName) != 0) + return TRUE; + + // If the monitor driver is installed, we will already have an accurate name for the monitor. + if (strcmp(monitor->name, "Generic PnP Monitor") != 0) + return TRUE; + + monitor->win32.handle = handle; + accurateMonitorName = tryGetAccurateMonitorName(mi.szDevice); + if(accurateMonitorName != NULL) { - _GLFWmonitor* monitor = (_GLFWmonitor*) data; - if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0) - { - monitor->win32.handle = handle; - possiblyMoreAccurateMonitorName = getAccurateMonitorName(mi.szDevice); - if(possiblyMoreAccurateMonitorName != NULL) - { - strncpy(monitor->name, possiblyMoreAccurateMonitorName, sizeof(monitor->name) - 1); - free(possiblyMoreAccurateMonitorName); - possiblyMoreAccurateMonitorName = NULL; - } - } + strncpy(monitor->name, accurateMonitorName, sizeof(monitor->name) - 1); + free(accurateMonitorName); + accurateMonitorName = NULL; } return TRUE; diff --git a/src/win32_platform.h b/src/win32_platform.h index 82b34bb9..82df9f2e 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -126,6 +126,259 @@ typedef struct #ifndef MSGFLT_ALLOW #define MSGFLT_ALLOW 1 #endif + +typedef struct DISPLAYCONFIG_PATH_SOURCE_INFO +{ + LUID adapterId; + UINT32 id; + union + { + UINT32 modeInfoIdx; + struct + { + UINT32 cloneGroupId : 16; + UINT32 sourceModeInfoIdx : 16; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + UINT32 statusFlags; +} DISPLAYCONFIG_PATH_SOURCE_INFO; + +typedef enum +{ + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER = -1, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15 = 0, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO = 1, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO = 2, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO = 3, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI = 4, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI = 5, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS = 6, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN = 8, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI = 9, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = 10, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = 11, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL = 12, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED = 13, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE = 14, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST = 15, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INDIRECT_WIRED = 16, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INDIRECT_VIRTUAL = 17, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_USB_TUNNEL, + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL = (int)0x80000000, // Cast required to enforce 4 byte enum. + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32 = (int)0xFFFFFFFF // Cast required to enforce 4 byte enum. +} DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY; + +typedef enum +{ + DISPLAYCONFIG_ROTATION_IDENTITY = 1, + DISPLAYCONFIG_ROTATION_ROTATE90 = 2, + DISPLAYCONFIG_ROTATION_ROTATE180 = 3, + DISPLAYCONFIG_ROTATION_ROTATE270 = 4, + DISPLAYCONFIG_ROTATION_FORCE_UINT32 = 0xFFFFFFFF +} DISPLAYCONFIG_ROTATION; + +typedef enum +{ + DISPLAYCONFIG_SCALING_IDENTITY = 1, + DISPLAYCONFIG_SCALING_CENTERED = 2, + DISPLAYCONFIG_SCALING_STRETCHED = 3, + DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4, + DISPLAYCONFIG_SCALING_CUSTOM = 5, + DISPLAYCONFIG_SCALING_PREFERRED = 128, + DISPLAYCONFIG_SCALING_FORCE_UINT32 = 0xFFFFFFFF +} DISPLAYCONFIG_SCALING; + +typedef struct DISPLAYCONFIG_RATIONAL +{ + UINT32 Numerator; + UINT32 Denominator; +} DISPLAYCONFIG_RATIONAL; + +typedef enum +{ + DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED = 0, + DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE = 1, + DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED = 2, + DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST, + DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3, + DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32 = 0xFFFFFFFF +} DISPLAYCONFIG_SCANLINE_ORDERING; + +typedef struct DISPLAYCONFIG_PATH_TARGET_INFO +{ + LUID adapterId; + UINT32 id; + union + { + UINT32 modeInfoIdx; + struct + { + UINT32 desktopModeInfoIdx : 16; + UINT32 targetModeInfoIdx : 16; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology; + DISPLAYCONFIG_ROTATION rotation; + DISPLAYCONFIG_SCALING scaling; + DISPLAYCONFIG_RATIONAL refreshRate; + DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering; + BOOL targetAvailable; + UINT32 statusFlags; +} DISPLAYCONFIG_PATH_TARGET_INFO; + +typedef struct DISPLAYCONFIG_PATH_INFO +{ + DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo; + DISPLAYCONFIG_PATH_TARGET_INFO targetInfo; + UINT32 flags; +} DISPLAYCONFIG_PATH_INFO; + +typedef enum +{ + DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE = 1, + DISPLAYCONFIG_MODE_INFO_TYPE_TARGET = 2, + DISPLAYCONFIG_MODE_INFO_TYPE_DESKTOP_IMAGE = 3, + DISPLAYCONFIG_MODE_INFO_TYPE_FORCE_UINT32 = 0xFFFFFFFF +} DISPLAYCONFIG_MODE_INFO_TYPE; + +typedef struct DISPLAYCONFIG_2DREGION +{ + UINT32 cx; + UINT32 cy; +} DISPLAYCONFIG_2DREGION; + +typedef struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO +{ + UINT64 pixelRate; + DISPLAYCONFIG_RATIONAL hSyncFreq; + DISPLAYCONFIG_RATIONAL vSyncFreq; + DISPLAYCONFIG_2DREGION activeSize; + DISPLAYCONFIG_2DREGION totalSize; + union + { + struct + { + UINT32 videoStandard : 16; + UINT32 vSyncFreqDivider : 6; + UINT32 reserved : 10; + } AdditionalSignalInfo; + UINT32 videoStandard; + } DUMMYUNIONNAME; + DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering; +} DISPLAYCONFIG_VIDEO_SIGNAL_INFO; + +typedef struct DISPLAYCONFIG_TARGET_MODE +{ + DISPLAYCONFIG_VIDEO_SIGNAL_INFO targetVideoSignalInfo; +} DISPLAYCONFIG_TARGET_MODE; + +typedef enum +{ + DISPLAYCONFIG_PIXELFORMAT_8BPP = 1, + DISPLAYCONFIG_PIXELFORMAT_16BPP = 2, + DISPLAYCONFIG_PIXELFORMAT_24BPP = 3, + DISPLAYCONFIG_PIXELFORMAT_32BPP = 4, + DISPLAYCONFIG_PIXELFORMAT_NONGDI = 5, + DISPLAYCONFIG_PIXELFORMAT_FORCE_UINT32 = 0xffffffff +} DISPLAYCONFIG_PIXELFORMAT; + +typedef struct DISPLAYCONFIG_SOURCE_MODE +{ + UINT32 width; + UINT32 height; + DISPLAYCONFIG_PIXELFORMAT pixelFormat; + POINTL position; +} DISPLAYCONFIG_SOURCE_MODE; + +typedef struct DISPLAYCONFIG_DESKTOP_IMAGE_INFO +{ + POINTL PathSourceSize; + RECTL DesktopImageRegion; + RECTL DesktopImageClip; +} DISPLAYCONFIG_DESKTOP_IMAGE_INFO; + +typedef struct DISPLAYCONFIG_MODE_INFO +{ + DISPLAYCONFIG_MODE_INFO_TYPE infoType; + UINT32 id; + LUID adapterId; + union + { + DISPLAYCONFIG_TARGET_MODE targetMode; + DISPLAYCONFIG_SOURCE_MODE sourceMode; + DISPLAYCONFIG_DESKTOP_IMAGE_INFO desktopImageInfo; + } DUMMYUNIONNAME; +} DISPLAYCONFIG_MODE_INFO; + +extern const UINT32 QDC_ONLY_ACTIVE_PATHS; + +typedef enum +{ + DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1, + DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2, + DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3, + DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME = 4, + DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE = 5, + DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE = 6, + DISPLAYCONFIG_DEVICE_INFO_GET_SUPPORT_VIRTUAL_RESOLUTION = 7, + DISPLAYCONFIG_DEVICE_INFO_SET_SUPPORT_VIRTUAL_RESOLUTION = 8, + DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO = 9, + DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE = 10, + DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL = 11, + DISPLAYCONFIG_DEVICE_INFO_GET_MONITOR_SPECIALIZATION, + DISPLAYCONFIG_DEVICE_INFO_SET_MONITOR_SPECIALIZATION, + DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32 = 0xFFFFFFFF +} DISPLAYCONFIG_DEVICE_INFO_TYPE; + +typedef struct DISPLAYCONFIG_DEVICE_INFO_HEADER { + DISPLAYCONFIG_DEVICE_INFO_TYPE type; + UINT32 size; + LUID adapterId; + UINT32 id; +} DISPLAYCONFIG_DEVICE_INFO_HEADER; + +typedef struct DISPLAYCONFIG_SOURCE_DEVICE_NAME +{ + DISPLAYCONFIG_DEVICE_INFO_HEADER header; + WCHAR viewGdiDeviceName[CCHDEVICENAME]; +} DISPLAYCONFIG_SOURCE_DEVICE_NAME; + +typedef struct DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS +{ + union + { + struct + { + UINT32 friendlyNameFromEdid : 1; + UINT32 friendlyNameForced : 1; + UINT32 edidIdsValid : 1; + UINT32 reserved : 29; + } DUMMYSTRUCTNAME; + UINT32 value; + } DUMMYUNIONNAME; +} DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS; + +typedef struct DISPLAYCONFIG_TARGET_DEVICE_NAME +{ + DISPLAYCONFIG_DEVICE_INFO_HEADER header; + DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS flags; + DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology; + UINT16 edidManufactureId; + UINT16 edidProductCodeId; + UINT32 connectorInstance; + WCHAR monitorFriendlyDeviceName[64]; + WCHAR monitorDevicePath[128]; +} DISPLAYCONFIG_TARGET_DEVICE_NAME; + +typedef enum DISPLAYCONFIG_TOPOLOGY_ID +{ + DISPLAYCONFIG_TOPOLOGY_INTERNAL = 0x00000001, + DISPLAYCONFIG_TOPOLOGY_CLONE = 0x00000002, + DISPLAYCONFIG_TOPOLOGY_EXTEND = 0x00000004, + DISPLAYCONFIG_TOPOLOGY_EXTERNAL = 0x00000008, + DISPLAYCONFIG_TOPOLOGY_FORCE_UINT32 = 0xFFFFFFFF +} DISPLAYCONFIG_TOPOLOGY_ID; + #endif /*Windows 7*/ #if WINVER < 0x0600 @@ -288,6 +541,10 @@ typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE); typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND); typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT); typedef int (WINAPI * PFN_GetSystemMetricsForDpi)(int,UINT); +typedef LONG (WINAPI * PFN_GetDisplayConfigBufferSizes)(UINT32,UINT32*,UINT32*); +typedef LONG (WINAPI * PFN_QueryDisplayConfig)(UINT32,UINT32*,DISPLAYCONFIG_PATH_INFO*,UINT32*,DISPLAYCONFIG_MODE_INFO*,DISPLAYCONFIG_TOPOLOGY_ID*); +typedef LONG (WINAPI * PFN_DisplayConfigGetDeviceInfo)(DISPLAYCONFIG_DEVICE_INFO_HEADER*); + #define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_ #define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_ #define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_ @@ -295,6 +552,9 @@ typedef int (WINAPI * PFN_GetSystemMetricsForDpi)(int,UINT); #define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_ #define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_ #define GetSystemMetricsForDpi _glfw.win32.user32.GetSystemMetricsForDpi_ +#define GetDisplayConfigBufferSizes _glfw.win32.user32.GetDisplayConfigBufferSizes_ +#define QueryDisplayConfig _glfw.win32.user32.QueryDisplayConfig_ +#define DisplayConfigGetDeviceInfo _glfw.win32.user32.DisplayConfigGetDeviceInfo_ // dwmapi.dll function pointer typedefs typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*); @@ -479,6 +739,9 @@ typedef struct _GLFWlibraryWin32 PFN_GetDpiForWindow GetDpiForWindow_; PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_; PFN_GetSystemMetricsForDpi GetSystemMetricsForDpi_; + PFN_GetDisplayConfigBufferSizes GetDisplayConfigBufferSizes_; + PFN_QueryDisplayConfig QueryDisplayConfig_; + PFN_DisplayConfigGetDeviceInfo DisplayConfigGetDeviceInfo_; } user32; struct { From 71dfe1fc457ae4891ab973971982426f3ab7ae7a Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Sun, 3 Sep 2023 02:11:00 -0400 Subject: [PATCH 14/16] ISO C90 --- src/win32_monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 9b137272..8791f39b 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -191,6 +191,7 @@ static BOOL CALLBACK monitorCallback(HMONITOR handle, { MONITORINFOEXW mi; char* accurateMonitorName = NULL; + _GLFWmonitor* monitor = (_GLFWmonitor*) data; ZeroMemory(&mi, sizeof(mi)); mi.cbSize = sizeof(mi); @@ -198,7 +199,6 @@ static BOOL CALLBACK monitorCallback(HMONITOR handle, if (GetMonitorInfoW(handle, (MONITORINFO*) &mi) == 0) return TRUE; - _GLFWmonitor* monitor = (_GLFWmonitor*) data; if (wcscmp(mi.szDevice, monitor->win32.adapterName) != 0) return TRUE; From 99ed2a3d22d123ad856ec2852ef6f0409d58f58a Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Mon, 4 Sep 2023 02:59:40 -0400 Subject: [PATCH 15/16] Bugfix: Fix skipping monitor handle assignation when monitor name was not generic Found the issue why fullscreen was not working --- src/win32_monitor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 8791f39b..8c308ae2 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -202,11 +202,12 @@ static BOOL CALLBACK monitorCallback(HMONITOR handle, if (wcscmp(mi.szDevice, monitor->win32.adapterName) != 0) return TRUE; + monitor->win32.handle = handle; + // If the monitor driver is installed, we will already have an accurate name for the monitor. if (strcmp(monitor->name, "Generic PnP Monitor") != 0) return TRUE; - monitor->win32.handle = handle; accurateMonitorName = tryGetAccurateMonitorName(mi.szDevice); if(accurateMonitorName != NULL) { From 9f7a40059ec87826f5c25021986f55b3d39277ac Mon Sep 17 00:00:00 2001 From: Scr3amer Date: Tue, 26 Sep 2023 08:36:40 -0400 Subject: [PATCH 16/16] Bugfix : handle localised default monitor names If your OS is not in English you won't have "Generic PnP Monitor" so the test will succeed inspite of having a localised default monitor name. I changed the test to look for the output port between parenthesis as this is how the monitor will look like when driver is installed AFAICT. --- src/win32_monitor.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 8c308ae2..a92a2080 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -182,6 +182,14 @@ char* tryGetAccurateMonitorName(const WCHAR *deviceName) return monitorName; } +BOOL nameContainsOutputPort(const char *const i_nameToCheck) +{ + const size_t nameLength = strlen(i_nameToCheck); + const char lastChar = i_nameToCheck[nameLength - 1]; + + return lastChar == ')'; // Non generic initial names contain the output port use. E.g. MonitorName(DisplayPort) +} + // Callback for EnumDisplayMonitors in createMonitor // static BOOL CALLBACK monitorCallback(HMONITOR handle, @@ -205,7 +213,7 @@ static BOOL CALLBACK monitorCallback(HMONITOR handle, monitor->win32.handle = handle; // If the monitor driver is installed, we will already have an accurate name for the monitor. - if (strcmp(monitor->name, "Generic PnP Monitor") != 0) + if (nameContainsOutputPort(monitor->name)) return TRUE; accurateMonitorName = tryGetAccurateMonitorName(mi.szDevice);