4

From a Qt application I want to report the actual screen resolution, not the virtual one available from QScreen. I tried:

[[NSScreen mainScreen] backingScaleFactor]

but it returns the same value as QScreen (2 for a high dpi screen). However, in macOS, if the user has chosen a scaled resolution then this does not work.

For example, on a macbookpro with the 2880x1800 resolution and the display resolution set to default then

CGDisplayPixelsWide(CGMainDisplayID()) //returns 1440
[[NSScreen mainScreen] backingScaleFactor] //returns 2

2 * 1440 = 2880 and it works

However, when the display resolution is set to more space in system preferences:

CGDisplayPixelsWide(CGMainDisplayID()) //returns 1920 
[[NSScreen mainScreen] backingScaleFactor] // still returns 2

How can I get the actual resolution?

Okay, here is my solution, which returns the monitor native resolution to my app as it is moved from one monitor to another.

// triggered by app move event
QPoint loc = centralWidget->window()->geometry().center();

// get displayID for monitor at point 
CGPoint point = loc.toCGPoint();
const int maxDisplays = 8; 
CGDisplayCount displayCount; 
CGDirectDisplayID displayIDs[maxDisplays];  
CGGetDisplaysWithPoint (point, maxDisplays, displayIDs, &displayCount);
auto displayID;
if (displayCount == 1) displayID = displayIDs[0];
else displayID = CGMainDisplayID();

// get list of all display modes for the monitor
auto modes = CGDisplayCopyAllDisplayModes(displayID, nullptr);
auto count = CFArrayGetCount(modes);
CGDisplayModeRef mode;
int displayHorizontalPixels, displayVerticalPixels = 0;

// the native resolution is the largest display mode
for(auto c = count; c--;) {
    mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, c);
    auto w = CGDisplayModeGetWidth(mode);
    auto h = CGDisplayModeGetHeight(mode);
    if (w > displayHorizontalPixels) displayHorizontalPixels = (int)w;
    if (h > displayVerticalPixels) displayVerticalPixels = (int)h;
}
Rory
  • 113
  • 8
  • In retina mode, the backingScaleFactor is 2.0. But in non-retina scaled mode, the backingScaleFactor is 1.0, and the GPU is running the video output at a different resolution than the native resolution of the panel. – Eljay Dec 17 '17 at 01:09
  • I understand it doesn't work. Do you have a solution? – Rory Dec 18 '17 at 03:44
  • It does work. It is working correctly. Those are the expected results. – Eljay Dec 18 '17 at 12:59
  • Thanks. I understand the backingScaleFactor is reporting as expected. This does not help me determine the actual screen resolution. Can you suggest another approach? – Rory Dec 18 '17 at 15:34
  • Your computer can have multiple screens connected to it. Here's a SO question/answer that can get the current screen resolution for each monitor: https://stackoverflow.com/questions/4982656/programmatically-get-screen-size-in-mac-os-x – Eljay Dec 18 '17 at 22:00
  • Yes, that is basically doing the same thing as I tried before. It returns the virtual screen size, not the real resolution. In my case, I still get a width of 1920 pixels, not the actual 2880. – Rory Dec 19 '17 at 02:22
  • Not sure. This looks promising: https://stackoverflow.com/questions/31780390/how-can-i-get-all-supported-screen-resolutions-on-mac-osx-swift – Eljay Dec 19 '17 at 03:55
  • Thanks. Looks like the first thing I tried: CGDisplayPixelsWide(CGMainDisplayID()) //returns 1920 I'll try all the options presented but I'm new to objective C and swift - coming from Qt C++. – Rory Dec 19 '17 at 06:15
  • @Eljay Unfortunately this is just an outdated version of what I initially presented, returning the virtual screen sizes. – Rory Dec 19 '17 at 13:11
  • • When you ask the OS for the resolution of the screen, it tells you the real resolution. But you said it is returning the virtual screen size, not the real resolution. I'm not sure what you are looking for. The current geometry in conjunction with the scaling factor is the real resolution. – Eljay Dec 19 '17 at 14:04
  • What you are saying is correct if the user has not set the scaling in the macOS display preferences as I noted in my original post. – Rory Dec 19 '17 at 18:41
  • I have appended a solution to my original question. – Rory Mar 25 '18 at 23:32

0 Answers0