diff options
author | Gabriel de Dietrich <gabriel.dedietrich@digia.com> | 2014-04-01 18:18:17 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-04-18 11:05:25 +0200 |
commit | c7bd85e97df1b188bcbd4a2a511313d221c5bb83 (patch) | |
tree | 757f1fea25705524b6fbdf280fd68dadb5aa602d /src/plugins/platforms | |
parent | 454dc332b3856c1726683595575c34281650a469 (diff) |
Cocoa: NSMenu views never get viewDidUnhide called
This is the case for QWidgets added as native menu items with
QWidgetAction. According to Cocoa's documentation [1], we should
rely on -[QNSView viewDidMoveToWindow] instead.
On 10.9 however, we receive NSWindowDidChangeOcclusionStateNotification
from the NSMenu window, which is preferable to using -[QNSView
viewDidMoveToWindow] as it guarantees the view is actually visible.
We do runtime symbol lookup to get this to work on 10.9 regardless
of the build SDK version.
[1] https://developer.apple.com/library/mac/documentation/cocoa/Conceptual/MenuList/Articles/ViewsInMenuItems.html
Task-number: QTBUG-19840
Change-Id: If4676df5d79c359965f09ef2e5eddf4c925e3533
Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.mm | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 0b9683a3ef..e2572d607a 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -42,6 +42,7 @@ #include <QtCore/qglobal.h> #include <Carbon/Carbon.h> +#include <dlfcn.h> #include "qnsview.h" #include "qcocoawindow.h" @@ -65,6 +66,9 @@ static QTouchDevice *touchDevice = 0; +// ### HACK Remove once 10.8 is unsupported +static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; + @interface NSEvent (Qt_Compile_Leopard_DeviceDelta) - (CGFloat)deviceDeltaX; - (CGFloat)deviceDeltaY; @@ -73,6 +77,13 @@ static QTouchDevice *touchDevice = 0; @implementation QNSView ++ (void)initialize +{ + NSString **notificationNameVar = (NSString **)dlsym(RTLD_NEXT, "NSWindowDidChangeOcclusionStateNotification"); + if (notificationNameVar) + _q_NSWindowDidChangeOcclusionStateNotification = *notificationNameVar; +} + - (id) init { self = [super initWithFrame : NSMakeRect(0,0, 300,300)]; @@ -192,6 +203,19 @@ static QTouchDevice *touchDevice = 0; } } +- (void)viewDidMoveToWindow +{ + if (self.window) { + // This is the case of QWidgetAction's generated QWidget inserted in an NSMenu. + // 10.9 and newer get the NSWindowDidChangeOcclusionStateNotification + if (!_q_NSWindowDidChangeOcclusionStateNotification + && [self.window.className isEqualToString:@"NSCarbonMenuWindow"]) + m_platformWindow->exposeWindow(); + } else { + m_platformWindow->obscureWindow(); + } +} + - (void)viewWillMoveToWindow:(NSWindow *)newWindow { // ### Merge "normal" window code path with this one for 5.1. @@ -325,6 +349,23 @@ static QTouchDevice *touchDevice = 0; m_platformWindow->obscureWindow(); } else if ([notificationName isEqualToString: @"NSWindowDidOrderOnScreenAndFinishAnimatingNotification"]) { m_platformWindow->exposeWindow(); + } else if (_q_NSWindowDidChangeOcclusionStateNotification + && [notificationName isEqualToString:_q_NSWindowDidChangeOcclusionStateNotification]) { +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 +// ### HACK Remove the enum declaration, the warning disabling and the cast further down once 10.8 is unsupported +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-method-access" + enum { NSWindowOcclusionStateVisible = 1UL << 1 }; +#endif + // Older versions managed in -[QNSView viewDidMoveToWindow]. + // Support QWidgetAction in NSMenu. Mavericks only sends this notification. + // Ideally we should support this in Qt as well, in order to disable animations + // when the window is occluded. + if ((NSUInteger)[self.window occlusionState] & NSWindowOcclusionStateVisible) + m_platformWindow->exposeWindow(); +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 +#pragma clang diagnostic pop +#endif } else if (notificationName == NSWindowDidChangeScreenNotification) { if (m_window) { NSUInteger screenIndex = [[NSScreen screens] indexOfObject:self.window.screen]; |