From b572aadfd56ecff397bc7b2916923bd1337097ef Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Thu, 20 Jan 2022 17:10:08 +0200 Subject: [PATCH] wayland: Allow setting "no border" flag even without xdg decoration Historically, noBorder() was used for two things: * as a substitute for AbstractClient::isDecorated() * to determine whether the AbstractClient should have a decoration With async decoration updates refactoring, a few things around noBorder() have changed, which exposed an existing bug in the handling of borderless maximized windows. It's possible to have a case where an initially maximized window makes an xdg_toplevel.set_maximized request before the initial commit, but creates the decoration object after the initial commit. Since XdgToplevelClient::userCanSetNoBorder() would return false when maximize() is called in XdgToplevelClient::initialize(), m_userNoBorder won't be updated and therefore the window can end up having a server side decoration. Previously, it wasn't the case because kwin would do nothing if the decoration is installed and its preferred mode changes after the initial commit but before the surface is mapped. With async decoration fixes, kwin would react as expected, which unfortunately has exposed the bug. The root cause of the problem is the fact that noBorder() is overloaded, which makes it error-prone. This patch changes how the noBorder property is treated. Now, it only indicates whether the compositor wants the window to have no borders. If noBorder() is true, it means that the compositor doesn't want the window to have a server-side decoration; on the other hand, if noBorder() is false, it doesn't imply that the window should have a decoration. BUG: 448740 --- autotests/integration/dbus_interface_test.cpp | 2 +- src/useractions.cpp | 4 +++- src/xdgshellclient.cpp | 5 +---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/autotests/integration/dbus_interface_test.cpp b/autotests/integration/dbus_interface_test.cpp index e324faefd2..a64b5269fd 100644 --- a/autotests/integration/dbus_interface_test.cpp +++ b/autotests/integration/dbus_interface_test.cpp @@ -137,7 +137,7 @@ void TestDbusInterface::testGetWindowInfoXdgShellClient() QCOMPARE(windowData.value(QStringLiteral("skipSwitcher")).toBool(), false); QCOMPARE(windowData.value(QStringLiteral("maximizeHorizontal")).toBool(), false); QCOMPARE(windowData.value(QStringLiteral("maximizeVertical")).toBool(), false); - QCOMPARE(windowData.value(QStringLiteral("noBorder")).toBool(), true); + QCOMPARE(windowData.value(QStringLiteral("noBorder")).toBool(), false); QCOMPARE(windowData.value(QStringLiteral("clientMachine")).toString(), QString()); QCOMPARE(windowData.value(QStringLiteral("localhost")).toBool(), true); QCOMPARE(windowData.value(QStringLiteral("role")).toString(), QString()); diff --git a/src/useractions.cpp b/src/useractions.cpp index b97c12898d..f056de21d1 100644 --- a/src/useractions.cpp +++ b/src/useractions.cpp @@ -1217,7 +1217,9 @@ void Workspace::performWindowOperation(AbstractClient* c, Options::WindowOperati c->setFullScreen(!c->isFullScreen(), true); break; case Options::NoBorderOp: - c->setNoBorder(!c->noBorder()); + if (c->userCanSetNoBorder()) { + c->setNoBorder(!c->noBorder()); + } break; case Options::KeepAboveOp: { StackingUpdatesBlocker blocker(this); diff --git a/src/xdgshellclient.cpp b/src/xdgshellclient.cpp index 4e778e6bd2..906078d874 100644 --- a/src/xdgshellclient.cpp +++ b/src/xdgshellclient.cpp @@ -741,14 +741,11 @@ bool XdgToplevelClient::userCanSetNoBorder() const bool XdgToplevelClient::noBorder() const { - return m_userNoBorder || preferredDecorationMode() != DecorationMode::Server; + return m_userNoBorder; } void XdgToplevelClient::setNoBorder(bool set) { - if (!userCanSetNoBorder()) { - return; - } set = rules()->checkNoBorder(set); if (m_userNoBorder == set) { return;