From ab18007d2a62165e82857cdb6ffc9de580698f8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Fl=C3=B6ser?= Date: Sun, 4 Mar 2018 17:05:46 +0100 Subject: [PATCH] Better map ShellClient to resource name and class Summary: The window rules dialog did not properly detect the wayland windows. So I investigated what ICCCM writes about the WM_CLASS property (which is the base for window rule matching) and checked how ShellClient maps to it. Basically name and class was swapped and the reason for the detection not working properly. As we don't have a proper name, the code is adjusted to generate a name by using the executable name. This is also what WM_CLASS should be filled with, according to ICCCM. Test Plan: Rules dialog detects the name and class correctly Reviewers: #kwin, #plasma Subscribers: kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D11023 --- autotests/integration/shell_client_test.cpp | 4 ++++ shell_client.cpp | 14 +++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/autotests/integration/shell_client_test.cpp b/autotests/integration/shell_client_test.cpp index 5edf5b4b7c..b5900895d1 100644 --- a/autotests/integration/shell_client_test.cpp +++ b/autotests/integration/shell_client_test.cpp @@ -778,6 +778,8 @@ void TestShellClient::testDesktopFileName() auto c = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue); QVERIFY(c); QCOMPARE(c->desktopFileName(), QByteArrayLiteral("org.kde.foo")); + QCOMPARE(c->resourceClass(), QByteArrayLiteral("org.kde.foo")); + QVERIFY(c->resourceName().startsWith("testShellClient")); // the desktop file does not exist, so icon should be generic Wayland QCOMPARE(c->icon().name(), QStringLiteral("wayland")); @@ -788,6 +790,8 @@ void TestShellClient::testDesktopFileName() shellSurface->setAppId(QByteArrayLiteral("org.kde.bar")); QVERIFY(desktopFileNameChangedSpy.wait()); QCOMPARE(c->desktopFileName(), QByteArrayLiteral("org.kde.bar")); + QCOMPARE(c->resourceClass(), QByteArrayLiteral("org.kde.bar")); + QVERIFY(c->resourceName().startsWith("testShellClient")); // icon should still be wayland QCOMPARE(c->icon().name(), QStringLiteral("wayland")); QVERIFY(iconChangedSpy.isEmpty()); diff --git a/shell_client.cpp b/shell_client.cpp index f2e1a2ab31..59f5a32930 100644 --- a/shell_client.cpp +++ b/shell_client.cpp @@ -51,6 +51,7 @@ along with this program. If not, see . #include +#include #include #include @@ -126,11 +127,18 @@ void ShellClient::initSurface(T *shellSurface) } ); - setResourceClass(shellSurface->windowClass()); + // determine the resource name, this is inspired from ICCCM 4.1.2.5 + // the binary name of the invoked client + QFileInfo info{shellSurface->client()->executablePath()}; + QByteArray resourceName; + if (info.exists()) { + resourceName = info.fileName().toUtf8(); + } + setResourceClass(resourceName, shellSurface->windowClass()); setDesktopFileName(shellSurface->windowClass()); connect(shellSurface, &T::windowClassChanged, this, - [this] (const QByteArray &windowClass) { - setResourceClass(windowClass); + [this, resourceName] (const QByteArray &windowClass) { + setResourceClass(resourceName, windowClass); setDesktopFileName(windowClass); } );