[PATCH] applets/appmenu: Fix displaying menu of the previous active window
authorVlad Zahorodnii <vlad.zahorodnii@kde.org>
Fri, 18 Apr 2025 19:39:46 +0000 (22:39 +0300)
committerAurélien COUDERC <coucouf@debian.org>
Tue, 20 May 2025 06:31:26 +0000 (08:31 +0200)
We need to break the DBusMenuImporter::menuUpdated() signal connection
when the active window changes. Otherwise, it's possible that the
menuUpdated signal will be emitted and the menu will be marked as
available.

BUG: 473714

Gbp-Pq: Name upstream_73875471_applets-appmenu-Fix-displaying-menu-of-the-previous-active-window.patch

applets/appmenu/plugin/appmenumodel.cpp

index 04834b6fab6859a70b05eb0ebabb4bf716bbd96c..db3b351405fc8ce2d31157b4d19306c3689cf87a 100644 (file)
@@ -202,16 +202,7 @@ void AppMenuModel::onActiveWindowChanged()
     const QModelIndex activeTaskIndex = m_tasksModel->activeTask();
     const QString objectPath = m_tasksModel->data(activeTaskIndex, TaskManager::AbstractTasksModel::ApplicationMenuObjectPath).toString();
     const QString serviceName = m_tasksModel->data(activeTaskIndex, TaskManager::AbstractTasksModel::ApplicationMenuServiceName).toString();
-
-    if (!objectPath.isEmpty() && !serviceName.isEmpty()) {
-        setMenuAvailable(true);
-        updateApplicationMenu(serviceName, objectPath);
-        setVisible(true);
-        Q_EMIT modelNeedsUpdate();
-    } else {
-        setMenuAvailable(false);
-        setVisible(false);
-    }
+    updateApplicationMenu(serviceName, objectPath);
 }
 
 QHash<int, QByteArray> AppMenuModel::roleNames() const
@@ -282,61 +273,81 @@ void AppMenuModel::updateApplicationMenu(const QString &serviceName, const QStri
         return;
     }
 
-    m_serviceName = serviceName;
-    m_serviceWatcher->setWatchedServices(QStringList({m_serviceName}));
-
-    m_menuObjectPath = menuObjectPath;
+    if (serviceName.isEmpty() || menuObjectPath.isEmpty()) {
+        setMenuAvailable(false);
+        setVisible(false);
 
-    if (m_importer) {
-        m_importer->deleteLater();
-    }
+        m_serviceName = QString();
+        m_menuObjectPath = QString();
+        m_serviceWatcher->setWatchedServices({});
 
-    m_importer = new KDBusMenuImporter(serviceName, menuObjectPath, this);
-    QMetaObject::invokeMethod(m_importer, "updateMenu", Qt::QueuedConnection);
+        if (m_importer) {
+            m_importer->disconnect(this);
+            m_importer->deleteLater();
+            m_importer = nullptr;
+        }
+    } else {
+        m_serviceName = serviceName;
+        m_menuObjectPath = menuObjectPath;
+        m_serviceWatcher->setWatchedServices(QStringList({m_serviceName}));
 
-    connect(m_importer.data(), &DBusMenuImporter::menuUpdated, this, [=, this](QMenu *menu) {
-        m_menu = m_importer->menu();
-        if (m_menu.isNull() || menu != m_menu) {
-            return;
+        if (m_importer) {
+            m_importer->disconnect(this);
+            m_importer->deleteLater();
         }
 
-        // cache first layer of sub menus, which we'll be popping up
-        const auto actions = m_menu->actions();
-        for (QAction *a : actions) {
-            // signal dataChanged when the action changes
-            connect(a, &QAction::changed, this, [this, a] {
-                if (m_menuAvailable && m_menu) {
-                    const int actionIdx = m_menu->actions().indexOf(a);
-                    if (actionIdx > -1) {
-                        const QModelIndex modelIdx = index(actionIdx, 0);
-                        Q_EMIT dataChanged(modelIdx, modelIdx);
+        m_importer = new KDBusMenuImporter(serviceName, menuObjectPath, this);
+        QMetaObject::invokeMethod(m_importer, "updateMenu", Qt::QueuedConnection);
+
+        connect(m_importer.data(), &DBusMenuImporter::menuUpdated, this, [=, this](QMenu *menu) {
+            m_menu = m_importer->menu();
+            if (m_menu.isNull() || menu != m_menu) {
+                return;
+            }
+
+            // cache first layer of sub menus, which we'll be popping up
+            const auto actions = m_menu->actions();
+            for (QAction *a : actions) {
+                // signal dataChanged when the action changes
+                connect(a, &QAction::changed, this, [this, a] {
+                    if (m_menuAvailable && m_menu) {
+                        const int actionIdx = m_menu->actions().indexOf(a);
+                        if (actionIdx > -1) {
+                            const QModelIndex modelIdx = index(actionIdx, 0);
+                            Q_EMIT dataChanged(modelIdx, modelIdx);
+                        }
                     }
+                });
+
+                connect(a, &QAction::destroyed, this, &AppMenuModel::modelNeedsUpdate);
+
+                if (a->menu()) {
+                    m_importer->updateMenu(a->menu());
                 }
-            });
+            }
 
-            connect(a, &QAction::destroyed, this, &AppMenuModel::modelNeedsUpdate);
+            setMenuAvailable(true);
+            Q_EMIT modelNeedsUpdate();
+        });
 
-            if (a->menu()) {
-                m_importer->updateMenu(a->menu());
+        connect(m_importer.data(), &DBusMenuImporter::actionActivationRequested, this, [this](QAction *action) {
+            // TODO submenus
+            if (!m_menuAvailable || !m_menu) {
+                return;
             }
-        }
 
-        setMenuAvailable(true);
-        Q_EMIT modelNeedsUpdate();
-    });
+            const auto actions = m_menu->actions();
+            auto it = std::find(actions.begin(), actions.end(), action);
+            if (it != actions.end()) {
+                Q_EMIT requestActivateIndex(it - actions.begin());
+            }
+        });
 
-    connect(m_importer.data(), &DBusMenuImporter::actionActivationRequested, this, [this](QAction *action) {
-        // TODO submenus
-        if (!m_menuAvailable || !m_menu) {
-            return;
-        }
+        setMenuAvailable(true);
+        setVisible(true);
 
-        const auto actions = m_menu->actions();
-        auto it = std::find(actions.begin(), actions.end(), action);
-        if (it != actions.end()) {
-            Q_EMIT requestActivateIndex(it - actions.begin());
-        }
-    });
+        Q_EMIT modelNeedsUpdate();
+    }
 }
 
 #include "moc_appmenumodel.cpp"