From 02bbef3b506aa4c605cee88bd39a6d88dea63f34 Mon Sep 17 00:00:00 2001 From: Konrad Materka Date: Fri, 29 Nov 2019 09:39:08 +0100 Subject: [PATCH] [XembedSNIProxy] Send all container windows to background on KWin restart Summary: For each tray icon XEmbedSNIProxy is creating container window 32x32 in size. It is black with opaque set to 0 (fully transparent when compositor is enabled). All of these container windows are stacked below all windows, so normally you can't see them. On creation all container windows are created in top-left corner. When user clicks on the tray icon, container window is moved to the click location (to handle events correctly). On KWin restart all windows are shuffled, usually KWin is able to restore ordering correctly, but for some reason not it this case. As a result black/transparent container windows are stacked above all other windows and panels. To solve that, on KWin restart, XembedSNIProxy needs to iterate over all known container windows and stack them below again. BUG: 357443 Test Plan: 1. [Optional] Disable compositor - with disable container window is black and easier to spot 2. Run any application with XEmbed system tray icon, do not click on the icon 3. Restart KWin a) Before: black/transparent rectangle in the top-left corner, reacts to mouse click b) After: no rectangle, mouse clicks work as expected Reviewers: #plasma_workspaces, #plasma, davidedmundson Reviewed By: #plasma_workspaces, #plasma, davidedmundson Subscribers: plasma-devel Tags: #plasma Differential Revision: https://phabricator.kde.org/D25603 --- xembed-sni-proxy/fdoselectionmanager.cpp | 14 +++++++++++++- xembed-sni-proxy/sniproxy.cpp | 16 ++++++++++------ xembed-sni-proxy/sniproxy.h | 1 + 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/xembed-sni-proxy/fdoselectionmanager.cpp b/xembed-sni-proxy/fdoselectionmanager.cpp index c458744b7..f740b7c39 100644 --- a/xembed-sni-proxy/fdoselectionmanager.cpp +++ b/xembed-sni-proxy/fdoselectionmanager.cpp @@ -22,9 +22,10 @@ #include "debug.h" #include +#include +#include #include #include - #include #include @@ -187,6 +188,17 @@ void FdoSelectionManager::onClaimedOwnership() qCDebug(SNIPROXY) << "Manager selection claimed"; setSystemTrayVisual(); + + // send all container windows to background on KWin restart + QDBusServiceWatcher *watcher = new QDBusServiceWatcher(QStringLiteral("org.kde.KWin"), QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration, this); + connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, [=](const QString &) { + // some delay is necesary + QTimer::singleShot(100, this, [=]() { + for (auto sniproxy : m_proxies) { + sniproxy->stackContainerWindow(XCB_STACK_MODE_BELOW); + } + }); + }); } void FdoSelectionManager::onFailedToClaimOwnership() diff --git a/xembed-sni-proxy/sniproxy.cpp b/xembed-sni-proxy/sniproxy.cpp index 102a9a622..cdb8d24df 100644 --- a/xembed-sni-proxy/sniproxy.cpp +++ b/xembed-sni-proxy/sniproxy.cpp @@ -122,8 +122,7 @@ SNIProxy::SNIProxy(xcb_window_t wid, QObject* parent): */ #ifndef VISUAL_DEBUG - const uint32_t stackBelowData[] = {XCB_STACK_MODE_BELOW}; - xcb_configure_window(c, m_containerWid, XCB_CONFIG_WINDOW_STACK_MODE, stackBelowData); + stackContainerWindow(XCB_STACK_MODE_BELOW); NETWinInfo wm(c, m_containerWid, screen->root, NET::Properties(), NET::Properties2()); wm.setOpacity(0); @@ -214,6 +213,13 @@ void SNIProxy::update() emit NewToolTip(); } +void SNIProxy::stackContainerWindow(const uint32_t stackMode) const +{ + auto c = QX11Info::connection(); + const uint32_t stackData[] = {stackMode}; + xcb_configure_window(c, m_containerWid, XCB_CONFIG_WINDOW_STACK_MODE, stackData); +} + QSize SNIProxy::calculateClientWindowSize() const { auto c = QX11Info::connection(); @@ -538,8 +544,7 @@ void SNIProxy::sendClick(uint8_t mouseButton, int x, int y) xcb_configure_window(c, m_containerWid, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, configVals); //pull window up - const uint32_t stackAboveData[] = {XCB_STACK_MODE_ABOVE}; - xcb_configure_window(c, m_containerWid, XCB_CONFIG_WINDOW_STACK_MODE, stackAboveData); + stackContainerWindow(XCB_STACK_MODE_ABOVE); //mouse down if (m_injectMode == Direct) { @@ -589,7 +594,6 @@ void SNIProxy::sendClick(uint8_t mouseButton, int x, int y) } #ifndef VISUAL_DEBUG - const uint32_t stackBelowData[] = {XCB_STACK_MODE_BELOW}; - xcb_configure_window(c, m_containerWid, XCB_CONFIG_WINDOW_STACK_MODE, stackBelowData); + stackContainerWindow(XCB_STACK_MODE_BELOW); #endif } diff --git a/xembed-sni-proxy/sniproxy.h b/xembed-sni-proxy/sniproxy.h index 0617f900b..d3f004790 100644 --- a/xembed-sni-proxy/sniproxy.h +++ b/xembed-sni-proxy/sniproxy.h @@ -49,6 +49,7 @@ public: ~SNIProxy() override; void update(); + void stackContainerWindow(const uint32_t stackMode) const; /** * @return the category of the application associated to this item