summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorGabriel de Dietrich <gabriel.dedietrich@digia.com>2014-01-13 15:13:46 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-01-31 14:43:54 +0100
commit79fb39a87ce5ffbda22f297977b510e89ebf5485 (patch)
tree180994cd6c90ce5f88295207d845516be04fd3a4 /src/plugins
parent2d576f79f748ca4c9bb54634f0fd44fa207a2248 (diff)
Cocoa: Merge QNSWindow and QNSPanel, inherit NSPanel
Since we will later have frameless NSWindow child QWindows, it makes sense to be able to keep and reuse the instantiated NSWindows in cases like QDockWidgets. If we keep these 2 different classes, it becomes impossible to morph one into the other. Task-number: QTBUG-33082 Change-Id: I351c628b887101b1cfd67689afbf689f119554de Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h47
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm182
2 files changed, 99 insertions, 130 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index c20773601d..18d512ce30 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -52,34 +52,32 @@
QT_FORWARD_DECLARE_CLASS(QCocoaWindow)
-@interface QNSWindow : NSWindow {
- @public QCocoaWindow *m_cocoaPlatformWindow;
-}
-
-- (void)clearPlatformWindow;
-- (BOOL)canBecomeKeyWindow;
-@end
+@class QNSWindowDelegate;
-@interface QNSPanel : NSPanel {
- @public QCocoaWindow *m_cocoaPlatformWindow;
+@interface QNSWindow : NSPanel {
+@public
+ QCocoaWindow *m_cocoaPlatformWindow;
}
+
- (void)clearPlatformWindow;
-- (BOOL)canBecomeKeyWindow;
@end
-@class QNSWindowDelegate;
-
QT_BEGIN_NAMESPACE
+
// QCocoaWindow
//
-// QCocoaWindow is an NSView (not an NSWindow!) in the sense
-// that it relies on a NSView for all event handling and
-// graphics output and does not require a NSWindow, except for
-// for the window-related functions like setWindowTitle.
+// A QCocoaWindow is backed by a NSView and optionally a NSWindow.
//
-// As a consequence of this it is possible to embed the QCocoaWindow
-// in an NSView hierarchy by getting a pointer to the "backing"
-// NSView and not calling QCocoaWindow::show():
+// The NSView is used for most event handling and graphics output.
+//
+// Top-level QWindows are always backed by a NSWindow in addition to
+// the NSView. Child QWindows can also be backed by NSWindows, which
+// enables proper stacking of GL Widgets and threaded GL rendering
+// to multiple contexts.
+//
+// It is possible to embed the QCocoaWindow in an NSView hierarchy
+// by getting a pointer to the backing NSView and not calling
+// QCocoaWindow::show():
//
// QWindow *qtWindow = new MyWindow();
// qtWindow->create();
@@ -135,6 +133,7 @@ public:
void windowDidResize();
bool windowShouldClose();
bool windowIsPopupType(Qt::WindowType type = Qt::Widget) const;
+ bool windowShouldBehaveAsPanel() const;
void setSynchedWindowStateFromWindow();
@@ -170,9 +169,9 @@ protected:
// NSWindow handling. The QCocoaWindow/QNSView can either be displayed
// in an existing NSWindow or in one created by Qt.
void recreateWindow(const QPlatformWindow *parentWindow);
- NSWindow *createNSWindow();
- void setNSWindow(NSWindow *window);
- void clearNSWindow(NSWindow *window);
+ QNSWindow *createNSWindow();
+ void setNSWindow(QNSWindow *window);
+ void clearNSWindow(QNSWindow *window);
QRect windowGeometry() const;
QCocoaWindow *parentCocoaWindow() const;
@@ -185,12 +184,14 @@ public: // for QNSView
NSView *m_contentView;
QNSView *m_qtView;
- NSWindow *m_nsWindow;
+ QNSWindow *m_nsWindow;
// TODO merge to one variable if possible
bool m_contentViewIsEmbedded; // true if the m_contentView is actually embedded in a "foreign" NSView hiearchy
bool m_contentViewIsToBeEmbedded; // true if the m_contentView is intended to be embedded in a "foreign" NSView hiearchy
+ QCocoaWindow *m_parentCocoaWindow;
+
QNSWindowDelegate *m_nsWindowDelegate;
Qt::WindowFlags m_windowFlags;
Qt::WindowState m_synchedWindowState;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index f62a6d29ce..c8d6541d3f 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -80,15 +80,10 @@ static bool isMouseEvent(NSEvent *ev)
}
@interface NSWindow (CocoaWindowCategory)
-- (void) clearPlatformWindow;
- (NSRect) legacyConvertRectFromScreen:(NSRect) rect;
@end
@implementation NSWindow (CocoaWindowCategory)
-- (void) clearPlatformWindow
-{
-}
-
- (NSRect) legacyConvertRectFromScreen:(NSRect) rect
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
@@ -104,11 +99,39 @@ static bool isMouseEvent(NSEvent *ev)
@implementation QNSWindow
+- (id)initWithContentRect:(NSRect)contentRect
+ styleMask:(NSUInteger)windowStyle
+ qPlatformWindow:(QCocoaWindow *)qpw
+{
+ self = [super initWithContentRect:contentRect
+ styleMask:windowStyle
+ backing:NSBackingStoreBuffered
+ defer:NO]; // Deferring window creation breaks OpenGL (the GL context is
+ // set up before the window is shown and needs a proper window)
+
+ if (self) {
+ m_cocoaPlatformWindow = qpw;
+ }
+ return self;
+}
+
- (BOOL)canBecomeKeyWindow
{
- // The default implementation returns NO for title-bar less windows,
- // override and return yes here to make sure popup windows such as
- // the combobox popup can become the key window.
+ if (!m_cocoaPlatformWindow)
+ return NO;
+
+ // Only tool or dialog windows should become key:
+ if (m_cocoaPlatformWindow && m_cocoaPlatformWindow->windowShouldBehaveAsPanel()) {
+ Qt::WindowType type = m_cocoaPlatformWindow->window()->type();
+ if (m_cocoaPlatformWindow->m_overrideBecomeKey
+ || type == Qt::Tool || type == Qt::Dialog)
+ return YES;
+ return NO;
+ }
+
+ // All other windows can become the key window. This includes
+ // popup windows such as the combobox popup, which is a title-bar
+ // less window that by default can't become key.
return YES;
}
@@ -121,50 +144,10 @@ static bool isMouseEvent(NSEvent *ev)
if (!m_cocoaPlatformWindow || m_cocoaPlatformWindow->window()->transientParent())
canBecomeMain = NO;
- return canBecomeMain;
-}
-
-- (void) sendEvent: (NSEvent*) theEvent
-{
- [super sendEvent: theEvent];
-
- if (!m_cocoaPlatformWindow)
- return;
-
- if (m_cocoaPlatformWindow->frameStrutEventsEnabled() && isMouseEvent(theEvent)) {
- NSPoint loc = [theEvent locationInWindow];
- NSRect windowFrame = [self legacyConvertRectFromScreen:[self frame]];
- NSRect contentFrame = [[self contentView] frame];
- if (NSMouseInRect(loc, windowFrame, NO) &&
- !NSMouseInRect(loc, contentFrame, NO))
- {
- QNSView *contentView = (QNSView *) m_cocoaPlatformWindow->contentView();
- [contentView handleFrameStrutMouseEvent: theEvent];
- }
- }
-}
-
-- (void)clearPlatformWindow
-{
- m_cocoaPlatformWindow = 0;
-}
-
-@end
-
-@implementation QNSPanel
-
-- (BOOL)canBecomeKeyWindow
-{
- if (!m_cocoaPlatformWindow)
- return NO;
+ if (m_cocoaPlatformWindow && m_cocoaPlatformWindow->windowShouldBehaveAsPanel())
+ canBecomeMain = NO;
- // Only tool or dialog windows should become key:
- if (m_cocoaPlatformWindow
- && (m_cocoaPlatformWindow->m_overrideBecomeKey ||
- m_cocoaPlatformWindow->window()->type() == Qt::Tool ||
- m_cocoaPlatformWindow->window()->type() == Qt::Dialog))
- return YES;
- return NO;
+ return canBecomeMain;
}
- (void) sendEvent: (NSEvent*) theEvent
@@ -543,15 +526,21 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
- Qt::WindowType type = window()->type();
- if ((type & Qt::Popup) != Qt::Popup && (type & Qt::Dialog) != Qt::Dialog) {
- NSWindowCollectionBehavior behavior = [m_nsWindow collectionBehavior];
+ NSWindowCollectionBehavior behavior = [m_nsWindow collectionBehavior];
+ if (windowShouldBehaveAsPanel()) {
+ behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary;
+ behavior |= NSWindowCollectionBehaviorFullScreenAuxiliary;
+ } else {
if (flags & Qt::WindowFullscreenButtonHint)
behavior |= NSWindowCollectionBehaviorFullScreenPrimary;
else
behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary;
- [m_nsWindow setCollectionBehavior:behavior];
}
+ [m_nsWindow setCollectionBehavior:behavior];
+
+ [m_nsWindow setAnimationBehavior:(flags & Qt::Popup) == Qt::Popup
+ ? NSWindowAnimationBehaviorUtilityWindow
+ : NSWindowAnimationBehaviorDefault];
}
#endif
}
@@ -823,6 +812,14 @@ bool QCocoaWindow::windowIsPopupType(Qt::WindowType type) const
return ((type & Qt::Popup) == Qt::Popup);
}
+bool QCocoaWindow::windowShouldBehaveAsPanel() const
+{
+ // Before merging QNSPanel and QNSWindow, we used NSPanel for popup-type
+ // windows (Popup, Tool, ToolTip, SplashScreen) and dialogs
+ Qt::WindowType type = window()->type();
+ return (type & Qt::Popup) == Qt::Popup || (type & Qt::Dialog) == Qt::Dialog;
+}
+
void QCocoaWindow::setCurrentContext(QCocoaGLContext *context)
{
m_glContext = context;
@@ -879,63 +876,29 @@ void QCocoaWindow::requestActivateWindow()
[ window makeKeyWindow ];
}
-NSWindow * QCocoaWindow::createNSWindow()
+QNSWindow * QCocoaWindow::createNSWindow()
{
QCocoaAutoReleasePool pool;
QRect rect = initialGeometry(window(), window()->geometry(), defaultWindowWidth, defaultWindowHeight);
NSRect frame = qt_mac_flipRect(rect, window());
- Qt::WindowType type = window()->type();
Qt::WindowFlags flags = window()->flags();
- NSUInteger styleMask = windowStyleMask(flags);
- NSWindow *createdWindow = 0;
-
- // Use NSPanel for popup-type windows. (Popup, Tool, ToolTip, SplashScreen)
- // and dialogs
- if ((type & Qt::Popup) == Qt::Popup || (type & Qt::Dialog) == Qt::Dialog) {
- QNSPanel *window;
- window = [[QNSPanel alloc] initWithContentRect:frame
- styleMask: styleMask
- backing:NSBackingStoreBuffered
- defer:NO]; // Deferring window creation breaks OpenGL (the GL context is set up
- // before the window is shown and needs a proper window.).
- if ((type & Qt::Popup) == Qt::Popup)
- [window setHasShadow:YES];
- [window setHidesOnDeactivate: NO];
+ NSUInteger styleMask;
+ styleMask = windowStyleMask(flags);
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
- if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
- // Make popup winows show on the same desktop as the parent full-screen window.
- [window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
+ QNSWindow *createdWindow = [[QNSWindow alloc] initWithContentRect:frame styleMask:styleMask qPlatformWindow:this];
- if ((type & Qt::Popup) == Qt::Popup)
- [window setAnimationBehavior:NSWindowAnimationBehaviorUtilityWindow];
- }
-#endif
- window->m_cocoaPlatformWindow = this;
- createdWindow = window;
- } else {
- QNSWindow *window;
- window = [[QNSWindow alloc] initWithContentRect:frame
- styleMask: styleMask
- backing:NSBackingStoreBuffered
- defer:NO]; // Deferring window creation breaks OpenGL (the GL context is set up
- // before the window is shown and needs a proper window.).
- window->m_cocoaPlatformWindow = this;
-
- createdWindow = window;
- }
+ Qt::WindowFlags type = window()->type();
+ createdWindow.hidesOnDeactivate = type == Qt::Tool || type == Qt::ToolTip;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
- if ([createdWindow respondsToSelector:@selector(setRestorable:)])
+ if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
[createdWindow setRestorable: NO];
+ }
#endif
- NSInteger level = windowLevel(flags);
- [createdWindow setLevel:level];
-
if (window()->format().alphaBufferSize() > 0) {
[createdWindow setBackgroundColor:[NSColor clearColor]];
[createdWindow setOpaque:NO];
@@ -948,10 +911,12 @@ NSWindow * QCocoaWindow::createNSWindow()
return createdWindow;
}
-void QCocoaWindow::setNSWindow(NSWindow *window)
+void QCocoaWindow::setNSWindow(QNSWindow *window)
{
- m_nsWindowDelegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:this];
- [window setDelegate:m_nsWindowDelegate];
+ if (!m_nsWindowDelegate) {
+ m_nsWindowDelegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:this];
+ [window setDelegate:m_nsWindowDelegate];
+ }
// Prevent Cocoa from releasing the window on close. Qt
// handles the close event asynchronously and we want to
@@ -959,25 +924,28 @@ void QCocoaWindow::setNSWindow(NSWindow *window)
// QCocoaWindow is deleted by Qt.
[window setReleasedWhenClosed : NO];
-
if (m_qtView)
[[NSNotificationCenter defaultCenter] addObserver:m_qtView
selector:@selector(windowNotification:)
name:nil // Get all notifications
object:m_nsWindow];
- [m_contentView setPostsFrameChangedNotifications: NO];
- [window setContentView:m_contentView];
- [m_contentView setPostsFrameChangedNotifications: YES];
+ if (window.contentView != m_contentView) {
+ [m_contentView setPostsFrameChangedNotifications: NO];
+ [window setContentView:m_contentView];
+ [m_contentView setPostsFrameChangedNotifications: YES];
+ }
}
-void QCocoaWindow::clearNSWindow(NSWindow *window)
+void QCocoaWindow::clearNSWindow(QNSWindow *window)
{
[window setContentView:nil];
[window setDelegate:nil];
[window clearPlatformWindow];
- [[NSNotificationCenter defaultCenter] removeObserver:m_contentView
- name:nil object:window];
+
+ if (m_qtView)
+ [[NSNotificationCenter defaultCenter] removeObserver:m_qtView
+ name:nil object:window];
}
// Returns the current global screen geometry for the nswindow associated with this window.