Details
-
Bug
-
Resolution: Incomplete
-
P2: Important
-
None
-
5.5.0 RC, 5.15.2
-
None
-
Windows
Description
QScreen is misreporting screen dimensions when using two monitors. This results in QQuickView windows being drawn at twice the expected size.
One is high DPI, and the lower DPI monitor is set as the main monitor. I have two monitors, configured in this manner:
- Dell XPS 15 laptop monitor, resolution set to recommended resolution 3840 * 1260 ("DISPLAY1")
- Dell U2414Hb External monitor set to recommended resolution 1920 * 1080 ("DISPLAY2")
- Windows scaling set with slider set to the second highest option. NOT set to "one scaling level for all my displays".
I get the following results. Take note of the difference in screen size dimensions as reported by Qt's QScreen vs. Windows' EnumDisplayDevices. I've put the full reports into a comment, for reference. Here I'm only listing the things that appear to be wrong
Scenario #1: Laptop monitor ("DISPLAY1") set as main display. This is good and presented just for illustration; our windows are drawn at the expected size here.
QScreen Information for screen: "\\\\.\\DISPLAY1" Available geometry: 0 0 1920 x 1036 Available size: 1920 x 1036 Logical DPI: 120 Logical DPI X: 120 Logical DPI Y: 120 Results from Windows EnumDisplayDevices: DPIAware= 2 Display 0 : DeviceName = "\\\\.\\DISPLAY1" StateFlags = 5 EffectiveDPIX = 240 EffectiveDPIY = 240 ClippingRect = QRect(0,0 1920x1036) QScreen Information for screen: "\\\\.\\DISPLAY2" Available geometry: 1920 0 960 x 540 Available size: 960 x 540 Logical DPI: 48 Logical DPI X: 48 Logical DPI Y: 48 Results from Windows EnumDisplayDevices: DPIAware= 2 Display 1 : DeviceName = "\\\\.\\DISPLAY2" StateFlags = 1 EffectiveDPIX = 240 EffectiveDPIY = 240 ClippingRect = QRect(1920,0 960x540)
Scenario #2: External monitor ("DISPLAY2") set as main display. Here you will notice a discrepancy in the Available geometry reported by QScreen vs. the ClippingRect reported by Windows. It almost appears like the two displays' geometries got swapped. Our windows display at twice the expected size in DISPLAY2.
QScreen Information for screen: "\\\\.\\DISPLAY2" Available geometry: 0 0 960 x 499 Available size: 960 x 499 Logical DPI X: 48 Logical DPI Y: 48 Results from Windows EnumDisplayDevices: DPIAware= 2 Display 1 : DeviceName = "\\\\.\\DISPLAY2" StateFlags = 5 EffectiveDPIX = 240 EffectiveDPIY = 240 ClippingRect = QRect(-1920,0 1920x1060) QScreen Information for screen: "\\\\.\\DISPLAY1" Available geometry: -1920 0 1920 x 1060 Available size: 1920 x 1060 Logical DPI X: 120 Logical DPI Y: 120 Results from Windows EnumDisplayDevices: DPIAware= 2 Display 0 : DeviceName = "\\\\.\\DISPLAY1" StateFlags = 1 EffectiveDPIX = 96 EffectiveDPIY = 96 ClippingRect = QRect(0,0 960x499)
The following code snippet in our app was used to generate the logs provided above. logs the screen dimensions as reported by QScreen and by EnumDisplayDevices.
QList<QRect> rectList; qDebug() << "\nResults from QScreen: DevicePixelRation=" << this->devicePixelRatio(); foreach (QScreen *screen, QGuiApplication::screens()) { qDebug() << "Information for screen:" << screen->name(); qDebug() << " Available geometry:" << screen->availableGeometry().x() << screen->availableGeometry().y() << screen->availableGeometry().width() << "x" << screen->availableGeometry().height(); qDebug() << " Available size:" << screen->availableSize().width() << "x" << screen->availableSize().height(); qDebug() << " Available virtual geometry:" << screen->availableVirtualGeometry().x() << screen->availableVirtualGeometry().y() << screen->availableVirtualGeometry().width() << "x" << screen->availableVirtualGeometry().height(); qDebug() << " Available virtual size:" << screen->availableVirtualSize().width() << "x" << screen->availableVirtualSize().height(); qDebug() << " Depth:" << screen->depth() << "bits"; qDebug() << " Geometry:" << screen->geometry().x() << screen->geometry().y() << screen->geometry().width() << "x" << screen->geometry().height(); qDebug() << " Logical DPI:" << screen->logicalDotsPerInch(); qDebug() << " Logical DPI X:" << screen->logicalDotsPerInchX(); qDebug() << " Logical DPI Y:" << screen->logicalDotsPerInchY(); qDebug() << " Orientation:" << screen->orientation(); qDebug() << " Physical DPI:" << screen->physicalDotsPerInch(); qDebug() << " Physical DPI X:" << screen->physicalDotsPerInchX(); qDebug() << " Physical DPI Y:" << screen->physicalDotsPerInchY(); qDebug() << " Physical size:" << screen->physicalSize().width() << "x" << screen->physicalSize().height() << "mm"; qDebug() << " Primary orientation:" << screen->primaryOrientation(); qDebug() << " Refresh rate:" << screen->refreshRate() << "Hz"; qDebug() << " Size:" << screen->size().width() << "x" << screen->size().height(); qDebug() << " Virtual geometry:" << screen->virtualGeometry().x() << screen->virtualGeometry().y() << screen->virtualGeometry().width() << "x" << screen->virtualGeometry().height(); qDebug() << " Virtual size:" << screen->virtualSize().width() << "x" << screen->virtualSize().height(); rectList.push_back(screen->availableGeometry()); } PROCESS_DPI_AWARENESS dpiAware = PROCESS_DPI_UNAWARE; GetProcessDpiAwareness( NULL, &dpiAware); qDebug() << "\n\nResults from Windows EnumDisplayDevices: DPIAware=" << dpiAware; bool succeeded = true; int num = 0; DISPLAY_DEVICE display; memset(&display, 0, sizeof(DISPLAY_DEVICE)); display.cb = sizeof(display); do { if (succeeded = EnumDisplayDevices( NULL, num, &display, EDD_GET_DEVICE_INTERFACE_NAME )) { if (num >= rectList.size()) break; qDebug() << "Display " << num << " : "; qDebug() << " DeviceName = " << QString::fromWCharArray( display.DeviceName ); qDebug() << " DeviceString = " << QString::fromWCharArray( display.DeviceString ); qDebug() << " StateFlags = " << display.StateFlags; qDebug() << " DeviceID = " << QString::fromWCharArray( display.DeviceID ); qDebug() << " DeviceKey = " << QString::fromWCharArray( display.DeviceKey ); RECT virtualGeometry; virtualGeometry.left = rectList[num].left() + 100; virtualGeometry.top = rectList[num].top() + 100; virtualGeometry.right = rectList[num].right() - 100; virtualGeometry.bottom = rectList[num].bottom() - 100; HMONITOR hm; EnumDisplayMonitors(NULL, &virtualGeometry, enumMonitorProc, (LONG) &hm); uint dpiX, dpiY; GetDpiForMonitor(hm, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); qDebug() << " EffectiveDPIX = " << dpiX; qDebug() << " EffectiveDPIY = " << dpiY; qDebug() << " ClippingRect = " << rectList[num]; num++; } }