Cocoa: Add basic support for Qt::SubWindow.
This allows embedding a QWindow in a foreign NSView hierarchy. Don't create a NSWindow. Add code paths for handling the embedded window case. Avoid changing the other window cases. There is potential for merging some of these cases but that can be done at a later point in time. Change-Id: I54c7b4eb82fad268f90ea6b716fc650ae31bd3af Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com>bb10
parent
bfce04fe5b
commit
3dc634be36
|
|
@ -162,6 +162,8 @@ public: // for QNSView
|
|||
|
||||
QNSView *m_contentView;
|
||||
NSWindow *m_nsWindow;
|
||||
bool m_contentViewIsEmbedded; // true if the m_contentView is embedded in a "foregin" NSView hiearchy
|
||||
|
||||
QNSWindowDelegate *m_nsWindowDelegate;
|
||||
Qt::WindowFlags m_windowFlags;
|
||||
Qt::WindowState m_synchedWindowState;
|
||||
|
|
|
|||
|
|
@ -186,6 +186,7 @@ static bool isMouseEvent(NSEvent *ev)
|
|||
QCocoaWindow::QCocoaWindow(QWindow *tlw)
|
||||
: QPlatformWindow(tlw)
|
||||
, m_nsWindow(0)
|
||||
, m_contentViewIsEmbedded(false)
|
||||
, m_nsWindowDelegate(0)
|
||||
, m_synchedWindowState(Qt::WindowActive)
|
||||
, m_windowModality(Qt::NonModal)
|
||||
|
|
@ -237,6 +238,10 @@ void QCocoaWindow::setGeometry(const QRect &rect)
|
|||
void QCocoaWindow::setCocoaGeometry(const QRect &rect)
|
||||
{
|
||||
QCocoaAutoReleasePool pool;
|
||||
|
||||
if (m_contentViewIsEmbedded)
|
||||
return;
|
||||
|
||||
if (m_nsWindow) {
|
||||
NSRect bounds = qt_mac_flipRect(rect, window());
|
||||
[m_nsWindow setContentSize : bounds.size];
|
||||
|
|
@ -634,7 +639,9 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
|
|||
m_nsWindowDelegate = 0;
|
||||
}
|
||||
|
||||
if (!parentWindow) {
|
||||
if (window()->type() == Qt::SubWindow) {
|
||||
// Subwindows don't have a NSWindow.
|
||||
} else if (!parentWindow) {
|
||||
// Create a new NSWindow if this is a top-level window.
|
||||
m_nsWindow = createNSWindow();
|
||||
setNSWindow(m_nsWindow);
|
||||
|
|
|
|||
|
|
@ -173,6 +173,36 @@ static QTouchDevice *touchDevice = 0;
|
|||
QWindowSystemInterface::handleExposeEvent(m_window, m_window->geometry());
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToSuperview
|
||||
{
|
||||
if (!(m_window->type() & Qt::SubWindow))
|
||||
return;
|
||||
|
||||
if ([self superview]) {
|
||||
m_platformWindow->m_contentViewIsEmbedded = true;
|
||||
QWindowSystemInterface::handleGeometryChange(m_window, m_platformWindow->geometry());
|
||||
QWindowSystemInterface::handleExposeEvent(m_window, m_platformWindow->geometry());
|
||||
QWindowSystemInterface::flushWindowSystemEvents();
|
||||
} else {
|
||||
m_platformWindow->m_contentViewIsEmbedded = false;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewWillMoveToWindow:(NSWindow *)newWindow
|
||||
{
|
||||
// ### Merge "normal" window code path with this one for 5.1.
|
||||
if (!(m_window->type() & Qt::SubWindow))
|
||||
return;
|
||||
|
||||
if (newWindow) {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(windowNotification:)
|
||||
name:nil // Get all notifications
|
||||
object:newWindow];
|
||||
} else {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:[self window]];
|
||||
}
|
||||
}
|
||||
- (void)updateGeometry
|
||||
{
|
||||
QRect geometry;
|
||||
|
|
@ -181,6 +211,9 @@ static QTouchDevice *touchDevice = 0;
|
|||
NSRect rect = [self frame];
|
||||
NSRect windowRect = [[self window] frame];
|
||||
geometry = QRect(windowRect.origin.x, qt_mac_flipYCoordinate(windowRect.origin.y + rect.size.height), rect.size.width, rect.size.height);
|
||||
} else if (m_window->type() & Qt::SubWindow) {
|
||||
// embedded child window, use the frame rect ### merge with case below
|
||||
geometry = qt_mac_toQRect([self bounds]);
|
||||
} else {
|
||||
// child window, use the frame rect
|
||||
geometry = qt_mac_toQRect([self frame]);
|
||||
|
|
@ -198,6 +231,12 @@ static QTouchDevice *touchDevice = 0;
|
|||
// an infinite loop when this notification is triggered again.)
|
||||
m_platformWindow->QPlatformWindow::setGeometry(geometry);
|
||||
|
||||
// Don't send the geometry change if the QWindow is designated to be
|
||||
// embedded in a foregin view hiearchy but has not actually been
|
||||
// embedded yet - it's too early.
|
||||
if ((m_window->type() & Qt::SubWindow) && !m_platformWindow->m_contentViewIsEmbedded)
|
||||
return;
|
||||
|
||||
// Send a geometry change event to Qt, if it's ready to handle events
|
||||
if (!m_platformWindow->m_inConstructor) {
|
||||
QWindowSystemInterface::handleGeometryChange(m_window, geometry);
|
||||
|
|
@ -317,7 +356,12 @@ static QTouchDevice *touchDevice = 0;
|
|||
);
|
||||
CGImageRef bsCGImage = m_backingStore->getBackingStoreCGImage();
|
||||
CGImageRef cleanImg = CGImageCreateWithImageInRect(bsCGImage, backingStoreRect);
|
||||
CGContextSetBlendMode(cgContext, kCGBlendModeCopy);
|
||||
|
||||
// Optimization: Copy frame buffer content instead of blending for
|
||||
// top-level windows where Qt fills the entire window content area.
|
||||
if (m_platformWindow->m_nsWindow)
|
||||
CGContextSetBlendMode(cgContext, kCGBlendModeCopy);
|
||||
|
||||
CGContextDrawImage(cgContext, dirtyWindowRect, cleanImg);
|
||||
|
||||
// Clean-up:
|
||||
|
|
|
|||
Loading…
Reference in New Issue