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 <gabriel.dedietrich@digia.com>
This commit is contained in:
Liang Qi 2014-01-03 14:11:27 +01:00 committed by The Qt Project
parent b5ab7ee0d7
commit bdd3ead827
3 changed files with 67 additions and 13 deletions

View File

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

View File

@ -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<QWindow *>(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

View File

@ -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<int>("windowflags");
QTest::addColumn<int>("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);