5#include <AppKit/AppKit.h>
6#include <ScreenCaptureKit/ScreenCaptureKit.h>
14#include <QtCore/qcoreapplication.h>
15#include <QtGui/private/qcoregraphics_p.h>
17#include <IOKit/graphics/IOGraphicsLib.h>
19#include <QtGui/private/qwindow_p.h>
20#include <QtGui/private/qhighdpiscaling_p.h>
22#include <QtCore/private/qcore_mac_p.h>
23#include <QtCore/private/qeventdispatcher_cf_p.h>
42 Q_ENUM_NS(DisplayChange)
45QMacNotificationObserver
QCocoaScreen::s_screenParameterObserver;
46CGDisplayReconfigurationCallBack
QCocoaScreen::s_displayReconfigurationCallBack =
nullptr;
52 s_displayReconfigurationCallBack = [](CGDirectDisplayID displayId, CGDisplayChangeSummaryFlags flags,
void *userInfo) {
55 const bool beforeReconfigure = flags & kCGDisplayBeginConfigurationFlag;
56 qCDebug(lcQpaScreen).verbosity(0) <<
"Display" << displayId
57 << (beforeReconfigure ?
"beginning" :
"finished") <<
"reconfigure"
60 if (!beforeReconfigure)
63 CGDisplayRegisterReconfigurationCallback(s_displayReconfigurationCallBack,
nullptr);
65 s_screenParameterObserver = QMacNotificationObserver(NSApplication.sharedApplication,
66 NSApplicationDidChangeScreenParametersNotification, [&]() {
67 qCDebug(lcQpaScreen) <<
"Received screen parameter change notification";
77
78
79
80
88 static bool updatingScreens =
false;
89 if (updatingScreens) {
90 qCInfo(lcQpaScreen) <<
"Skipping screen update, already updating";
93 QScopedValueRollback recursionGuard(updatingScreens,
true);
95 uint32_t displayCount = 0;
96 if (CGGetOnlineDisplayList(0,
nullptr, &displayCount) != kCGErrorSuccess)
97 qFatal(
"Failed to get number of online displays");
99 QVector<CGDirectDisplayID> onlineDisplays(displayCount);
100 if (CGGetOnlineDisplayList(displayCount, onlineDisplays.data(), &displayCount) != kCGErrorSuccess)
101 qFatal(
"Failed to get online displays");
103 qCInfo(lcQpaScreen) <<
"Updating screens with" << displayCount
104 <<
"online displays:" << onlineDisplays;
107 int mainDisplayIndex = onlineDisplays.indexOf(CGMainDisplayID());
108 if (mainDisplayIndex < 0) {
109 qCWarning(lcQpaScreen) <<
"Main display not in list of online displays!";
110 }
else if (mainDisplayIndex > 0) {
111 qCWarning(lcQpaScreen) <<
"Main display not first display, making sure it is";
112 onlineDisplays.move(mainDisplayIndex, 0);
115 for (CGDirectDisplayID displayId : onlineDisplays) {
116 Q_ASSERT(CGDisplayIsOnline(displayId));
118 if (CGDisplayMirrorsDisplay(displayId))
127 QCFType<CFUUIDRef> uuid = CGDisplayCreateUUIDFromDisplayID(displayId);
130 if (QCocoaScreen *existingScreen = QCocoaScreen::get(uuid)) {
131 existingScreen->update(displayId);
132 qCInfo(lcQpaScreen) <<
"Updated" << existingScreen;
133 if (CGDisplayIsMain(displayId) && existingScreen != qGuiApp->primaryScreen()->handle()) {
134 qCInfo(lcQpaScreen) <<
"Primary screen changed to" << existingScreen;
135 QWindowSystemInterface::handlePrimaryScreenChanged(existingScreen);
138 QCocoaScreen::add(displayId);
142 for (QScreen *screen : QGuiApplication::screens()) {
143 QCocoaScreen *platformScreen =
static_cast<QCocoaScreen*>(screen->handle());
144 if (!platformScreen->isOnline() || platformScreen->isMirroring())
145 platformScreen->remove();
151 const bool isPrimary = CGDisplayIsMain(displayId);
153 qCInfo(lcQpaScreen) <<
"Adding" << cocoaScreen
154 << (isPrimary ?
"as new primary screen" :
"");
155 QWindowSystemInterface::handleScreenAdded(cocoaScreen, isPrimary);
159 : QPlatformScreen(), m_displayId(displayId)
162 m_cursor =
new QCocoaCursor;
168 for (QScreen *screen : backwards(QGuiApplication::screens()))
169 static_cast<QCocoaScreen*>(screen->handle())->remove();
171 Q_ASSERT(s_displayReconfigurationCallBack);
172 CGDisplayRemoveReconfigurationCallback(s_displayReconfigurationCallBack,
nullptr);
173 s_displayReconfigurationCallBack =
nullptr;
175 s_screenParameterObserver.remove();
191 qCInfo(lcQpaScreen) <<
"Removing " <<
this;
192 QWindowSystemInterface::handleScreenRemoved(
this);
197 Q_ASSERT_X(!screen(),
"QCocoaScreen",
"QScreen should be deleted first");
201 CVDisplayLinkRelease(m_displayLink);
202 if (m_displayLinkSource)
203 dispatch_release(m_displayLinkSource);
208 if (displayId != m_displayId) {
209 qCDebug(lcQpaScreen) <<
"Reconnecting" <<
this <<
"as display" << displayId;
210 m_displayId = displayId;
216 NSScreen *nsScreen = nativeScreen();
218 qCDebug(lcQpaScreen) <<
"Corresponding NSScreen not yet available. Deferring update";
222 const QRect previousGeometry = m_geometry;
223 const QRect previousAvailableGeometry = m_availableGeometry;
224 const qreal previousRefreshRate = m_refreshRate;
225 const double previousRotation = m_rotation;
228 QRectF primaryScreenGeometry = QRectF::fromCGRect(CGDisplayBounds(CGMainDisplayID()));
229 m_geometry = qt_mac_flip(QRectF::fromCGRect(nsScreen.frame), primaryScreenGeometry).toRect();
230 m_availableGeometry = qt_mac_flip(QRectF::fromCGRect(nsScreen.visibleFrame), primaryScreenGeometry).toRect();
232 if (QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSTahoe) {
237 if (NSApp.presentationOptions & NSApplicationPresentationFullScreen
238 && m_availableGeometry.height() == m_geometry.height()) {
239 if (
auto menuBarHeight = NSApp.mainMenu.menuBarHeight; menuBarHeight > 0)
240 m_availableGeometry.setTop(m_availableGeometry.top() + qRound(menuBarHeight));
244 m_devicePixelRatio = nsScreen.backingScaleFactor;
246 m_format = QImage::Format_RGB32;
247 m_depth = NSBitsPerPixelFromDepth(nsScreen.depth);
248 m_colorSpace = QColorSpace::fromIccProfile(QByteArray::fromNSData(nsScreen.colorSpace.ICCProfileData));
249 if (!m_colorSpace.isValid()) {
250 qCWarning(lcQpaScreen) <<
"Failed to parse ICC profile for" << nsScreen.colorSpace
251 <<
"with ICC data" << nsScreen.colorSpace.ICCProfileData
252 <<
"- Falling back to sRGB";
253 m_colorSpace = QColorSpace::SRgb;
256 CGSize size = CGDisplayScreenSize(m_displayId);
257 m_physicalSize = QSizeF(size.width, size.height);
259 QCFType<CGDisplayModeRef> displayMode = CGDisplayCopyDisplayMode(m_displayId);
260 float refresh = CGDisplayModeGetRefreshRate(displayMode);
261 m_refreshRate = refresh > 0 ? refresh : 60.0;
262 m_rotation = CGDisplayRotation(displayId);
263 m_name = QString::fromNSString(nsScreen.localizedName);
265 const bool didChangeGeometry = m_geometry != previousGeometry || m_availableGeometry != previousAvailableGeometry;
267 if (m_rotation != previousRotation)
268 QWindowSystemInterface::handleScreenOrientationChange(screen(), orientation());
270 if (didChangeGeometry)
271 QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry());
272 if (m_refreshRate != previousRefreshRate)
273 QWindowSystemInterface::handleScreenRefreshRateChange(screen(), m_refreshRate);
282 Q_ASSERT(m_displayId);
285 qCDebug(lcQpaScreenUpdates) <<
this <<
"is not online. Ignoring update request";
292 ++m_pendingUpdateRequests;
294 if (!m_displayLink) {
295 qCDebug(lcQpaScreenUpdates) <<
"Creating display link for" <<
this;
296 if (CVDisplayLinkCreateWithCGDisplay(m_displayId, &m_displayLink) != kCVReturnSuccess) {
297 qCWarning(lcQpaScreenUpdates) <<
"Failed to create display link for" <<
this;
300 if (
auto displayId = CVDisplayLinkGetCurrentCGDisplay(m_displayLink); displayId != m_displayId) {
301 qCWarning(lcQpaScreenUpdates) <<
"Unexpected display" << displayId <<
"for display link";
302 CVDisplayLinkRelease(m_displayLink);
303 m_displayLink =
nullptr;
306 CVDisplayLinkSetOutputCallback(m_displayLink, [](CVDisplayLinkRef,
const CVTimeStamp*,
307 const CVTimeStamp*, CVOptionFlags, CVOptionFlags*,
void* displayLinkContext) ->
int {
310 return kCVReturnSuccess;
332 static CFMachPortRef eventTap = []() {
333 CFMachPortRef eventTap = CGEventTapCreateForPid(getpid(), kCGTailAppendEventTap,
334 kCGEventTapOptionListenOnly, NSEventMaskLeftMouseDragged,
335 [](CGEventTapProxy, CGEventType type, CGEventRef event,
void *) -> CGEventRef {
336 if (type == kCGEventTapDisabledByTimeout)
337 qCWarning(lcQpaScreenUpdates) <<
"Event tap disabled due to timeout!";
340 CGEventTapEnable(eventTap,
false);
341 static CFRunLoopSourceRef runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
342 CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
344 NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
345 [center addObserverForName:NSWindowWillStartLiveResizeNotification object:nil queue:nil
346 usingBlock:^(NSNotification *notification) {
347 qCDebug(lcQpaScreenUpdates) <<
"Live resize of" << notification.object
348 <<
"started. Enabling event tap";
349 CGEventTapEnable(eventTap,
true);
351 [center addObserverForName:NSWindowDidEndLiveResizeNotification object:nil queue:nil
352 usingBlock:^(NSNotification *notification) {
353 qCDebug(lcQpaScreenUpdates) <<
"Live resize of" << notification.object
354 <<
"ended. Disabling event tap";
355 CGEventTapEnable(eventTap,
false);
362 if (!CVDisplayLinkIsRunning(m_displayLink)) {
363 qCDebug(lcQpaScreenUpdates) <<
"Starting display link for" <<
this;
364 CVDisplayLinkStart(m_displayLink);
374 if (cat.isDebugEnabled())
375 debug =
new QDebug(QMessageLogger().debug(cat).nospace());
389#define qDeferredDebug(helper) if (Q_UNLIKELY(helper.debug)) *helper.debug
394 qCDebug(lcQpaScreenUpdates) <<
this <<
"is not online. Ignoring update request delivery";
398 QMacAutoReleasePool pool;
405 if (!NSThread.isMainThread) {
409 const int pendingUpdates = ++m_pendingDisplayLinkUpdates;
411 const int pendingUpdateRequests = m_pendingUpdateRequests;
414 qDeferredDebug(screenUpdates) <<
"display link callback for screen " << m_displayId
415 <<
" with " << pendingUpdateRequests <<
" pending update requests";
417 if (
const int framesAheadOfDelivery = pendingUpdates - 1) {
422 qDeferredDebug(screenUpdates) <<
", " << framesAheadOfDelivery <<
" frame(s) ahead";
425 if (!pendingUpdateRequests) {
430 qDeferredDebug(screenUpdates) <<
"; skipping signaling dispatch source";
431 m_pendingDisplayLinkUpdates = 0;
437 if (!m_displayLinkSource) {
438 m_displayLinkSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());
439 dispatch_source_set_event_handler(m_displayLinkSource, ^{
442 dispatch_resume(m_displayLinkSource);
445 dispatch_source_merge_data(m_displayLinkSource, 1);
451 const int pendingUpdates = m_pendingDisplayLinkUpdates;
452 if (pendingUpdates > 1)
453 qDeferredDebug(screenUpdates) <<
", " << (pendingUpdates - 1) <<
" frame(s) behind display link";
457 int pendingUpdateRequests = 0;
459 auto windows = QGuiApplication::allWindows();
460 for (
int i = 0; i < windows.size(); ++i) {
461 QWindow *window = windows.at(i);
462 if (window->screen() != screen())
465 QPointer<QCocoaWindow> platformWindow =
static_cast<
QCocoaWindow*>(window->handle());
469 if (!platformWindow->hasPendingUpdateRequest())
473 if (!platformWindow->updatesWithDisplayLink())
476 platformWindow->deliverUpdateRequest();
485 if (platformWindow->hasPendingUpdateRequest())
486 ++pendingUpdateRequests;
489 m_pendingUpdateRequests = pendingUpdateRequests;
491 if (
const int missedUpdates = m_pendingDisplayLinkUpdates.fetchAndStoreRelaxed(0) - pendingUpdates) {
492 qCWarning(lcQpaScreenUpdates) <<
"main thread missed" << missedUpdates
493 <<
"update(s) from display link during update request delivery";
500 if (!CVDisplayLinkIsRunning(m_displayLink))
503 const auto windows = QGuiApplication::allWindows();
504 for (
auto *window : windows) {
505 if (window->screen() != screen())
508 QPointer<QCocoaWindow> platformWindow =
static_cast<QCocoaWindow*>(window->handle());
512 if (window->isExposed())
515 if (platformWindow->hasPendingUpdateRequest())
519 qCDebug(lcQpaScreenUpdates) <<
"Stopping display link for" <<
this;
520 CVDisplayLinkStop(m_displayLink);
528 if (@available(macOS 14, *)) {
529 for (
auto *window : QGuiApplication::allWindows()) {
530 auto *platformWindow =
static_cast<QCocoaWindow*>(window->handle());
534 NSView *view = platformWindow->view();
536 if (!view.layer.wantsExtendedDynamicRangeContent)
539 [view setNeedsDisplay:YES];
548 QPlatformScreen::SubpixelAntialiasingType type = QPlatformScreen::subpixelAntialiasingTypeHint();
549 if (type == QPlatformScreen::Subpixel_None) {
551 type = QPlatformScreen::Subpixel_RGB;
559 return Qt::LandscapeOrientation;
560 if (m_rotation == 90)
561 return Qt::PortraitOrientation;
562 if (m_rotation == 180)
563 return Qt::InvertedLandscapeOrientation;
564 if (m_rotation == 270)
565 return Qt::InvertedPortraitOrientation;
566 return QPlatformScreen::orientation();
571 __block QWindow *window =
nullptr;
572 [NSApp enumerateWindowsWithOptions:NSWindowListOrderedFrontToBack
573 usingBlock:^(NSWindow *nsWindow, BOOL *stop) {
578 if (![nsWindow conformsToProtocol:@protocol(QNSWindowProtocol)])
581 QCocoaWindow *cocoaWindow = qnsview_cast(nsWindow.contentView).platformWindow;
585 QWindow *w = cocoaWindow->window();
589 auto nativeGeometry = QHighDpi::toNativePixels(w->geometry(), w);
590 if (!nativeGeometry.contains(point))
593 QRegion mask = QHighDpi::toNativeLocalPosition(w->mask(), w);
594 if (!mask.isEmpty() && !mask.contains(point - nativeGeometry.topLeft()))
600 if (!window->isTopLevel())
611
612
613
614
615
619 if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(
620 QPlatformIntegration::ScreenWindowGrabbing)) {
621 qCWarning(lcQpaScreen) <<
"Ignoring grabWindow to not bring down WindowServer";
625 auto grabFromDisplay = [](CGDirectDisplayID displayId,
const QRect &grabRect) -> QPixmap {
626 QMacAutoReleasePool pool;
628 const qreal scale = QCocoaScreen::nativeScreenForDisplayId(displayId).backingScaleFactor;
630 dispatch_semaphore_t sem = dispatch_semaphore_create(0);
631 auto cleanup = qScopeGuard([sem]() { dispatch_release(sem); });
633 auto captureShareableContent = [sem](
void (^capture)(SCShareableContent *)) {
637 [SCShareableContent getShareableContentWithCompletionHandler:
638 ^(SCShareableContent *content, NSError *error) {
640 qCDebug(lcQpaScreen) <<
"Failed to capture all windows" << error;
648 [SCShareableContent getCurrentProcessShareableContentWithCompletionHandler:
649 ^(SCShareableContent *content, NSError *error) {
651 qCWarning(lcQpaScreen) <<
"Failed to capture own windows" << error;
655 dispatch_semaphore_signal(sem);
662 __block QImage image;
663 captureShareableContent(^(SCShareableContent *content) {
666 QMacAutoReleasePool pool;
668 SCDisplay *scDisplay = nil;
669 for (SCDisplay *d in content.displays) {
670 if (d.displayID == displayId) {
676 qCWarning(lcQpaScreen) <<
"No SCDisplay for display" << displayId;
677 dispatch_semaphore_signal(sem);
681 SCContentFilter *filter = [[[SCContentFilter alloc]
682 initWithDisplay:scDisplay
683 includingApplications:content.applications
684 exceptingWindows:@[]] autorelease];
685 filter.includeMenuBar = YES;
687 SCStreamConfiguration *config = [[SCStreamConfiguration
new] autorelease];
688 config.sourceRect = grabRect.toCGRect();
689 config.width = qRound(grabRect.width() * scale);
690 config.height = qRound(grabRect.height() * scale);
691 config.showsCursor = NO;
692 config.capturesAudio = NO;
693 config.ignoreShadowsDisplay = NO;
694 config.ignoreShadowsSingleWindow = NO;
696 [SCScreenshotManager captureImageWithFilter:filter configuration:config
697 completionHandler:^(CGImageRef cgImage, NSError *error) {
699 qCWarning(lcQpaScreen) <<
"Failed screen capture" << error;
701 image = qt_mac_toQImage(cgImage);
702 dispatch_semaphore_signal(sem);
708 if (dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC)) != 0) {
709 qCWarning(lcQpaScreen) <<
"Screen capture timed out for display" << displayId;
713 QPixmap pixmap = QPixmap::fromImage(image);
714 pixmap.setDevicePixelRatio(scale);
718 QRect grabRect = QRect(x, y, width, height);
719 qCDebug(lcQpaScreen) <<
"input grab rect" << grabRect;
723 NSView *nsView =
reinterpret_cast<NSView*>(view);
724 NSPoint windowPoint = [nsView convertPoint:NSMakePoint(0, 0) toView:nil];
725 NSRect screenRect = [nsView.window convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)];
726 QPoint position = mapFromNative(screenRect.origin).toPoint();
727 QSize size = QRectF::fromCGRect(NSRectToCGRect(nsView.bounds)).toRect().size();
728 QRect windowRect = QRect(position, size);
729 if (!grabRect.isValid())
730 grabRect = windowRect;
732 grabRect.translate(windowRect.topLeft());
735 if (!grabRect.isValid())
736 grabRect = geometry();
740 const int maxDisplays = 128;
741 CGDirectDisplayID displays[maxDisplays];
742 CGDisplayCount displayCount;
743 CGRect cgRect = grabRect.isValid() ? grabRect.toCGRect() : CGRectInfinite;
744 const CGDisplayErr err = CGGetDisplaysWithRect(cgRect, maxDisplays, displays, &displayCount);
745 if (err || displayCount == 0)
748 qCDebug(lcQpaScreen) <<
"final grab rect" << grabRect <<
"from" << displayCount <<
"displays";
753 QVector<QPixmap> pixmaps;
754 QVector<QRect> globalGrabBounds;
756 for (uint i = 0; i < displayCount; ++i) {
757 auto display = displays[i];
758 const QRect displayBounds = QRectF::fromCGRect(CGDisplayBounds(display)).toRect();
759 const QRect grabBounds = displayBounds.intersected(grabRect);
760 if (grabBounds.isNull()) {
761 globalGrabBounds.append(QRect());
762 pixmaps.append(QPixmap());
765 const QRect displayLocalGrabBounds = QRect(QPoint(grabBounds.topLeft() - displayBounds.topLeft()), grabBounds.size());
767 qCDebug(lcQpaScreen) <<
"grab display" << i <<
"global" << grabBounds <<
"local" << displayLocalGrabBounds;
768 QPixmap displayPixmap = grabFromDisplay(display, displayLocalGrabBounds);
770 if (displayCount == 1)
771 return displayPixmap;
773 qCDebug(lcQpaScreen) <<
"grab sub-image size" << displayPixmap.size() <<
"devicePixelRatio" << displayPixmap.devicePixelRatio();
774 pixmaps.append(displayPixmap);
775 globalGrabBounds.append(grabBounds);
776 outputRect = outputRect.united(grabBounds);
781 for (uint i = 0; i < displayCount; ++i)
782 dpr = qMax(dpr, pixmaps.at(i).devicePixelRatio());
785 qCDebug(lcQpaScreen) <<
"Create grap pixmap" << outputRect.size() <<
"at devicePixelRatio" << dpr;
786 QPixmap windowPixmap(outputRect.size() * dpr);
787 windowPixmap.setDevicePixelRatio(dpr);
788 windowPixmap.fill(Qt::transparent);
789 QPainter painter(&windowPixmap);
790 for (uint i = 0; i < displayCount; ++i) {
791 const QRect grabBounds = globalGrabBounds.at(i);
792 if (grabBounds.isNull())
794 const QRect dest(grabBounds.topLeft() - outputRect.topLeft(), grabBounds.size());
795 painter.drawPixmap(dest, pixmaps.at(i));
808 int isOnline = CGDisplayIsOnline(m_displayId);
809 static const int kCGDisplayIsDisconnected = 0xffffffff;
810 return isOnline != kCGDisplayIsDisconnected && isOnline;
814
815
821 return CGDisplayMirrorsDisplay(m_displayId);
825
826
832 return static_cast<QCocoaScreen *>(QGuiApplication::primaryScreen()->handle());
837 QList<QPlatformScreen*> siblings;
840 for (QScreen *screen : QGuiApplication::screens())
841 siblings << screen->handle();
848 auto displayId = nsScreen.qt_displayId;
849 auto *cocoaScreen = get(displayId);
851 qCWarning(lcQpaScreen) <<
"Failed to map" << nsScreen
852 <<
"to QCocoaScreen. Doing last minute update.";
854 cocoaScreen = get(displayId);
856 qCWarning(lcQpaScreen) <<
"Last minute update failed!";
863 for (QScreen *screen : QGuiApplication::screens()) {
864 QCocoaScreen *cocoaScreen =
static_cast<QCocoaScreen*>(screen->handle());
865 if (cocoaScreen->m_displayId == displayId)
874 for (QScreen *screen : QGuiApplication::screens()) {
875 auto *platformScreen =
static_cast<QCocoaScreen*>(screen->handle());
876 if (!platformScreen->isOnline())
879 auto displayId = platformScreen->displayId();
880 QCFType<CFUUIDRef> candidateUuid(CGDisplayCreateUUIDFromDisplayID(displayId));
881 Q_ASSERT(candidateUuid);
883 if (candidateUuid == uuid)
884 return platformScreen;
890NSScreen *
QCocoaScreen::nativeScreenForDisplayId(CGDirectDisplayID displayId)
892 for (NSScreen *screen in NSScreen.screens) {
893 if (screen.qt_displayId == displayId)
904 return nativeScreenForDisplayId(m_displayId);
910 return qt_mac_flip(pos, screen->geometry()).toCGPoint();
916 return qt_mac_flip(rect, screen->geometry()).toCGRect();
922 return qt_mac_flip(QPointF::fromCGPoint(pos), screen->geometry());
928 return qt_mac_flip(QRectF::fromCGRect(rect), screen->geometry());
931#ifndef QT_NO_DEBUG_STREAM
934 QDebugStateSaver saver(debug);
936 debug <<
"QCocoaScreen(" << (
const void *)screen;
938 debug <<
", " << screen->name();
940 if (CGDisplayIsAsleep(screen->displayId()))
941 debug <<
", Sleeping";
942 if (
auto mirroring = CGDisplayMirrorsDisplay(screen->displayId()))
943 debug <<
", mirroring=" << mirroring;
945 debug <<
", Offline";
947 debug <<
", " << screen->geometry();
948 debug <<
", dpr=" << screen->devicePixelRatio();
949 debug <<
", displayId=" << screen->displayId();
951 if (
auto nativeScreen = screen->nativeScreen())
952 debug <<
", " << nativeScreen;
961#include "qcocoascreen.moc"
963@implementation NSScreen (QtExtras)
965- (CGDirectDisplayID)qt_displayId
967 return [self.deviceDescription[@
"NSScreenNumber"] unsignedIntValue];
QPixmap grabWindow(WId window, int x, int y, int width, int height) const override
void deliverUpdateRequests()
NSScreen * nativeScreen() const override
QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const override
Returns a hint about this screen's subpixel layout structure.
static QCocoaScreen * primaryScreen()
The screen used as a reference for global window geometry.
Qt::ScreenOrientation orientation() const override
Reimplement this function in subclass to return the current orientation of the screen,...
QList< QPlatformScreen * > virtualSiblings() const override
Returns a list of all the platform screens that are part of the same virtual desktop.
QWindow * topLevelAt(const QPoint &point) const override
Return the given top level window for a given position.
\inmodule QtCore\reentrant
@ ReconfiguredWithFlagsMissing
#define qDeferredDebug(helper)
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
DeferredDebugHelper(const QLoggingCategory &cat)