From 9cc80d7468c92a2800daf98319e626e022ff1045 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Tue, 7 Dec 2021 09:32:33 +0200 Subject: [PATCH] wayland: Resize the client to last requested client size if decoration is destroyed If the decoration is destroyed before the window is mapped, kwin can respond with a configure event that has 0x0 size. New tests check that problematic case. BUG: 444962 --- autotests/integration/xdgshellclient_test.cpp | 48 +++++++++++++++++++ src/abstract_client.cpp | 3 +- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/autotests/integration/xdgshellclient_test.cpp b/autotests/integration/xdgshellclient_test.cpp index 77d7f753d9..c8ff0d0748 100644 --- a/autotests/integration/xdgshellclient_test.cpp +++ b/autotests/integration/xdgshellclient_test.cpp @@ -104,6 +104,8 @@ private Q_SLOTS: void testPointerInputTransform(); void testReentrantSetFrameGeometry(); void testDoubleMaximize(); + void testMaximizeAndChangeDecorationModeAfterInitialCommit(); + void testFullScreenAndChangeDecorationModeAfterInitialCommit(); }; void TestXdgShellClient::testXdgWindowReactive() @@ -1837,5 +1839,51 @@ void TestXdgShellClient::testMaximizeFull() QVERIFY(Test::waitForWindowDestroyed(client)); } +void TestXdgShellClient::testMaximizeAndChangeDecorationModeAfterInitialCommit() +{ + // Ideally, the app would initialize the xdg-toplevel surface before the initial commit, but + // many don't do it. They initialize the surface after the first commit. + // This test verifies that the client will receive a configure event with correct size + // if an xdg-toplevel surface is set maximized and decoration mode changes after initial commit. + + QScopedPointer surface(Test::createSurface()); + QScopedPointer shellSurface(Test::createXdgToplevelSurface(surface.data())); // will wait for the first configure event + QScopedPointer decoration(Test::createXdgToplevelDecorationV1(shellSurface.data())); + QSignalSpy toplevelConfigureRequestedSpy(shellSurface.data(), &Test::XdgToplevel::configureRequested); + QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested); + + // Request maximized mode and set decoration mode, i.e. perform late initialization. + shellSurface->set_maximized(); + decoration->set_mode(Test::XdgToplevelDecorationV1::mode_client_side); + + // The compositor will respond with a new configure event, which should contain maximized state. + QVERIFY(surfaceConfigureRequestedSpy.wait()); + QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value(), QSize(1280, 1024)); + QCOMPARE(toplevelConfigureRequestedSpy.last().at(1).value(), Test::XdgToplevel::State::Maximized); +} + +void TestXdgShellClient::testFullScreenAndChangeDecorationModeAfterInitialCommit() +{ + // Ideally, the app would initialize the xdg-toplevel surface before the initial commit, but + // many don't do it. They initialize the surface after the first commit. + // This test verifies that the client will receive a configure event with correct size + // if an xdg-toplevel surface is set fullscreen and decoration mode changes after initial commit. + + QScopedPointer surface(Test::createSurface()); + QScopedPointer shellSurface(Test::createXdgToplevelSurface(surface.data())); // will wait for the first configure event + QScopedPointer decoration(Test::createXdgToplevelDecorationV1(shellSurface.data())); + QSignalSpy toplevelConfigureRequestedSpy(shellSurface.data(), &Test::XdgToplevel::configureRequested); + QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested); + + // Request fullscreen mode and set decoration mode, i.e. perform late initialization. + shellSurface->set_fullscreen(nullptr); + decoration->set_mode(Test::XdgToplevelDecorationV1::mode_client_side); + + // The compositor will respond with a new configure event, which should contain fullscreen state. + QVERIFY(surfaceConfigureRequestedSpy.wait()); + QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value(), QSize(1280, 1024)); + QCOMPARE(toplevelConfigureRequestedSpy.last().at(1).value(), Test::XdgToplevel::State::Fullscreen); +} + WAYLANDTEST_MAIN(TestXdgShellClient) #include "xdgshellclient_test.moc" diff --git a/src/abstract_client.cpp b/src/abstract_client.cpp index 21053359e3..826b0dc9a2 100644 --- a/src/abstract_client.cpp +++ b/src/abstract_client.cpp @@ -2337,8 +2337,9 @@ void AbstractClient::createDecoration(const QRect &oldGeometry) void AbstractClient::destroyDecoration() { + const QSize clientSize = frameSizeToClientSize(moveResizeGeometry().size()); setDecoration(nullptr); - resize(implicitSize()); + resize(clientSize); } void AbstractClient::setDecoration(KDecoration2::Decoration *decoration)