From 7bf2c1d73eb952bef8254320691488f081657c51 Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Fri, 22 Feb 2019 18:54:52 +0000 Subject: [PATCH] [wayland] Fix window sizing when restoring a window that was initially fullscreen Summary: When creating a surface and setting it as fullscreen before attaching its buffer KWin does not know the original dimensions of the surface and tries to use an invalid value when unsetting the fullscreen flag. This patch fixes this by sending a configure with the size of 0,0 - which according to xdg-shell spec means that the client is requested to set its size by itself. Test Plan: 1. Create a fullscreen Wayland window. 2. Toggle fullscreen off. 3. KWin should send a configure event with size 0,0 instead of 1,1. Reviewers: #kwin, davidedmundson Reviewed By: #kwin, davidedmundson Subscribers: zzag, graesslin, davidedmundson, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D16710 --- autotests/integration/shell_client_test.cpp | 53 +++++++++++++++++++++ shell_client.cpp | 7 +-- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/autotests/integration/shell_client_test.cpp b/autotests/integration/shell_client_test.cpp index ada55eb052..f60caeab57 100644 --- a/autotests/integration/shell_client_test.cpp +++ b/autotests/integration/shell_client_test.cpp @@ -72,6 +72,8 @@ private Q_SLOTS: void testMinimizeActiveWindow(); void testFullscreen_data(); void testFullscreen(); + void testFullscreenRestore_data(); + void testFullscreenRestore(); void testUserCanSetFullscreen_data(); void testUserCanSetFullscreen(); void testUserSetFullscreenWlShell(); @@ -524,6 +526,57 @@ void TestShellClient::testFullscreen() QCOMPARE(c->isDecorated(), decoMode == ServerSideDecoration::Mode::Server); } +void TestShellClient::testFullscreenRestore_data() +{ + QTest::addColumn("type"); + + QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5; + QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6; + QTest::newRow("xdgShellWmBase") << Test::ShellSurfaceType::XdgShellStable; +} + +void TestShellClient::testFullscreenRestore() +{ + // this test verifies that windows created fullscreen can be later properly restored + QScopedPointer surface(Test::createSurface()); + QFETCH(Test::ShellSurfaceType, type); + QScopedPointer shellSurface(Test::createShellSurface(type, surface.data())); + + XdgShellSurface *xdgShellSurface = nullptr; + // fullscreen the window + xdgShellSurface = qobject_cast(shellSurface.data()); + xdgShellSurface->setFullscreen(true); + + auto c = Test::renderAndWaitForShown(surface.data(), QSize(screens()->size(0)), Qt::blue); + QVERIFY(c); + QVERIFY(c->isFullScreen()); + + QSignalSpy fullscreenChangedSpy(c, &ShellClient::fullScreenChanged); + QVERIFY(fullscreenChangedSpy.isValid()); + QSignalSpy geometryChangedSpy(c, &ShellClient::geometryChanged); + QVERIFY(geometryChangedSpy.isValid()); + QSignalSpy configureRequestedSpy(shellSurface.data(), SIGNAL(configureRequested(QSize, KWayland::Client::XdgShellSurface::States, quint32))); + QVERIFY(configureRequestedSpy.isValid()); + + // swap back to normal + xdgShellSurface->setFullscreen(false); + + QVERIFY(fullscreenChangedSpy.wait()); + QVERIFY(configureRequestedSpy.wait()); + QCOMPARE(configureRequestedSpy.last().first().toSize(), QSize(0, 0)); + QVERIFY(!c->isFullScreen()); + + for (const auto &it: configureRequestedSpy) { + xdgShellSurface->ackConfigure(it[2].toInt()); + } + + Test::render(surface.data(), QSize(100, 50), Qt::red); + QVERIFY(geometryChangedSpy.wait()); + QCOMPARE(geometryChangedSpy.count(), 1); + QVERIFY(!c->isFullScreen()); + QCOMPARE(c->geometry().size(), QSize(100, 50)); +} + void TestShellClient::testUserCanSetFullscreen_data() { QTest::addColumn("type"); diff --git a/shell_client.cpp b/shell_client.cpp index 892dced092..e156b91a87 100644 --- a/shell_client.cpp +++ b/shell_client.cpp @@ -920,14 +920,15 @@ void ShellClient::setFullScreen(bool set, bool user) if (isFullScreen()) { setGeometry(workspace()->clientArea(FullScreenArea, this)); } else { - if (!m_geomFsRestore.isNull()) { + if (m_geomFsRestore.isValid()) { int currentScreen = screen(); setGeometry(QRect(m_geomFsRestore.topLeft(), adjustedSize(m_geomFsRestore.size()))); if( currentScreen != screen()) workspace()->sendClientToScreen( this, currentScreen ); } else { - // does this ever happen? - setGeometry(workspace()->clientArea(MaximizeArea, this)); + // this can happen when the window was first shown already fullscreen, + // so let the client set the size by itself + setGeometry(QRect(workspace()->clientArea(PlacementArea, this).topLeft(), QSize(0, 0))); } } updateWindowRules(Rules::Fullscreen|Rules::Position|Rules::Size);