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

QCocoaScreen::grabWindow doesn't work with Retina display to the right of the main display

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P3: Somewhat important
    • 5.12.1
    • 5.3.2, 5.4.0, 5.11
    • QPA
    • OS X 10.9.5
    • macOS

    Description

      When a Retina display is set to be a secondary display and arranged to the right of the main display, QScreen::grabWindow captures the wrong portion of the screen.

      Build and run the following code:

      #include <QtGui>
      #include <QtWidgets>
      
      QString text = R"foo(
      Any other combination of encoding prefixes may or may not be supported by the implementation. The result of such a concatenation is implementation-defined.
      String literals have static storage duration, and thus exist in memory for the life of the program.
      String literals can be used to initialize character arrays. If an array is initialized like char str[] = "foo";, str will contain a copy of the string "foo".
      The compiler is allowed, but not required, to combine storage for equal or overlapping string literals. That means that identical string literals may or may not compare equal when compared by pointer.
      )foo";
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
      
          QWidget win;
          win.setWindowTitle("Hello");
          win.setLayout(new QVBoxLayout);
      
          auto label = new QLabel(text);
          label->setWordWrap(true);
          win.layout()->addWidget(label);
      
          auto btn = new QPushButton("Hit Me!");
          win.layout()->addWidget(btn);
      
          qDebug() << QApplication::desktop()->windowHandle()->frameGeometry() << QApplication::desktop()->mapToGlobal(QPoint(0,0));
      
          QObject::connect(btn, &QPushButton::clicked, [&win](bool){
              auto window = win.windowHandle();
              auto screen = window->screen();
              auto r = window->frameGeometry();
              auto img = screen->grabWindow(QApplication::desktop()->winId(), r.left(), r.top(), r.width(), r.height());
              static QString f = "untitled.png";
              f = QFileDialog::getSaveFileName(&win, "Save File", f, "Images (*.png *.xpm *.jpg)");
              if(f.size()) {
                  img.save(f);
      
                  img = screen->grabWindow(QApplication::desktop()->winId());
                  img.save(QFileInfo(f).dir().absoluteFilePath("full.png"));
              }
          });
      
          win.show();
      
          return a.exec();
      }
      

      Drag the window to the Retina display that is set to a secondary display to the right of the main.

      Click the "Hit Me!" button and choose where to save the image.

      Open the saved image, note the captured image is not the specified window frame rect.

      Also open the full.png file at the same location, notice the main display portion is overlaid with a scaled and cropped version of itself, while the Retina display part is distorted.

      See the attached images for examples.

      Attachments

        1. full.png
          full.png
          3.38 MB
        2. window.png
          window.png
          545 kB

        Issue Links

          For Gerrit Dashboard: QTBUG-44422
          # Subject Branch Project Status CR V

          Activity

            People

              sorvig Morten Sørvig
              stephenju Stephen Chu
              Votes:
              4 Vote for this issue
              Watchers:
              12 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes