diff --git a/xembed-sni-proxy/fdoselectionmanager.cpp b/xembed-sni-proxy/fdoselectionmanager.cpp --- a/xembed-sni-proxy/fdoselectionmanager.cpp +++ b/xembed-sni-proxy/fdoselectionmanager.cpp @@ -1,6 +1,7 @@ /* * Registers as a embed container * Copyright (C) 2015 David Edmundson + * Copyright (C) 2019 Konrad Materka * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,11 +23,7 @@ #include "debug.h" #include -#include -#include -#include #include -#include #include #include @@ -163,6 +160,15 @@ sniProxy->resizeWindow(event->width, event->height); } } + } else if (responseType == XCB_VISIBILITY_NOTIFY) { + const auto event = reinterpret_cast(ev); + // it's possible that something showed our container window, we have to hide it + // workaround for BUG 357443: when KWin is restarted, container window is shown on top + if (event->state == XCB_VISIBILITY_UNOBSCURED) { + for (auto sniProxy : m_proxies.values()) { + sniProxy->hideContainerWindow(event->window); + } + } } return false; @@ -197,17 +203,6 @@ 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.h b/xembed-sni-proxy/sniproxy.h --- a/xembed-sni-proxy/sniproxy.h +++ b/xembed-sni-proxy/sniproxy.h @@ -1,6 +1,7 @@ /* * Holds one embedded window, registers as DBus entry * Copyright (C) 2015 David Edmundson + * Copyright (C) 2019 Konrad Materka * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -49,8 +50,8 @@ ~SNIProxy() override; void update(); - void stackContainerWindow(const uint32_t stackMode) const; void resizeWindow(const uint16_t width, const uint16_t height) const; + void hideContainerWindow(xcb_window_t windowId) const; /** * @return the category of the application associated to this item @@ -154,13 +155,14 @@ bool isTransparentImage(const QImage &image) const; QImage convertFromNative(xcb_image_t *xcbImage) const; QPoint calculateClickPoint() const; + void stackContainerWindow(const uint32_t stackMode) const; QDBusConnection m_dbus; xcb_window_t m_windowId; xcb_window_t m_containerWid; static int s_serviceCount; QPixmap m_pixmap; - + bool sendingClickEvent; InjectMode m_injectMode; }; diff --git a/xembed-sni-proxy/sniproxy.cpp b/xembed-sni-proxy/sniproxy.cpp --- a/xembed-sni-proxy/sniproxy.cpp +++ b/xembed-sni-proxy/sniproxy.cpp @@ -1,6 +1,7 @@ /* * Holds one embedded window, registers as DBus entry * Copyright (C) 2015 David Edmundson + * Copyright (C) 2019 Konrad Materka * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -79,6 +80,7 @@ //instead lets use one DBus connection per SNI m_dbus(QDBusConnection::connectToBus(QDBusConnection::SessionBus, QStringLiteral("XembedSniProxy%1").arg(s_serviceCount++))), m_windowId(wid), + sendingClickEvent(false), m_injectMode(Direct) { //create new SNI @@ -101,8 +103,9 @@ uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; values[0] = screen->black_pixel; //draw a solid background so the embedded icon doesn't get garbage in it values[1] = true; //bypass wM - // Redirect and handle structure (size, position) requests on the embedded window. - values[2] = XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; + values[2] = XCB_EVENT_MASK_VISIBILITY_CHANGE | // receive visibility change, to handle KWin restart #357443 + // Redirect and handle structure (size, position) requests from the embedded window. + XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; xcb_create_window (c, /* connection */ XCB_COPY_FROM_PARENT, /* depth */ m_containerWid, /* window Id */ @@ -217,13 +220,6 @@ 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); -} - void SNIProxy::resizeWindow(const uint16_t width, const uint16_t height) const { auto connection = QX11Info::connection(); @@ -239,6 +235,14 @@ xcb_flush(connection); } +void SNIProxy::hideContainerWindow(xcb_window_t windowId) const +{ + if (m_containerWid == windowId && !sendingClickEvent) { + qDebug() << "Container window visible, stack below"; + stackContainerWindow(XCB_STACK_MODE_BELOW); + } +} + QSize SNIProxy::calculateClientWindowSize() const { auto c = QX11Info::connection(); @@ -432,6 +436,13 @@ return clickPoint; } +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); +} + //____________properties__________ QString SNIProxy::Category() const @@ -513,6 +524,7 @@ //ideally we should make this match the plasmoid hit area qCDebug(SNIPROXY) << "Received click" << mouseButton << "with passed x*y" << x << y; + sendingClickEvent = true; auto c = QX11Info::connection(); @@ -603,4 +615,6 @@ #ifndef VISUAL_DEBUG stackContainerWindow(XCB_STACK_MODE_BELOW); #endif + + sendingClickEvent = false; }