Details
Description
Events
NSScreen reconfiguration
- Is done in response to _NSCGSDisplayCGSNotificationHandler, which calls _NSApplicationReactToDisplayChanged.
- This in turn calls [_NSScreenConfiguration invalidateConfigurationForReason:0x1], which refreshes NScreen.screens based on the new display info.
- It then calls [NSApplication _reactToScreenInvalidation], which schedules a block to run on the next runloop pass.
- This block calls [NSApplication _reactToScreenInvalidationImmediately:] when run, which among other things:
- Updated depth for window, triggering NSWindowDidChangeBackingPropertiesNotification
- Send screen change event to window, triggering NSWindowDidChangeScreenNotification
- Moves windows if needed, triggering NSWindowDidMoveNotification
- After all this, the block sends a NSApplicationDidChangeScreenParametersNotification
- This block calls [NSApplication _reactToScreenInvalidationImmediately:] when run, which among other things:
The problem with this flow from Qt's point of view is that the screen parameter notification comes in after the notifications for the window. We'd like to know about the screen update before all this happens, so we can process those events with an updated view of the screens.
CGDisplayReconfigurationCallBack
This is part of Quartz Display Services. It has two callbacks when a display change happens.
- First the callback is called with the kCGDisplayBeginConfigurationFlag, via displayWillConfigNotifyProc
- Then the callback is called with the changed flags after the change has happened, eg. kCGDisplayAddFlag, via displayConfigFinalizedProc
Both of these are delivered as events from the window server. The problem with this API is that the second callback is not guaranteed to happen after _NSCGSDisplayCGSNotificationHandler, at least not in practice, so we can't rely on the NSScreen array to be up to date at that point.
Debugging
Running this in a standalone terminal will show relevant debug output (assuming rasterwindow example used for testing):
sudo log stream --color always --level debug --process rasterwindow --style compact --type log --predicate 'subsystem == "com.apple.AppKit" || senderImagePath CONTAINS "QtCore"' | c++filt -n
Pass -NSScreenLoggingEnabled YES as arguments to the application to trigger screen configuration logging from AppKit.
Test cases
Switching GPUs
Changing resolution
Mirroring on/off
Display sleep
Changing main/primary display
Connecting/disconnecting external display
Attachments
Issue Links
- is duplicated by
-
QTCREATORBUG-21614 Occasional crashes when changing screen configuration
- Closed
- is required for
-
QTCREATORBUG-26019 Occasional crashes when disconnecting external display (macOS)
- Closed
- relates to
-
QTBUG-57788 Two Help menus shown on Mac
- Closed
-
QTCREATORBUG-25471 With multiscreen setup, the popup windows & tooltips are shown on the incorrect screen
- Closed
For Gerrit Dashboard: QTBUG-80193 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
282701,2 | macOS: Don't tweak NSApp presentationOptions on startup | 5.14 | qt/qtbase | Status: MERGED | +2 | 0 |
283064,8 | macOS: Harden screen handling logic when reconfiguring displays | 5.14.0 | qt/qtbase | Status: MERGED | +2 | 0 |
283277,7 | Back-port of 6ec5a97ebbf65a9283a57b8e5f4192e7ec84a759 | 5.13.2 | qt/qtbase | Status: ABANDONED | 0 | 0 |
283280,1 | macOS: Back-port screen hardening patches from 5.14 | 5.13 | qt/qtbase | Status: ABANDONED | +2 | 0 |
356768,7 | macOS: Stop relying on balanced CGDisplay reconfiguration callbacks | dev | qt/qtbase | Status: MERGED | +2 | 0 |
362817,2 | macOS: Stop relying on balanced CGDisplay reconfiguration callbacks | 6.1 | qt/qtbase | Status: MERGED | +2 | 0 |
362818,2 | macOS: Stop relying on balanced CGDisplay reconfiguration callbacks | 6.2 | qt/qtbase | Status: MERGED | +2 | 0 |
362822,2 | macOS: Stop relying on balanced CGDisplay reconfiguration callbacks | tqtc/lts-5.15 | qt/tqtc-qtbase | Status: MERGED | +2 | 0 |