OSX: make reported window state consistent with reality

You can't always get what you want: if you exit from fullscreen
mode via showNormal, it might actually be maximized; or if you exit
via showMaximized, it might actually be normal, if that's the mode the
NSWindow remembers.  We can't set the state, we can only toggle it.
But now at least it's predictable, so that if you call showNormal
or showMaximized twice, you will definitely get back to that state.

Task-number: QTBUG-35166
Change-Id: I7422960a64f624920566c25763f5c3b03a684fb5
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com>
bb10
Shawn Rutledge 2014-03-21 14:31:23 +01:00 committed by The Qt Project
parent ce8271ce05
commit a6bf169479
3 changed files with 30 additions and 5 deletions

View File

@ -252,6 +252,7 @@ public: // for QNSView
QList<QCocoaWindow *> m_childWindows;
Qt::WindowFlags m_windowFlags;
bool m_effectivelyMaximized;
Qt::WindowState m_synchedWindowState;
Qt::WindowModality m_windowModality;
QPointer<QWindow> m_activePopupWindow;

View File

@ -352,6 +352,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
, m_contentViewIsToBeEmbedded(false)
, m_parentCocoaWindow(0)
, m_isNSWindowChild(false)
, m_effectivelyMaximized(false)
, m_synchedWindowState(Qt::WindowActive)
, m_windowModality(Qt::NonModal)
, m_windowUnderMouse(false)
@ -1436,7 +1437,6 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState)
{
if (!m_nsWindow)
return;
// if content view width or height is 0 then the window animations will crash so
// do nothing except set the new state
NSRect contentRect = [contentView() frame];
@ -1446,9 +1446,7 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState)
return;
}
if ((m_synchedWindowState & Qt::WindowMaximized) != (newState & Qt::WindowMaximized)) {
[m_nsWindow performZoom : m_nsWindow]; // toggles
}
Qt::WindowState predictedState = newState;
if ((m_synchedWindowState & Qt::WindowMinimized) != (newState & Qt::WindowMinimized)) {
if (newState & Qt::WindowMinimized) {
@ -1458,12 +1456,26 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState)
}
}
if ((m_synchedWindowState & Qt::WindowMaximized) != (newState & Qt::WindowMaximized) || (m_effectivelyMaximized && newState == Qt::WindowNoState)) {
if ((m_synchedWindowState & Qt::WindowFullScreen) == (newState & Qt::WindowFullScreen)) {
[m_nsWindow performZoom : m_nsWindow]; // toggles
m_effectivelyMaximized = !m_effectivelyMaximized;
} else if (!(newState & Qt::WindowMaximized)) {
// it would be nice to change the target geometry that toggleFullScreen will animate toward
// but there is no known way, so the maximized state is not possible at this time
predictedState = static_cast<Qt::WindowState>(static_cast<int>(newState) | Qt::WindowMaximized);
m_effectivelyMaximized = true;
}
}
if ((m_synchedWindowState & Qt::WindowFullScreen) != (newState & Qt::WindowFullScreen)) {
bool fakeFullScreen = true;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
if (window()->flags() & Qt::WindowFullscreenButtonHint) {
fakeFullScreen = false;
if (m_effectivelyMaximized && m_synchedWindowState == Qt::WindowFullScreen)
predictedState = Qt::WindowMaximized;
[m_nsWindow toggleFullScreen : m_nsWindow];
}
}
@ -1490,8 +1502,12 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState)
}
}
#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG
qDebug() << "QCocoaWindow::syncWindowState" << newState << "actual" << predictedState << "was" << m_synchedWindowState << "effectively maximized" << m_effectivelyMaximized;
#endif
// New state is now the current synched state
m_synchedWindowState = newState;
m_synchedWindowState = predictedState;
}
bool QCocoaWindow::setWindowModified(bool modified)

View File

@ -281,6 +281,12 @@ static QTouchDevice *touchDevice = 0;
- (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_window, newState);
// We want to read the window state back from the window,
// but the event we just sent may be asynchronous.
@ -346,6 +352,8 @@ static QTouchDevice *touchDevice = 0;
- (void)notifyWindowWillZoom:(BOOL)willZoom
{
Qt::WindowState newState = willZoom ? Qt::WindowMaximized : Qt::WindowNoState;
if (!willZoom)
m_platformWindow->m_effectivelyMaximized = false;
[self notifyWindowStateChanged:newState];
}