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

Issues with screen attach/detach/sleep/property changes

    XMLWordPrintable

Details

    • macOS: Screen issues
    • macOS
    • a609761b71844d3ebf158465b7a64c6c1197652e (qt/tqtc-qtbase/6.1.3)

    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

      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.

      1. First the callback is called with the kCGDisplayBeginConfigurationFlag, via displayWillConfigNotifyProc
      2. 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

          Activity

            People

              vestbo Tor Arne Vestbø
              vestbo Tor Arne Vestbø
              Veli-Pekka Heinonen Veli-Pekka Heinonen
              Tor Arne Vestbø Tor Arne Vestbø
              Votes:
              2 Vote for this issue
              Watchers:
              15 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: