diff --git a/gmenu-dbusmenu-proxy/menu.cpp b/gmenu-dbusmenu-proxy/menu.cpp index 1415d1109..ac4e7a5c4 100644 --- a/gmenu-dbusmenu-proxy/menu.cpp +++ b/gmenu-dbusmenu-proxy/menu.cpp @@ -30,6 +30,8 @@ #include #include +#include + #include "dbusmenuadaptor.h" #include "../libdbusmenuqt/dbusmenushortcut_p.h" @@ -87,7 +89,7 @@ Menu::Menu(WId winId, if (ok) { m_applicationActions = actions; m_queriedApplicationActions = true; - start(); + init(); } }); @@ -95,12 +97,14 @@ Menu::Menu(WId winId, if (ok) { m_windowActions = actions; m_queriedWindowActions = true; - start(); + init(); } }); } -Menu::~Menu() +Menu::~Menu() = default; + +void Menu::cleanup() { stop(m_subscriptions); @@ -137,16 +141,18 @@ QString Menu::proxyObjectPath() const return m_proxyObjectPath; } -void Menu::start() +void Menu::init() { if (!m_queriedApplicationActions || m_queriedWindowActions) { return; } - qDebug() << "START!"; - start(0); -} + if (!registerDBusObject()) { + return; + } + emit requestWriteWindowProperties(); +} void Menu::start(uint id) { @@ -235,14 +241,6 @@ void Menu::start(uint id) } } } - - - // first time we successfully requested a menu, announce that this window supports DBusMenu - if (!m_subscriptions.isEmpty() && !wasSubscribed) { - if (registerDBusObject()) { - emit requestWriteWindowProperties(); - } - } } // When it was a delayed GetLayout request, send the reply now @@ -266,8 +264,30 @@ void Menu::start(uint id) void Menu::stop(const QList &ids) { - // TODO - Q_UNUSED(ids); + qDebug() << "STOP" << ids; + + QDBusMessage msg = QDBusMessage::createMethodCall(m_serviceName, + m_menuObjectPath, + s_orgGtkMenus, + QStringLiteral("End")); + msg.setArguments({ + QVariant::fromValue(ids) // don't let it unwrap it, hence in a variant + }); + + QDBusPendingReply reply = QDBusConnection::sessionBus().asyncCall(msg); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, ids](QDBusPendingCallWatcher *watcher) { + QDBusPendingReply reply = *watcher; + if (reply.isError()) { + qWarning() << "Failed to stop subscription to" << ids << "from" << m_serviceName << "at" << m_menuObjectPath << reply.error(); + } else { + // remove all subscriptions that we unsubscribed from + // TODO is there a nicer algorithm for that? + m_subscriptions.erase(std::remove_if(m_subscriptions.begin(), m_subscriptions.end(), + std::bind(&QList::contains, m_subscriptions, std::placeholders::_1)), + m_subscriptions.end()); + } + }); } void Menu::onMenuChanged(const GMenuChangeList &changes) diff --git a/gmenu-dbusmenu-proxy/menu.h b/gmenu-dbusmenu-proxy/menu.h index 7df81738b..83ca13115 100644 --- a/gmenu-dbusmenu-proxy/menu.h +++ b/gmenu-dbusmenu-proxy/menu.h @@ -48,6 +48,8 @@ public: const QString &menuObjectPath); ~Menu(); + void cleanup(); + WId winId() const; QString serviceName() const; @@ -83,7 +85,7 @@ private slots: void onWindowActionsChanged(const GMenuActionsChange &changes); private: - void start(); + void init(); void start(uint id); void stop(const QList &id); diff --git a/gmenu-dbusmenu-proxy/menuproxy.cpp b/gmenu-dbusmenu-proxy/menuproxy.cpp index 06e32b65e..cf3a038a0 100644 --- a/gmenu-dbusmenu-proxy/menuproxy.cpp +++ b/gmenu-dbusmenu-proxy/menuproxy.cpp @@ -164,7 +164,8 @@ void MenuProxy::onWindowAdded(WId id) void MenuProxy::onWindowRemoved(WId id) { - delete m_menus.take(id); // destructor of Menu cleans up everything + // no need to cleanup() (which removes window properties) when the window is gone, delete right away + delete m_menus.take(id); } QByteArray MenuProxy::getWindowPropertyString(WId id, const QByteArray &name)