Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-49523

Windows: QScreen is misreporting screen dimensions (Laptop with external primary screen)

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Reported
    • Priority: P2: Important
    • Resolution: Unresolved
    • Affects Version/s: 5.5.0 RC, 5.15.2
    • Fix Version/s: None
    • Labels:
      None
    • Environment:
      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++;
              }
          }
      

        Attachments

        1. Display_1_Resolution.png
          Display_1_Resolution.png
          85 kB
        2. Display_2_Resolution.png
          Display_2_Resolution.png
          93 kB
        3. Scaling.png
          Scaling.png
          86 kB
        4. Scenario_1_qtdiag_output.txt
          6 kB
        5. Scenario_2_qtdiag_output.txt
          6 kB
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

            Assignee:
            Unassigned Unassigned
            Reporter:
            jvillanueva@atlassian.com Jerome Villanueva
            PM Owner:
            Veli-Pekka Heinonen Veli-Pekka Heinonen
            Votes:
            3 Vote for this issue
            Watchers:
            13 Start watching this issue

              Dates

              Created:
              Updated:

                Gerrit Reviews

                There are no open Gerrit changes