From efc62941eeb6161b3b1e3645c5c12f68877dee5f Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Tue, 9 Apr 2019 11:15:02 +0100 Subject: [PATCH] [wayland] Place all toplevels before the first configure Summary: Currently popups get positioned once at the initial configure, to set the correct size and again when they are mapped. Toplevels are currently only positioned when they are mapped. This works for all cases where the the toplevel defines its own size, but not if the window should have an initial size set by the placement strategy or window rules. Most notably the maximised placement strategy used on plasma mobile. Being out of sync and resizing later currently causes a positioning bug when plasma mobile is used with XdgShell. This patch repositions all top levels that don't have a position set through the plasma interface. Test Plan: Relevant unit test Reviewers: #kwin, bshah Reviewed By: bshah Subscribers: zzag, bshah, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D20241 --- autotests/integration/maximize_test.cpp | 40 ++++++++++++++++++++++++- placement.cpp | 4 +++ shell_client.cpp | 2 +- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/autotests/integration/maximize_test.cpp b/autotests/integration/maximize_test.cpp index 5bd85fce17..5abe5928df 100644 --- a/autotests/integration/maximize_test.cpp +++ b/autotests/integration/maximize_test.cpp @@ -31,6 +31,8 @@ along with this program. If not, see . #include #include #include +#include +#include #include #include @@ -55,6 +57,7 @@ private Q_SLOTS: void testInitiallyMaximized(); void testBorderlessMaximizedWindow(); void testBorderlessMaximizedWindowNoClientSideDecoration(); + void testMaximizePlacementStrategy(); }; void TestMaximized::initTestCase() @@ -80,7 +83,8 @@ void TestMaximized::initTestCase() void TestMaximized::init() { QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::Decoration | - Test::AdditionalWaylandInterface::XdgDecoration)); + Test::AdditionalWaylandInterface::XdgDecoration | + Test::AdditionalWaylandInterface::PlasmaShell)); screens()->setCurrent(0); KWin::Cursor::setPos(QPoint(1280, 512)); @@ -294,5 +298,39 @@ void TestMaximized::testBorderlessMaximizedWindowNoClientSideDecoration() QCOMPARE(deco->mode(), XdgDecoration::Mode::ServerSide); } +void TestMaximized::testMaximizePlacementStrategy() +{ + // adjust config + auto group = kwinApp()->config()->group("Windows"); + group.writeEntry("Placement", "Maximizing"); + group.sync(); + Workspace::self()->slotReconfigure(); + + // add a top panel + QScopedPointer panelSurface(Test::createSurface()); + QScopedPointer panelShellSurface(Test::createXdgShellStableSurface(panelSurface.data())); + QScopedPointer plasmaSurface(Test::waylandPlasmaShell()->createSurface(panelSurface.data())); + plasmaSurface->setRole(PlasmaShellSurface::Role::Panel); + plasmaSurface->setPosition(QPoint(0, 0)); + Test::renderAndWaitForShown(panelSurface.data(), QSize(1280, 20), Qt::blue); + + // create a new window - it should be maximised on the first configure and positioned beneath the strut + QScopedPointer surface(Test::createSurface()); + auto shellSurface = Test::createXdgShellStableSurface(surface.data(), surface.data(), Test::CreationSetup::CreateOnly); + QSignalSpy configSpy(shellSurface, &XdgShellSurface::configureRequested); + surface->commit(Surface::CommitFlag::None); + QVERIFY(configSpy.wait()); + + const auto size = configSpy[0][0].toSize(); + const auto states = configSpy[0][1].value(); + QVERIFY(states & XdgShellSurface::State::Maximized); + shellSurface->ackConfigure(configSpy[0][2].toUInt()); + QCOMPARE(size, QSize(1280, 1024 - 20)); + + auto c = Test::renderAndWaitForShown(surface.data(), size, Qt::red); + QVERIFY(c); + QCOMPARE(c->geometry(), QRect(0, 20, 1280, 1024 - 20)); +} + WAYLANDTEST_MAIN(TestMaximized) #include "maximize_test.moc" diff --git a/placement.cpp b/placement.cpp index da1368b8da..b4a3a9eca2 100644 --- a/placement.cpp +++ b/placement.cpp @@ -376,6 +376,10 @@ QPoint Workspace::cascadeOffset(const AbstractClient *c) const **/ void Placement::placeCascaded(AbstractClient* c, QRect& area, Policy nextPlacement) { + if (!c->size().isValid()) { + return; + } + /* cascadePlacement by Cristian Tibirna (tibirna@kde.org) (30Jan98) */ // work coords diff --git a/shell_client.cpp b/shell_client.cpp index c7487ce861..e2477c0003 100644 --- a/shell_client.cpp +++ b/shell_client.cpp @@ -372,7 +372,7 @@ void ShellClient::finishInit() { SurfaceInterface *s = surface(); disconnect(s, &SurfaceInterface::committed, this, &ShellClient::finishInit); - if (m_xdgShellPopup) { + if (!isInitialPositionSet()) { QRect area = workspace()->clientArea(PlacementArea, Screens::self()->current(), desktop()); placeIn(area); }