From ab7b6757bf323a07d950bff0d44a5db93a04cd09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Fl=C3=B6ser?= Date: Mon, 18 Sep 2017 18:37:45 +0200 Subject: [PATCH] Properly update the visible (icon) name when the caption changes Summary: It was possible that we performed an early exit when the caption changes and this results in the visible name being wrong. E.g if we have two windows called foo, the second one has the visible name "foo <2>". After changing that to "bar" the bug resulted in it still being the foo variant instead of getting cleared. BUG: 384760 FIXED-IN: 5.11.0 Test Plan: Created new test case exposing the problem Reviewers: #kwin, #plasma, hein Subscribers: plasma-devel, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D7871 --- autotests/integration/x11_client_test.cpp | 74 +++++++++++++++++++++++ client.cpp | 3 +- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/autotests/integration/x11_client_test.cpp b/autotests/integration/x11_client_test.cpp index 7ceadb4731..49187e55bd 100644 --- a/autotests/integration/x11_client_test.cpp +++ b/autotests/integration/x11_client_test.cpp @@ -52,6 +52,7 @@ private Q_SLOTS: void testX11WindowId(); void testCaptionChanges(); void testCaptionWmName(); + void testCaptionMultipleWindows(); }; void X11ClientTest::initTestCase() @@ -449,5 +450,78 @@ void X11ClientTest::testCaptionWmName() QVERIFY(glxgears.waitForFinished()); } +void X11ClientTest::testCaptionMultipleWindows() +{ + // BUG 384760 + // create first window + QScopedPointer c(xcb_connect(nullptr, nullptr)); + QVERIFY(!xcb_connection_has_error(c.data())); + const QRect windowGeometry(0, 0, 100, 200); + xcb_window_t w = xcb_generate_id(c.data()); + xcb_create_window(c.data(), XCB_COPY_FROM_PARENT, w, rootWindow(), + windowGeometry.x(), + windowGeometry.y(), + windowGeometry.width(), + windowGeometry.height(), + 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr); + xcb_size_hints_t hints; + memset(&hints, 0, sizeof(hints)); + xcb_icccm_size_hints_set_position(&hints, 1, windowGeometry.x(), windowGeometry.y()); + xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height()); + xcb_icccm_set_wm_normal_hints(c.data(), w, &hints); + NETWinInfo info(c.data(), w, kwinApp()->x11RootWindow(), NET::Properties(), NET::Properties2()); + info.setName("foo"); + xcb_map_window(c.data(), w); + xcb_flush(c.data()); + + QSignalSpy windowCreatedSpy(workspace(), &Workspace::clientAdded); + QVERIFY(windowCreatedSpy.isValid()); + QVERIFY(windowCreatedSpy.wait()); + Client *client = windowCreatedSpy.first().first().value(); + QVERIFY(client); + QCOMPARE(client->windowId(), w); + QCOMPARE(client->caption(), QStringLiteral("foo")); + + // create second window with same caption + xcb_window_t w2 = xcb_generate_id(c.data()); + xcb_create_window(c.data(), XCB_COPY_FROM_PARENT, w2, rootWindow(), + windowGeometry.x(), + windowGeometry.y(), + windowGeometry.width(), + windowGeometry.height(), + 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr); + xcb_icccm_set_wm_normal_hints(c.data(), w2, &hints); + NETWinInfo info2(c.data(), w2, kwinApp()->x11RootWindow(), NET::Properties(), NET::Properties2()); + info2.setName("foo"); + info2.setIconName("foo"); + xcb_map_window(c.data(), w2); + xcb_flush(c.data()); + + windowCreatedSpy.clear(); + QVERIFY(windowCreatedSpy.wait()); + Client *client2 = windowCreatedSpy.first().first().value(); + QVERIFY(client2); + QCOMPARE(client2->windowId(), w2); + QCOMPARE(client2->caption(), QStringLiteral("foo <2>\u200E")); + NETWinInfo info3(kwinApp()->x11Connection(), w2, kwinApp()->x11RootWindow(), NET::WMVisibleName | NET::WMVisibleIconName, NET::Properties2()); + QCOMPARE(QByteArray(info3.visibleName()), QByteArrayLiteral("foo <2>\u200E")); + QCOMPARE(QByteArray(info3.visibleIconName()), QByteArrayLiteral("foo <2>\u200E")); + + QSignalSpy captionChangedSpy(client2, &Client::captionChanged); + QVERIFY(captionChangedSpy.isValid()); + + NETWinInfo info4(c.data(), w2, kwinApp()->x11RootWindow(), NET::Properties(), NET::Properties2()); + info4.setName("foobar"); + info4.setIconName("foobar"); + xcb_map_window(c.data(), w2); + xcb_flush(c.data()); + + QVERIFY(captionChangedSpy.wait()); + QCOMPARE(client2->caption(), QStringLiteral("foobar")); + NETWinInfo info5(kwinApp()->x11Connection(), w2, kwinApp()->x11RootWindow(), NET::WMVisibleName | NET::WMVisibleIconName, NET::Properties2()); + QCOMPARE(QByteArray(info5.visibleName()), QByteArray()); + QTRY_COMPARE(QByteArray(info5.visibleIconName()), QByteArray()); +} + WAYLANDTEST_MAIN(X11ClientTest) #include "x11_client_test.moc" diff --git a/client.cpp b/client.cpp index 9c418e4597..f3432667a2 100644 --- a/client.cpp +++ b/client.cpp @@ -1447,8 +1447,9 @@ void Client::setCaption(const QString& _s, bool force) for (int i = 0; i < s.length(); ++i) if (!s[i].isPrint()) s[i] = QChar(u' '); + const bool changed = (s != cap_normal); cap_normal = s; - if (!force) { + if (!force && !changed) { emit captionChanged(); return; }