diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm index f536045fec..eac0e61be9 100644 --- a/src/plugins/platforms/cocoa/qnswindow.mm +++ b/src/plugins/platforms/cocoa/qnswindow.mm @@ -225,6 +225,16 @@ NSWindow *qnswindow_cast(NSWindow *window) m_platformWindow->setWindowFilePath(window->filePath()); // Also sets window icon m_platformWindow->setWindowState(window->windowState()); m_platformWindow->setOpacity(window->opacity()); + + // At the time of creation the QNSWindow is given a geometry based + // on the client geometry of the QWindow. But at that point we don't + // know anything about the size of the NSWindow frame, which means + // that the logic in QCocoaWindow::setGeometry for adjusting the + // client geometry based on the QWindow's positionPolicy is a noop. + // Now that we have a NSWindow to read the frame from we re-apply + // the QWindow geometry, which will move the NSWindow if needed. + m_platformWindow->setGeometry(window->geometry()); + m_platformWindow->setVisible(window->isVisible()); } diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index 227fd77e1a..232fc7af9a 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -46,6 +46,8 @@ private slots: void mapGlobal(); void positioning_data(); void positioning(); + void framePositioning(); + void framePositioning_data(); void positioningDuringMinimized(); void childWindowPositioning_data(); void childWindowPositioning(); @@ -607,39 +609,64 @@ void tst_QWindow::positioning() QTRY_COMPARE(originalPos, window.position()); QTRY_COMPARE(originalFramePos, window.framePosition()); QTRY_COMPARE(originalMargins, window.frameMargins()); +} - // 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)) { - const QScreen *screen = window.screen(); - const QRect availableGeometry = screen->availableGeometry(); - const QPoint framePos = availableGeometry.center(); +void tst_QWindow::framePositioning_data() +{ + QTest::addColumn("showBeforePositioning"); - window.reset(); - const QPoint oldFramePos = window.framePosition(); - window.setFramePosition(framePos); + QTest::newRow("before show") << false; + QTest::newRow("after show") << true; +} - QTRY_VERIFY(window.received(QEvent::Move)); - const int fuzz = int(QHighDpiScaling::factor(&window)); - if (!qFuzzyCompareWindowPosition(window.framePosition(), framePos, fuzz)) { - qDebug() << "About to fail auto-test. Here is some additional information:"; - qDebug() << "window.framePosition() == " << window.framePosition(); - qDebug() << "old frame position == " << oldFramePos; - qDebug() << "We received " << window.received(QEvent::Move) << " move events"; - qDebug() << "frame positions after each move event:" << window.m_framePositionsOnMove; - } - QTRY_VERIFY2(qFuzzyCompareWindowPosition(window.framePosition(), framePos, fuzz), - qPrintable(msgPointMismatch(window.framePosition(), framePos))); +void tst_QWindow::framePositioning() +{ + QFETCH(bool, showBeforePositioning); + + Window window; + const QScreen *screen = window.screen(); + const QRect availableGeometry = screen->availableGeometry(); + const QPoint screenCenter = availableGeometry.center(); + + const QPoint oldFramePos = window.framePosition(); + QMargins originalMargins; + + if (showBeforePositioning) { + window.showNormal(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + originalMargins = window.frameMargins(); + window.setFramePosition(screenCenter); + } else { + window.setFramePosition(screenCenter); + window.showNormal(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + } + + QTRY_VERIFY(window.received(QEvent::Move)); + const int fuzz = int(QHighDpiScaling::factor(&window)); + if (!qFuzzyCompareWindowPosition(window.framePosition(), screenCenter, fuzz)) { + qDebug() << "About to fail auto-test. Here is some additional information:"; + qDebug() << "window.framePosition() == " << window.framePosition(); + qDebug() << "old frame position == " << oldFramePos; + qDebug() << "We received " << window.received(QEvent::Move) << " move events"; + qDebug() << "frame positions after each move event:" << window.m_framePositionsOnMove; + } + QTRY_VERIFY2(qFuzzyCompareWindowPosition(window.framePosition(), screenCenter, fuzz), + qPrintable(msgPointMismatch(window.framePosition(), screenCenter))); + + if (showBeforePositioning) { + // Repositioning should not affect existing margins QTRY_COMPARE(originalMargins, window.frameMargins()); QCOMPARE(window.position(), window.framePosition() + QPoint(originalMargins.left(), originalMargins.top())); - - // and back to regular positioning - - window.reset(); - window.setPosition(originalPos); - QTRY_VERIFY(window.received(QEvent::Move)); - QTRY_COMPARE(originalPos, window.position()); } + + // Check that regular positioning still works + + const QPoint screenCenterAdjusted = screenCenter + QPoint(50, 50); + window.reset(); + window.setPosition(screenCenterAdjusted); + QTRY_VERIFY(window.received(QEvent::Move)); + QTRY_COMPARE(screenCenterAdjusted, window.position()); } void tst_QWindow::positioningDuringMinimized()