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>bb10
parent
ac970d48fd
commit
4c6c094895
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue