Skip to content

Commit

Permalink
Fix restoring normal geometry on maximized windows
Browse files Browse the repository at this point in the history
Code is much simplified now. Basically, never call
setGeometry() on a maximized window.

Set the normal geometry on a normal window, only
then set its state.

Fixes issue #499
  • Loading branch information
iamsergio committed Apr 30, 2024
1 parent 616bc37 commit e304045
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 14 deletions.
21 changes: 7 additions & 14 deletions src/LayoutSaver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -527,21 +527,14 @@ bool LayoutSaver::restoreLayout(const QByteArray &data)

if (!(d->m_restoreOptions & InternalRestoreOption::SkipMainWindowGeometry)) {
Window::Ptr window = mainWindow->view()->window();

if (window->windowState() == WindowState::Maximized && mw.windowState != WindowState::Maximized) {
// Never call deserializeWindowGeometry() on a maximized window.
// If window is maximized and we're restoring it to "normal", then 1st change state, then set geometry
window->setWindowState(mw.windowState);
d->deserializeWindowGeometry(mw, window);
} else if (mw.windowState != window->windowState()) {
// If window is normal and we're restoring it to maximized, then set geometry 1st
// so its normal geometry gets remembered, only then maximize

d->deserializeWindowGeometry(mw, window);
window->setWindowState(mw.windowState);
} else {
d->deserializeWindowGeometry(mw, window);
if (window->windowState() == WindowState::Maximized) {
// Restoring geometry needs to be done in normal state.
// Qt doesn't support restoring normal geometry on maximized windows.
window->setWindowState(WindowState::None);
}

d->deserializeWindowGeometry(mw, window);
window->setWindowState(mw.windowState);
}

if (!mainWindow->deserialize(mw))
Expand Down
58 changes: 58 additions & 0 deletions tests/tst_native_qpa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public Q_SLOTS:
private Q_SLOTS:
void tst_restoreNormalFromMaximized();
void tst_restoreMaximizedFromNormal();
void tst_restoreMaximizedFromMaximized();
};

void TestNativeQPA::initTestCase()
Expand Down Expand Up @@ -199,6 +200,63 @@ void TestNativeQPA::tst_restoreMaximizedFromNormal()
QCOMPARE(m->geometry(), expectedMaximizedGeometry);
}

void TestNativeQPA::tst_restoreMaximizedFromMaximized()
{
if (qApp->platformName() == QLatin1String("offscreen")) {
// offscreen: calling showMaximized() on an hidden widget, puts it at pos=2,2 instead of 0,0
// Ignore this QPA. This file is for testing native QPAs only. offscreen is nice to have
// if it beahaves well only.
return;
}

#ifdef Q_OS_MACOS
if (Platform::instance()->isQtQuick())
return;
#endif

// whitelist some macOS warning
SetExpectedWarning warn("invalid window content view size");

// Saves the window state while in maximized state, then restores after the window is shown normal
// the window should become maximized again.
// qDebug() << qApp->primaryScreen()->geometry();
const QSize initialSize(500, 500);
auto m = createMainWindow(initialSize, MainWindowOption_None, "m1", false);

auto windowptr = m->view()->window();
auto window = static_cast<QtCommon::Window *>(windowptr.get());
QWindow *qtwindow = window->qtWindow();
MyEventFilter filter;
qtwindow->installEventFilter(&filter);

m->view()->showMaximized();
QVERIFY(filter.waitForState(Qt::WindowMaximized));

int count = 0;
// Qt annoyingly sends us 2 or 3 resize events before the fully maximized one, even when
// already having state==Qt::WindowMaximized. Probably depends on platform.
// Consume all resize events until window gets big.
while (m->geometry().size().width() < 700) {
QVERIFY(Platform::instance()->tests_waitForResize(m->view()));
count++;
QVERIFY(count < 5);
}

const auto expectedMaximizedGeometry = m->geometry();
QVERIFY(initialSize != expectedMaximizedGeometry.size());

LayoutSaver saver;
const QByteArray saved = saver.serializeLayout();

QVERIFY(saver.restoreLayout(saved));
QVERIFY(filter.waitForState(Qt::WindowMaximized));

// Catch more resizes:
QTest::qWait(1000);

QCOMPARE(m->geometry(), expectedMaximizedGeometry);
}

int main(int argc, char *argv[])
{
#ifdef Q_OS_LINUX
Expand Down

0 comments on commit e304045

Please sign in to comment.