Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Qt enumerate screens?

Today I found that the order how Qt enumerates screens (QGuiApplication::screens) differs from the order in Windows (EnumDisplayMonitors).

What is the logic behind this difference, in order to take it into account when mixing Windows API and Qt? For example, if required to show something in screen #2 (using Windows enumeration).

Here the code I've used to test (also available in GitHub):

#include <qapplication.h>
#include <qdebug.h>
#include <qscreen.h>
#include <Windows.h>
#include <iostream>

std::ostream& operator<<(std::ostream& of, const RECT& rect)
{
  return of << "RECT(" << rect.left << ", " << rect.top << " " << (rect.right - rect.left) << "x" << (rect.bottom - rect.top) << ")";
}

BOOL CALLBACK printMonitorInfoByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
  auto index = (int*)dwData;
  std::cout << ++*index << " " << *lprcMonitor << std::endl;
  return TRUE;
}

int main(int argc, char* argv[])
{
  QApplication a(argc, argv);

  qDebug() << "*** Qt screens ***";
  const auto screens = qApp->screens();
  for (int ii = 0; ii < screens.count(); ++ii) {
    qDebug() << ii + 1 << screens[ii]->geometry();
  }

  qDebug() << "*** Windows monitors ***";
  int index = 0;
  EnumDisplayMonitors(NULL, NULL, printMonitorInfoByHandle, (LPARAM)&index);

  return 0;
}

My displays configuration is, from left to right, 2 (1280x1024), 3 (1920x1080), 1 (1920x1080), being my primary screen the 3.

Results:

*** Qt screens ***
1 QRect(0,0 1920x1080)
2 QRect(1920,233 1920x1080)
3 QRect(-1280,47 1280x1024)
*** Windows monitors ***
1 RECT(1920, 233 1920x1080)
2 RECT(-1280, 47 1280x1024)
3 RECT(0, 0 1920x1080)
like image 352
cbuchart Avatar asked Jan 24 '19 16:01

cbuchart


1 Answers

As far as I've been able to see in different systems, EnumDisplayMonitors returns monitors in the order defined in the Display Settings, while QGuiApplication::screens always shows primary screen at the first position (actually, QGuiApplication::primaryScreen simply do that: return the first element).

Looking at the source code, in Windows Qt also uses the EnumDisplayMonitors function but basically moves the primary screen to the first position (it actually inserts in the first position the primary screen, while inserting at the end of the list any other monitor).

So, the primary screen will be at first position, screens with an index lower than primary screen's will be shifted one position, while the rest will match the index.


As a side note, taken from the comments of the code, if the primary screen is changed during the execution of the application, Qt is not able to report the change.

Note that the side effect of this policy is that there is no way to change primary screen reported by Qt, unless we want to delete all existing screens and add them again whenever primary screen changes.

like image 55
cbuchart Avatar answered Sep 27 '22 18:09

cbuchart