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;