From c87230c3a5feb6b31938189bd3dd69eaee490def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Fl=C3=B6ser?= Date: Tue, 1 Aug 2017 21:28:36 +0200 Subject: [PATCH] Use xcb-icccm to read the name property Summary: The KWindowSystem call which we used doesn't work on Wayland as it's only implemented in the xcb variant and cannot be made available for Wayland in an easy way as it is still XLib based. This change turns the optional XCB-ICCCM dependency in a required one and thus can use the functionality provided by said library to implement what KWindowSystem provided. BUG: 382789 Test Plan: New test case which failed with old code Reviewers: #kwin, #plasma Subscribers: plasma-devel, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D7046 --- CMakeLists.txt | 2 +- autotests/integration/x11_client_test.cpp | 23 +++++++++++++++++++++ client.cpp | 25 ++++++++++++++++++++--- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f8e31a2ea..4860c20c56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -233,7 +233,6 @@ find_package(XCB 1.10 SHM GLX CURSOR - OPTIONAL_COMPONENTS ICCCM ) set_package_properties(XCB PROPERTIES TYPE REQUIRED) @@ -570,6 +569,7 @@ set(kwin_XCB_LIBS XCB::KEYSYMS XCB::SHM XCB::GLX + XCB::ICCCM ) set(kwin_WAYLAND_LIBS diff --git a/autotests/integration/x11_client_test.cpp b/autotests/integration/x11_client_test.cpp index bb5af38c12..c5040c00f1 100644 --- a/autotests/integration/x11_client_test.cpp +++ b/autotests/integration/x11_client_test.cpp @@ -52,6 +52,7 @@ private Q_SLOTS: void testFocusInWithWaylandLastActiveWindow(); void testX11WindowId(); void testCaptionChanges(); + void testCaptionWmName(); }; void X11ClientTest::initTestCase() @@ -427,5 +428,27 @@ void X11ClientTest::testCaptionChanges() c.reset(); } +void X11ClientTest::testCaptionWmName() +{ + // this test verifies that a caption set through WM_NAME is read correctly + + // open glxgears as that one only uses WM_NAME + QSignalSpy clientAddedSpy(workspace(), &Workspace::clientAdded); + QVERIFY(clientAddedSpy.isValid()); + + QProcess glxgears; + glxgears.start(QStringLiteral("glxgears")); + QVERIFY(glxgears.waitForStarted()); + + QVERIFY(clientAddedSpy.wait()); + QCOMPARE(clientAddedSpy.count(), 1); + QCOMPARE(workspace()->clientList().count(), 1); + Client *glxgearsClient = workspace()->clientList().first(); + QCOMPARE(glxgearsClient->caption(), QStringLiteral("glxgears")); + + glxgears.terminate(); + QVERIFY(glxgears.waitForFinished()); +} + WAYLANDTEST_MAIN(X11ClientTest) #include "x11_client_test.moc" diff --git a/client.cpp b/client.cpp index 3dd7fd87f9..8b8f32e18e 100644 --- a/client.cpp +++ b/client.cpp @@ -52,6 +52,7 @@ along with this program. If not, see . // XLib #include #include +#include // system #include #include @@ -1411,12 +1412,30 @@ void Client::fetchName() setCaption(readName()); } +static inline QString readNameProperty(xcb_window_t w, xcb_atom_t atom) +{ + const auto cookie = xcb_icccm_get_text_property_unchecked(connection(), w, atom); + xcb_icccm_get_text_property_reply_t reply; + if (xcb_icccm_get_wm_name_reply(connection(), cookie, &reply, nullptr)) { + QString retVal; + if (reply.encoding == atoms->utf8_string) { + retVal = QString::fromUtf8(QByteArray(reply.name, reply.name_len)); + } else if (reply.encoding == XCB_ATOM_STRING) { + retVal = QString::fromLocal8Bit(QByteArray(reply.name, reply.name_len)); + } + xcb_icccm_get_text_property_reply_wipe(&reply); + return retVal.simplified(); + } + return QString(); +} + QString Client::readName() const { if (info->name() && info->name()[0] != '\0') return QString::fromUtf8(info->name()).simplified(); - else - return KWindowSystem::readNameProperty(window(), XCB_ATOM_WM_NAME).simplified(); + else { + return readNameProperty(window(), XCB_ATOM_WM_NAME); + } } // The list is taken from http://www.unicode.org/reports/tr9/ (#154840) @@ -1487,7 +1506,7 @@ void Client::fetchIconicName() if (info->iconName() && info->iconName()[0] != '\0') s = QString::fromUtf8(info->iconName()); else - s = KWindowSystem::readNameProperty(window(), XCB_ATOM_WM_ICON_NAME); + s = readNameProperty(window(), XCB_ATOM_WM_ICON_NAME); if (s != cap_iconic) { bool was_set = !cap_iconic.isEmpty(); cap_iconic = s;