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 <timur.pocheptsov@qt.io>
This commit is contained in:
Tor Arne Vestbø 2017-01-25 12:58:29 +01:00 committed by Timur Pocheptsov
parent fa3dca176e
commit 0b18d51b89
6 changed files with 24 additions and 31 deletions

View File

@ -241,11 +241,11 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowActivated, QWindow *window, Qt::Fo
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(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<Delivery>(e);
}
void QWindowSystemInterface::handleWindowScreenChanged(QWindow *window, QScreen *screen)

View File

@ -175,6 +175,7 @@ public:
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
static void handleWindowActivated(QWindow *window, Qt::FocusReason r = Qt::OtherFocusReason);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
static void handleWindowStateChanged(QWindow *window, Qt::WindowState newState);
static void handleWindowScreenChanged(QWindow *window, QScreen *newScreen);

View File

@ -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);

View File

@ -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<QWindowSystemInterface::SynchronousDelivery>(window(), newState);
m_synchedWindowState = window()->windowState();
}
bool QCocoaWindow::setWindowModified(bool modified)
{
if (!m_nsWindow)

View File

@ -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;

View File

@ -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