From bdd3ead8270dfde12b0b4eb57125a22e51ee88ce Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Fri, 3 Jan 2014 14:11:27 +0100 Subject: [PATCH] OSX: support fake fullscreen and etc * Fix QCocoaWindow::setGeometry() to respect WindowFrameInclusive * Support fake fullscreen on 10.6 or WindowFullscreenButtonHint was not set on 10.7 and later * Fix tst_qwindow on 10.6 and later Task-number: QTBUG-23059 Task-number: QTBUG-34629 Change-Id: I6e032ca55b45674388b00506a424d3bd7ece429f Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoawindow.h | 5 +++ src/plugins/platforms/cocoa/qcocoawindow.mm | 39 +++++++++++++++++-- tests/auto/gui/kernel/qwindow/tst_qwindow.cpp | 36 ++++++++++++----- 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index c7ec315f04..69bea31343 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -214,6 +214,11 @@ public: // for QNSView static const int NoAlertRequest; NSInteger m_alertRequest; id monitor; + + // used by showFullScreen in fake mode + QRect m_normalGeometry; + Qt::WindowFlags m_oldWindowFlags; + NSApplicationPresentationOptions m_presentationOptions; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index ad11a525ad..5702689d84 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -220,6 +220,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) , m_overrideBecomeKey(false) , m_alertRequest(NoAlertRequest) , monitor(nil) + , m_normalGeometry(QRect(0,0,-1,-1)) { #ifdef QT_COCOA_ENABLE_WINDOW_DEBUG qDebug() << "QCocoaWindow::QCocoaWindow" << this; @@ -271,8 +272,16 @@ QSurfaceFormat QCocoaWindow::format() const return window()->requestedFormat(); } -void QCocoaWindow::setGeometry(const QRect &rect) +void QCocoaWindow::setGeometry(const QRect &rectIn) { + QRect rect = rectIn; + // This means it is a call from QWindow::setFramePosition() and + // the coordinates include the frame (size is still the contents rectangle). + if (qt_window_private(const_cast(window()))->positionPolicy + == QWindowPrivate::WindowFrameInclusive) { + const QMargins margins = frameMargins(); + rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top())); + } if (geometry() == rect) return; #ifdef QT_COCOA_ENABLE_WINDOW_DEBUG @@ -1012,13 +1021,35 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState) } 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) { - [m_nsWindow toggleFullScreen : m_nsWindow]; - } else { - // TODO: "normal" fullscreen + if (window()->flags() & Qt::WindowFullscreenButtonHint) { + fakeFullScreen = false; + [m_nsWindow toggleFullScreen : m_nsWindow]; + } } #endif + if (fakeFullScreen) { + if (newState & Qt::WindowFullScreen) { + QScreen *screen = window()->screen(); + if (screen) { + if (m_normalGeometry.width() < 0) { + m_oldWindowFlags = m_windowFlags; + window()->setFlags(window()->flags() | Qt::FramelessWindowHint); + m_normalGeometry = windowGeometry(); + setGeometry(screen->geometry()); + m_presentationOptions = [NSApp presentationOptions]; + [NSApp setPresentationOptions : m_presentationOptions | NSApplicationPresentationAutoHideMenuBar | NSApplicationPresentationAutoHideDock]; + } + } + } else { + window()->setFlags(m_oldWindowFlags); + setGeometry(m_normalGeometry); + m_normalGeometry.setRect(0, 0, -1, -1); + [NSApp setPresentationOptions : m_presentationOptions]; + } + } } // New state is now the current synched state diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index 259c840ae7..76b3a4f6cc 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -61,6 +61,7 @@ private slots: void eventOrderOnShow(); void resizeEventAfterResize(); void mapGlobal(); + void positioning_data(); void positioning(); void isExposed(); void isActive(); @@ -93,7 +94,6 @@ private: QTouchDevice *touchDevice; }; - void tst_QWindow::mapGlobal() { QWindow a; @@ -116,10 +116,10 @@ void tst_QWindow::mapGlobal() class Window : public QWindow { public: - Window() + Window(const Qt::WindowFlags flags = Qt::Window | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint) { reset(); - setFlags(Qt::Window | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); + setFlags(flags); } void reset() @@ -188,6 +188,23 @@ void tst_QWindow::resizeEventAfterResize() QTRY_COMPARE(window.received(QEvent::Resize), 2); } +void tst_QWindow::positioning_data() +{ + QTest::addColumn("windowflags"); + QTest::addColumn("resizecount"); + + QTest::newRow("default") << int(Qt::Window | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowFullscreenButtonHint) +#if defined(Q_OS_OSX) && MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 + << 4; +#else + << 3; +#endif + +#ifdef Q_OS_OSX + QTest::newRow("fake") << int(Qt::Window | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint) << 4; +#endif +} + void tst_QWindow::positioning() { if (!QGuiApplicationPrivate::platformIntegration()->hasCapability( @@ -200,7 +217,9 @@ void tst_QWindow::positioning() const QSize size = QSize(300, 40); const QRect geometry(QPoint(80, 80), size); - Window window; + QFETCH(int, windowflags); + QFETCH(int, resizecount); + Window window((Qt::WindowFlags)windowflags); window.setGeometry(QRect(QPoint(20, 20), size)); window.setFramePosition(QPoint(40, 40)); // Move window around before show, size must not change. QCOMPARE(window.geometry().size(), size); @@ -223,14 +242,13 @@ void tst_QWindow::positioning() window.setWindowState(Qt::WindowFullScreen); QCoreApplication::processEvents(); -#ifdef Q_OS_OSX - QEXPECT_FAIL("", "Multiple failures in this test on Mac OS X, see QTBUG-23059", Abort); -#endif QTRY_COMPARE(window.received(QEvent::Resize), 2); + QTest::qWait(2000); + window.setWindowState(Qt::WindowNoState); QCoreApplication::processEvents(); - QTRY_COMPARE(window.received(QEvent::Resize), 3); + QTRY_COMPARE(window.received(QEvent::Resize), resizecount); QTRY_COMPARE(originalPos, window.position()); QTRY_COMPARE(originalFramePos, window.framePosition()); @@ -239,7 +257,7 @@ void tst_QWindow::positioning() // if our positioning is actually fully respected by the window manager // test whether it correctly handles frame positioning as well if (originalPos == geometry.topLeft() && (originalMargins.top() != 0 || originalMargins.left() != 0)) { - QPoint framePos = QGuiApplication::primaryScreen()->availableVirtualGeometry().topLeft() + QPoint(40, 40); + QPoint framePos = QPlatformScreen::platformScreenForWindow(&window)->availableGeometry().topLeft() + QPoint(40, 40); window.reset(); window.setFramePosition(framePos);