summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-07-02 12:44:58 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-01-07 12:00:47 +0100
commit4c6c0948955988ad93d2960ac8b7f64eaca42b58 (patch)
tree839aa16ef599339d41dc0f4ef0587f94993fcbf2 /src/plugins/platforms/windows
parentac970d48fdd35b03686d4c77d955875d6e8b1d68 (diff)
Windows QPA: Lookup DISPLAYCONFIG data for monitors
Gives more accurate orientation and refresh-rate. Change-Id: I90b0b7563efc35c9bace07ccb3996350a957e8e5 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Diffstat (limited to 'src/plugins/platforms/windows')
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp96
1 files changed, 94 insertions, 2 deletions
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index a15a39c2a4..cddc384418 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -74,6 +74,70 @@ static inline QDpi monitorDPI(HMONITOR hMonitor)
return {0, 0};
}
+static bool getPathInfo(const MONITORINFOEX &viewInfo, DISPLAYCONFIG_PATH_INFO *pathInfo)
+{
+ // We might want to consider storing adapterId/id from DISPLAYCONFIG_PATH_TARGET_INFO.
+ std::vector<DISPLAYCONFIG_PATH_INFO> pathInfos;
+ std::vector<DISPLAYCONFIG_MODE_INFO> modeInfos;
+
+ // Fetch paths
+ LONG result;
+ UINT32 numPathArrayElements;
+ UINT32 numModeInfoArrayElements;
+ do {
+ // QueryDisplayConfig documentation doesn't say the number of needed elements is updated
+ // when the call fails with ERROR_INSUFFICIENT_BUFFER, so we need a separate call to
+ // look up the needed buffer sizes.
+ if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &numPathArrayElements,
+ &numModeInfoArrayElements) != ERROR_SUCCESS) {
+ return false;
+ }
+ pathInfos.resize(numPathArrayElements);
+ modeInfos.resize(numModeInfoArrayElements);
+ result = QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &numPathArrayElements, pathInfos.data(),
+ &numModeInfoArrayElements, modeInfos.data(), nullptr);
+ } while (result == ERROR_INSUFFICIENT_BUFFER);
+
+ if (result != ERROR_SUCCESS)
+ return false;
+
+ // Find path matching monitor name
+ for (uint32_t p = 0; p < numPathArrayElements; p++) {
+ DISPLAYCONFIG_SOURCE_DEVICE_NAME deviceName;
+ deviceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
+ deviceName.header.size = sizeof(DISPLAYCONFIG_SOURCE_DEVICE_NAME);
+ deviceName.header.adapterId = pathInfos[p].sourceInfo.adapterId;
+ deviceName.header.id = pathInfos[p].sourceInfo.id;
+ if (DisplayConfigGetDeviceInfo(&deviceName.header) == ERROR_SUCCESS) {
+ if (wcscmp(viewInfo.szDevice, deviceName.viewGdiDeviceName) == 0) {
+ *pathInfo = pathInfos[p];
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+#if 0
+// Needed later for HDR support
+static float getMonitorSDRWhiteLevel(DISPLAYCONFIG_PATH_TARGET_INFO *targetInfo)
+{
+ const float defaultSdrWhiteLevel = 200.0;
+ if (!targetInfo)
+ return defaultSdrWhiteLevel;
+
+ DISPLAYCONFIG_SDR_WHITE_LEVEL whiteLevel = {};
+ whiteLevel.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL;
+ whiteLevel.header.size = sizeof(DISPLAYCONFIG_SDR_WHITE_LEVEL);
+ whiteLevel.header.adapterId = targetInfo->adapterId;
+ whiteLevel.header.id = targetInfo->id;
+ if (DisplayConfigGetDeviceInfo(&whiteLevel.header) != ERROR_SUCCESS)
+ return defaultSdrWhiteLevel;
+ return whiteLevel.SDRWhiteLevel * 80.0 / 1000.0;
+}
+#endif
+
using WindowsScreenDataList = QList<QWindowsScreenData>;
static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data)
@@ -107,8 +171,36 @@ static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data)
data->dpi.first);
} // CreateDC() failed
} // not lock screen
- data->orientation = data->geometry.height() > data->geometry.width() ?
- Qt::PortraitOrientation : Qt::LandscapeOrientation;
+
+ // ### We might want to consider storing adapterId/id from DISPLAYCONFIG_PATH_TARGET_INFO,
+ // if we are going to use DISPLAYCONFIG lookups more.
+ DISPLAYCONFIG_PATH_INFO pathInfo = {};
+ if (getPathInfo(info, &pathInfo)) {
+ switch (pathInfo.targetInfo.rotation) {
+ case DISPLAYCONFIG_ROTATION_IDENTITY:
+ data->orientation = Qt::LandscapeOrientation;
+ break;
+ case DISPLAYCONFIG_ROTATION_ROTATE90:
+ data->orientation = Qt::PortraitOrientation;
+ break;
+ case DISPLAYCONFIG_ROTATION_ROTATE180:
+ data->orientation = Qt::InvertedLandscapeOrientation;
+ break;
+ case DISPLAYCONFIG_ROTATION_ROTATE270:
+ data->orientation = Qt::InvertedPortraitOrientation;
+ break;
+ case DISPLAYCONFIG_ROTATION_FORCE_UINT32:
+ Q_UNREACHABLE();
+ break;
+ }
+ if (pathInfo.targetInfo.refreshRate.Numerator && pathInfo.targetInfo.refreshRate.Denominator)
+ data->refreshRateHz = static_cast<qreal>(pathInfo.targetInfo.refreshRate.Numerator)
+ / pathInfo.targetInfo.refreshRate.Denominator;
+ } else {
+ data->orientation = data->geometry.height() > data->geometry.width()
+ ? Qt::PortraitOrientation
+ : Qt::LandscapeOrientation;
+ }
// EnumDisplayMonitors (as opposed to EnumDisplayDevices) enumerates only
// virtual desktop screens.
data->flags |= QWindowsScreenData::VirtualDesktop;