summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorMorten Sorvig <morten.sorvig@nokia.com>2011-12-06 12:59:21 +0100
committerQt by Nokia <qt-info@nokia.com>2011-12-14 23:26:15 +0100
commitf950a0f0c0b9259bb424f0c81fd6516fe8e4e103 (patch)
treee7e1006cbf66bd29192cd6f94656e54fe6405678 /src/plugins
parentf295ef1a4b76eb6421fc3dcd7ab307d471c3e895 (diff)
Make QCocoaWindow independent of NSWindow.
QCocoaWindow now gets resize events from QNSViev and does not require a NSWindow. QWindow instances can now be inserted in NSView hierarchies. This is useful for Qt-as-a-plugin use cases and is needed to implement QMacNativeWidget for Qt 5. Change-Id: Ia95ea9c22a15a3e62d1e6543466cff07390c70a2 Reviewed-by: Morten Johan Sørvig <morten.sorvig@nokia.com>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm7
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h28
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm18
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h4
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm27
5 files changed, 68 insertions, 16 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
index c6aa0d39e6..e48d588e5a 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
@@ -52,8 +52,15 @@
void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window)
{
+ if (!window->handle()) {
+ qWarning("QCocoaNativeInterface::nativeResourceForWindow: Native window has not been created.");
+ return 0;
+ }
+
if (resourceString == "nsopenglcontext") {
return static_cast<QCocoaWindow *>(window->handle())->currentContext()->nsOpenGLContext();
+ } else if (resourceString == "nsview") {
+ return static_cast<QCocoaWindow *>(window->handle())->m_contentView;
}
return 0;
}
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 9fa04a0ca2..2c5f6b5db0 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -65,6 +65,25 @@
@end
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.
+//
+// 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():
+//
+// QWindow *qtWindow = new MyWindow();
+// qtWindow->create();
+// QPlatformNativeInterface *platformNativeInterface = QGuiApplication::platformNativeInterface();
+// NSView *qtView = (NSView *)platformNativeInterface->nativeResourceForWindow("nsview", qtWindow);
+// [parentView addSubview:qtView];
+//
+// See the qt_on_cocoa manual tests for a working example, located
+// in tests/manual/cocoa at the time of writing.
class QCocoaWindow : public QPlatformWindow
{
@@ -97,12 +116,17 @@ protected:
QRect windowGeometry() const;
QCocoaWindow *parentCocoaWindow() const;
-private:
+// private:
+public: // for QNSView
friend class QCocoaBackingStore;
- NSWindow *m_nsWindow;
+ friend class QCocoaNativeInterface;
+
QNSView *m_contentView;
+ QNSWindow *m_nsWindow;
+
quint32 m_windowAttributes;
quint32 m_windowClass;
+ bool m_inConstructor;
QCocoaGLContext *m_glContext;
};
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 859aa87cce..27e8e9a2c9 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -81,6 +81,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
, m_windowAttributes(0)
, m_windowClass(0)
, m_glContext(0)
+ , m_inConstructor(true)
{
QCocoaAutoReleasePool pool;
@@ -97,7 +98,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
// QCocoaWindow is deleted by Qt.
[m_nsWindow setReleasedWhenClosed : NO];
- m_contentView = [[QNSView alloc] initWithQWindow:tlw];
+ m_contentView = [[QNSView alloc] initWithQWindow:tlw platformWindow:this];
// ### Accept touch events by default.
// Beware that enabling touch events has a negative impact on the overall performance.
@@ -107,6 +108,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
setGeometry(tlw->geometry());
[m_nsWindow setContentView:m_contentView];
+ m_inConstructor = false;
}
QCocoaWindow::~QCocoaWindow()
@@ -124,8 +126,6 @@ void QCocoaWindow::setGeometry(const QRect &rect)
QPlatformWindow::setGeometry(rect);
NSRect bounds = qt_mac_flipRect(rect, window());
-
- [[m_nsWindow contentView] setFrameSize:bounds.size];
[m_nsWindow setContentSize : bounds.size];
[m_nsWindow setFrameOrigin : bounds.origin];
}
@@ -232,23 +232,17 @@ void QCocoaWindow::windowDidMove()
{
NSRect rect = [[m_nsWindow contentView]frame];
NSRect windowRect = [m_nsWindow frame];
-
- QRect geo(windowRect.origin.x, qt_mac_flipYCoordinate(windowRect.origin.y + rect.size.height), rect.size.width, rect.size.height);
- setGeometry(geo);
- QWindowSystemInterface::handleSynchronousGeometryChange(window(), geo);
+ [[m_nsWindow contentView] setFrameSize:rect.size];
}
void QCocoaWindow::windowDidResize()
{
NSRect rect = [[m_nsWindow contentView]frame];
NSRect windowRect = [m_nsWindow frame];
-
- QRect geo(windowRect.origin.x, qt_mac_flipYCoordinate(windowRect.origin.y + rect.size.height), rect.size.width, rect.size.height);
- setGeometry(geo);
- QWindowSystemInterface::handleSynchronousGeometryChange(window(), geo);
+ // Call setFrameSize which will trigger a frameDidChangeNotificatio on QNSView.
+ [[m_nsWindow contentView] setFrameSize:rect.size];
}
-
void QCocoaWindow::windowWillClose()
{
QWindowSystemInterface::handleSynchronousCloseEvent(window());
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index eddc1aa7e9..571449492d 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -47,15 +47,17 @@
#include <QtGui/QImage>
#include <QtGui/QAccessible>
+class QCocoaWindow;
@interface QNSView : NSView {
CGImageRef m_cgImage;
QWindow *m_window;
+ QCocoaWindow *m_platformWindow;
Qt::MouseButtons m_buttons;
QAccessibleInterface *m_accessibleRoot;
}
- (id)init;
-- (id)initWithQWindow:(QWindow *)window;
+- (id)initWithQWindow:(QWindow *)window platformWindow:(QCocoaWindow *) platformWindow;
- (void)setImage:(QImage *)image;
- (void)drawRect:(NSRect)dirtyRect;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 82b4e54deb..1a1e02d2fd 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -44,6 +44,7 @@
#include <Carbon/Carbon.h>
#include "qnsview.h"
+#include "qcocoawindow.h"
#include "qcocoahelpers.h"
#include "qmultitouch_mac_p.h"
@@ -81,12 +82,14 @@ static QTouchDevice *touchDevice = 0;
return self;
}
-- (id)initWithQWindow:(QWindow *)window {
+- (id)initWithQWindow:(QWindow *)window platformWindow:(QCocoaWindow *) platformWindow
+{
self = [self init];
if (!self)
return 0;
m_window = window;
+ m_platformWindow = platformWindow;
m_accessibleRoot = 0;
#ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
@@ -106,9 +109,31 @@ static QTouchDevice *touchDevice = 0;
m_accessibleRoot = window->accessibleRoot();
#endif
+ [self setPostsFrameChangedNotifications : YES];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(frameDidChangeNotification:)
+ name:NSViewFrameDidChangeNotification
+ object:self];
+
return self;
}
+- (void) frameDidChangeNotification: (NSNotification *) notification
+{
+ NSRect rect = [self frame];
+ NSRect windowRect = [[self window] frame];
+ QRect geo(windowRect.origin.x, qt_mac_flipYCoordinate(windowRect.origin.y + rect.size.height), rect.size.width, rect.size.height);
+
+ // Call setGeometry on QPlatformWindow. (not on QCocoaWindow,
+ // doing that will initiate a geometry change it and possibly create
+ // an infinite loop when this notification is triggered again.)
+ m_platformWindow->QPlatformWindow::setGeometry(geo);
+
+ // Send a geometry change event to Qt, if it's ready to handle events
+ if (!m_platformWindow->m_inConstructor)
+ QWindowSystemInterface::handleSynchronousGeometryChange(m_window, geo);
+}
+
- (void) setImage:(QImage *)image
{
CGImageRelease(m_cgImage);