From 0b18d51b89d49d0c6f26de45ecc415ba540930e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 25 Jan 2017 12:58:29 +0100 Subject: [PATCH] macOS: Handle window state changes directly in QCocoaWindow Now that notification callbacks are delivered directly to QCocoaWindow, it doesn't make sense to then send them to QPA via QNSView. By skipping the QNSView roundtrip we also enable window state notifications for foreign windows. As an optimization we no longer flush all window system events, but use the new synchronous API to deliver the window state change event. Change-Id: I529b625fbe22e664c34a51bcd4448d1bf0392e6b Reviewed-by: Timur Pocheptsov --- src/gui/kernel/qwindowsysteminterface.cpp | 4 +-- src/gui/kernel/qwindowsysteminterface.h | 1 + src/plugins/platforms/cocoa/qcocoawindow.h | 2 +- src/plugins/platforms/cocoa/qcocoawindow.mm | 30 +++++++++++++-------- src/plugins/platforms/cocoa/qnsview.h | 1 - src/plugins/platforms/cocoa/qnsview.mm | 17 +----------- 6 files changed, 24 insertions(+), 31 deletions(-) diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index b273682b976..2fc713f7081 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -241,11 +241,11 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowActivated, QWindow *window, Qt::Fo QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } -void QWindowSystemInterface::handleWindowStateChanged(QWindow *window, Qt::WindowState newState) +QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowStateChanged, QWindow *window, Qt::WindowState newState) { QWindowSystemInterfacePrivate::WindowStateChangedEvent *e = new QWindowSystemInterfacePrivate::WindowStateChangedEvent(window, newState); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } void QWindowSystemInterface::handleWindowScreenChanged(QWindow *window, QScreen *screen) diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index 11864e7adc3..eb52dd89b6a 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -175,6 +175,7 @@ public: template static void handleWindowActivated(QWindow *window, Qt::FocusReason r = Qt::OtherFocusReason); + template static void handleWindowStateChanged(QWindow *window, Qt::WindowState newState); static void handleWindowScreenChanged(QWindow *window, QScreen *newScreen); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index bb015c24194..b057299d0e0 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -217,7 +217,7 @@ public: bool windowShouldClose(); bool windowIsPopupType(Qt::WindowType type = Qt::Widget) const; - void setSynchedWindowStateFromWindow(); + void handleWindowStateChanged(Qt::WindowState); NSInteger windowLevel(Qt::WindowFlags flags); NSUInteger windowStyleMask(Qt::WindowFlags flags); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 114efc3e92f..2c4c06fdbc4 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1282,7 +1282,7 @@ void QCocoaWindow::windowDidEndLiveResize() { if (m_synchedWindowState == Qt::WindowMaximized && ![m_nsWindow isZoomed]) { m_effectivelyMaximized = false; - [qnsview_cast(m_view) notifyWindowStateChanged:Qt::WindowNoState]; + handleWindowStateChanged(Qt::WindowNoState); } } @@ -1320,22 +1320,22 @@ void QCocoaWindow::windowDidResignKey() void QCocoaWindow::windowDidMiniaturize() { - [qnsview_cast(m_view) notifyWindowStateChanged:Qt::WindowMinimized]; + handleWindowStateChanged(Qt::WindowMinimized); } void QCocoaWindow::windowDidDeminiaturize() { - [qnsview_cast(m_view) notifyWindowStateChanged:Qt::WindowNoState]; + handleWindowStateChanged(Qt::WindowNoState); } void QCocoaWindow::windowDidEnterFullScreen() { - [qnsview_cast(m_view) notifyWindowStateChanged:Qt::WindowFullScreen]; + handleWindowStateChanged(Qt::WindowFullScreen); } void QCocoaWindow::windowDidExitFullScreen() { - [qnsview_cast(m_view) notifyWindowStateChanged:Qt::WindowNoState]; + handleWindowStateChanged(Qt::WindowNoState); } void QCocoaWindow::windowDidOrderOffScreen() @@ -1399,12 +1399,6 @@ bool QCocoaWindow::windowShouldClose() // -------------------------------------------------------------------------- -void QCocoaWindow::setSynchedWindowStateFromWindow() -{ - if (QWindow *w = window()) - m_synchedWindowState = w->windowState(); -} - bool QCocoaWindow::windowIsPopupType(Qt::WindowType type) const { if (type == Qt::Widget) @@ -1834,6 +1828,20 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState) m_synchedWindowState = predictedState; } +void QCocoaWindow::handleWindowStateChanged(Qt::WindowState newState) +{ + // If the window was maximized, then fullscreen, then tried to go directly to "normal" state, + // this notification will say that it is "normal", but it will still look maximized, and + // if you called performZoom it would actually take it back to "normal". + // So we should say that it is maximized because it actually is. + if (newState == Qt::WindowNoState && m_effectivelyMaximized) + newState = Qt::WindowMaximized; + + QWindowSystemInterface::handleWindowStateChanged(window(), newState); + + m_synchedWindowState = window()->windowState(); +} + bool QCocoaWindow::setWindowModified(bool modified) { if (!m_nsWindow) diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index 84be7eb797b..a33e1a9de8d 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -100,7 +100,6 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); - (void)drawRect:(NSRect)dirtyRect; - (void)drawBackingStoreUsingCoreGraphics:(NSRect)dirtyRect; - (void)updateGeometry; -- (void)notifyWindowStateChanged:(Qt::WindowState)newState; - (void)notifyWindowWillZoom:(BOOL)willZoom; - (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification; - (void)viewDidHide; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 7ce407f7d0f..2009096aaac 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -339,21 +339,6 @@ static bool _q_dontOverrideCtrlLMB = false; } } -- (void)notifyWindowStateChanged:(Qt::WindowState)newState -{ - // If the window was maximized, then fullscreen, then tried to go directly to "normal" state, - // this notification will say that it is "normal", but it will still look maximized, and - // if you called performZoom it would actually take it back to "normal". - // So we should say that it is maximized because it actually is. - if (newState == Qt::WindowNoState && m_platformWindow->m_effectivelyMaximized) - newState = Qt::WindowMaximized; - QWindowSystemInterface::handleWindowStateChanged(m_platformWindow->window(), newState); - // We want to read the window state back from the window, - // but the event we just sent may be asynchronous. - QWindowSystemInterface::flushWindowSystemEvents(); - m_platformWindow->setSynchedWindowStateFromWindow(); -} - - (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification { Q_UNUSED(textInputContextKeyboardSelectionDidChangeNotification) @@ -368,7 +353,7 @@ static bool _q_dontOverrideCtrlLMB = false; Qt::WindowState newState = willZoom ? Qt::WindowMaximized : Qt::WindowNoState; if (!willZoom) m_platformWindow->m_effectivelyMaximized = false; - [self notifyWindowStateChanged:newState]; + m_platformWindow->handleWindowStateChanged(newState); } - (void)viewDidHide