diff options
Diffstat (limited to 'src/plugins/platforms/cocoa/qnswindow.mm')
-rw-r--r-- | src/plugins/platforms/cocoa/qnswindow.mm | 87 |
1 files changed, 43 insertions, 44 deletions
diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm index cce76e4b20..74ba6f65ac 100644 --- a/src/plugins/platforms/cocoa/qnswindow.mm +++ b/src/plugins/platforms/cocoa/qnswindow.mm @@ -58,6 +58,15 @@ static bool isMouseEvent(NSEvent *ev) } @end + +NSWindow<QNSWindowProtocol> *qnswindow_cast(NSWindow *window) +{ + if ([window conformsToProtocol:@protocol(QNSWindowProtocol)]) + return static_cast<QCocoaNSWindow *>(window); + else + return nil; +} + @implementation QNSWindow #define QNSWINDOW_PROTOCOL_IMPLMENTATION 1 #include "qnswindow.mm" @@ -98,9 +107,10 @@ static bool isMouseEvent(NSEvent *ev) continue; if ([window conformsToProtocol:@protocol(QNSWindowProtocol)]) { - QCocoaWindow *cocoaWindow = static_cast<QCocoaNSWindow *>(window).platformWindow; - window.level = notification.name == NSApplicationWillResignActiveNotification ? - NSNormalWindowLevel : cocoaWindow->windowLevel(cocoaWindow->window()->flags()); + if (QCocoaWindow *cocoaWindow = static_cast<QCocoaNSWindow *>(window).platformWindow) { + window.level = notification.name == NSApplicationWillResignActiveNotification ? + NSNormalWindowLevel : cocoaWindow->windowLevel(cocoaWindow->window()->flags()); + } } // The documentation says that "when a window enters a new level, it’s ordered @@ -167,45 +177,6 @@ static bool isMouseEvent(NSEvent *ev) } @end -#if !defined(QT_APPLE_NO_PRIVATE_APIS) -// When creating an NSWindow the worksWhenModal function is queried, -// and the resulting state is used to set the corresponding window tag, -// which the window server uses to determine whether or not the window -// should be allowed to activate via mouse clicks in the title-bar. -// Unfortunately, prior to macOS 10.15, this window tag was never -// updated after the initial assignment in [NSWindow _commonAwake], -// which meant that windows that dynamically change their worksWhenModal -// state will behave as if they were never allowed to work when modal. -// We work around this by manually updating the window tag when needed. - -typedef uint32_t CGSConnectionID; -typedef uint32_t CGSWindowID; - -extern "C" { -CGSConnectionID CGSMainConnectionID() __attribute__((weak_import)); -OSStatus CGSSetWindowTags(const CGSConnectionID, const CGSWindowID, int *, int) __attribute__((weak_import)); -OSStatus CGSClearWindowTags(const CGSConnectionID, const CGSWindowID, int *, int) __attribute__((weak_import)); -} - -@interface QNSPanel (WorksWhenModalWindowTagWorkaround) @end -@implementation QNSPanel (WorksWhenModalWindowTagWorkaround) -- (void)setWorksWhenModal:(BOOL)worksWhenModal -{ - [super setWorksWhenModal:worksWhenModal]; - - if (QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSCatalina) { - if (CGSMainConnectionID && CGSSetWindowTags && CGSClearWindowTags) { - static int kWorksWhenModalWindowTag = 0x40; - auto *function = worksWhenModal ? CGSSetWindowTags : CGSClearWindowTags; - function(CGSMainConnectionID(), self.windowNumber, &kWorksWhenModalWindowTag, 64); - } else { - qWarning() << "Missing APIs for window tag handling, can not update worksWhenModal state"; - } - } -} -@end -#endif // QT_APPLE_NO_PRIVATE_APIS - #else // QNSWINDOW_PROTOCOL_IMPLMENTATION // The following content is mixed in to the QNSWindow and QNSPanel classes via includes @@ -235,6 +206,29 @@ OSStatus CGSClearWindowTags(const CGSConnectionID, const CGSWindowID, int *, int return m_platformWindow; } +- (void)setContentView:(NSView*)view +{ + [super setContentView:view]; + + if (!qnsview_cast(self.contentView)) + return; + + // Now that we're the content view, we can apply the properties of + // the QWindow. We do this here, instead of in init, so that we can + // use the same code paths for setting these properties during + // NSWindow initialization as we do when setting them later on. + const QWindow *window = m_platformWindow->window(); + qCDebug(lcQpaWindow) << "Reflecting" << window << "state to" << self; + + m_platformWindow->propagateSizeHints(); + m_platformWindow->setWindowFlags(window->flags()); + m_platformWindow->setWindowTitle(window->title()); + m_platformWindow->setWindowFilePath(window->filePath()); // Also sets window icon + m_platformWindow->setWindowState(window->windowState()); + m_platformWindow->setOpacity(window->opacity()); + m_platformWindow->setVisible(window->isVisible()); +} + - (NSString *)description { NSMutableString *description = [NSMutableString stringWithString:[super description]]; @@ -296,8 +290,13 @@ OSStatus CGSClearWindowTags(const CGSConnectionID, const CGSWindowID, int *, int // we assume that if you have translucent content, without a // frame then you intend to do all background drawing yourself. const QWindow *window = m_platformWindow ? m_platformWindow->window() : nullptr; - if (!self.opaque && window && window->flags().testFlag(Qt::FramelessWindowHint)) - return [NSColor clearColor]; + if (!self.opaque && window) { + // Qt::Popup also requires clearColor - in qmacstyle + // we fill background using a special path with rounded corners. + if (window->flags().testFlag(Qt::FramelessWindowHint) + || (window->flags() & Qt::WindowType_Mask) == Qt::Popup) + return [NSColor clearColor]; + } // This still allows you to have translucent content with a frame, // where the system background (or color set via NSWindow) will |