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
icc-effect-5.14.5
Martin Flöser 2018-03-04 17:05:46 +01:00
parent 1a7a3b98ee
commit ab18007d2a
2 changed files with 15 additions and 3 deletions

View File

@ -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());

View File

@ -51,6 +51,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <KDesktopFile>
#include <QFileInfo>
#include <QOpenGLFramebufferObject>
#include <QWindow>
@ -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);
}
);