feature(sn-icon-menu):Support dynamic increase or decrease of sub-item MenuItem in the tray right-click menu and property changes

- 支持托盘右键菜单中的子项MenuItem动态增减以及属性变化

Closed #15944
This commit is contained in:
luoqing 2023-09-15 09:49:13 +08:00
parent 1143862811
commit b25b05dd44
2 changed files with 193 additions and 1 deletions

View File

@ -0,0 +1,188 @@
From c7bc43571acc57546cd732e3658be86d308f0256 Mon Sep 17 00:00:00 2001
From: luoqing <luoqing@kylinsec.com.cn>
Date: Thu, 14 Sep 2023 17:34:29 +0800
Subject: [PATCH] feature(sn-icon-menu):Support dynamic increase or decrease of
sub-item MenuItem in the tray right-click menu and property changes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 支持托盘右键菜单中的子项MenuItem动态增减以及属性变化
Closed #15944
---
src/tray/kiran-sn-icon-menu.c | 126 +++++++++++++++++++++++++++++-----
1 file changed, 109 insertions(+), 17 deletions(-)
diff --git a/src/tray/kiran-sn-icon-menu.c b/src/tray/kiran-sn-icon-menu.c
index 22e321f..ffae1bb 100644
--- a/src/tray/kiran-sn-icon-menu.c
+++ b/src/tray/kiran-sn-icon-menu.c
@@ -1,19 +1,20 @@
/**
- * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd.
+ * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd.
* kiran-cc-daemon is licensed under Mulan PSL v2.
- * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
- * http://license.coscl.org.cn/MulanPSL2
- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
- * See the Mulan PSL v2 for more details.
- *
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ *
* Author: wangxiaoqing <wangxiaoqing@kylinos.com.cn>
*/
#include "kiran-sn-icon-menu.h"
#include <libdbusmenu-glib/dbusmenu-glib.h>
+#include <libdbusmenu-glib/menuitem.h>
struct _KiranSnIconMenuPrivate
{
gchar *bus_name;
@@ -30,6 +31,7 @@ enum
LAST_PROP
};
+#define DATA_KEY_SIGNAL_PROPERTY_CHANGED_IS_CONNECTED "signal_property_changed_is_connected"
static GParamSpec *properties[LAST_PROP] = {NULL};
G_DEFINE_TYPE_WITH_PRIVATE(KiranSnIconMenu, kiran_sn_icon_menu, GTK_TYPE_MENU)
@@ -175,6 +177,88 @@ create_widget_from_menuitem(DbusmenuMenuitem *item)
return gmi;
}
+static void
+kiran_sn_icon_menu_create_widget_from_dbusmenuitem(KiranSnIconMenu *menu, DbusmenuMenuitem *item)
+{
+ GtkWidget *gmi = create_widget_from_menuitem(item);
+
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), gmi);
+ gtk_widget_show(gmi);
+
+ g_signal_connect(gmi,
+ "activate",
+ G_CALLBACK(activate_cb),
+ item);
+}
+
+static void
+kiran_sn_icon_menu_remove_widget_all(KiranSnIconMenu *menu)
+{
+ GList *child;
+ GList *container_children = gtk_container_get_children(GTK_CONTAINER(menu));
+ for (child = container_children; child; child = child->next)
+ {
+ gtk_container_remove(GTK_CONTAINER(menu), GTK_WIDGET(child->data));
+ gtk_widget_destroy(GTK_WIDGET(child->data));
+ }
+}
+
+static void
+property_changed_cb(DbusmenuMenuitem *item, gchar *property, GVariant *value, gpointer user_data)
+{
+ GList *child;
+ KiranSnIconMenu *menu = KIRAN_SN_ICON_MENU(user_data);
+
+ kiran_sn_icon_menu_remove_widget_all(menu);
+
+ // 遍历MenuItem以找到root
+ DbusmenuMenuitem *root = dbusmenu_menuitem_get_parent(item);
+ gboolean is_root = dbusmenu_menuitem_get_root(root);
+
+ while (!is_root)
+ {
+ root = dbusmenu_menuitem_get_parent(root);
+ is_root = dbusmenu_menuitem_get_root(root);
+ }
+
+ GList *dbus_menuitem_children = dbusmenu_menuitem_get_children(root);
+ for (child = dbus_menuitem_children; child; child = child->next)
+ {
+ kiran_sn_icon_menu_create_widget_from_dbusmenuitem(menu,child->data);
+ }
+}
+
+static void
+submenu_get_children_to_connect(DbusmenuMenuitem *submenu, gpointer user_data)
+{
+ KiranSnIconMenu *menu = KIRAN_SN_ICON_MENU(user_data);
+ GList *submenu_children = dbusmenu_menuitem_get_children(submenu);
+ GList *submenu_child;
+ for (submenu_child = submenu_children; submenu_child; submenu_child = submenu_child->next)
+ {
+ const gchar *children_display = dbusmenu_menuitem_property_get(submenu_child->data, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY);
+ if (g_strcmp0(children_display, "submenu") == 0)
+ {
+ submenu_get_children_to_connect(submenu_child->data, menu);
+ }
+
+ gboolean is_connected = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(submenu_child->data), DATA_KEY_SIGNAL_PROPERTY_CHANGED_IS_CONNECTED));
+ if (!is_connected)
+ {
+ g_signal_connect(submenu_child->data, DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(property_changed_cb), menu);
+ g_object_set_data(G_OBJECT(submenu_child->data), DATA_KEY_SIGNAL_PROPERTY_CHANGED_IS_CONNECTED, GINT_TO_POINTER(TRUE));
+ }
+ }
+}
+
+/**
+ * NOTE:
+ * dbus_menuitem 移除某个menuitem时没有类似REMOVE_MENUITEM的信号
+ * 而是会触发 DBUSMENU_CLIENT_SIGNAL_LAYOUT_UPDATED 信号。
+ * 新增时会触发 DBUSMENU_CLIENT_SIGNAL_NEW_MENUITEM 信号
+ *
+ * 因此layout_updated_cb中还会处理menuitem变化的情况
+ */
static void
layout_updated_cb(DbusmenuClient *client,
gpointer user_data)
@@ -182,21 +266,29 @@ layout_updated_cb(DbusmenuClient *client,
KiranSnIconMenu *menu;
DbusmenuMenuitem *root = dbusmenu_client_get_root(client);
GList *child;
- GList *children = dbusmenu_menuitem_get_children(root);
menu = KIRAN_SN_ICON_MENU(user_data);
- for (child = children; child; child = child->next)
+ kiran_sn_icon_menu_remove_widget_all(menu);
+
+ GList *dbus_menuitem_children = dbusmenu_menuitem_get_children(root);
+ for (child = dbus_menuitem_children; child; child = child->next)
{
- GtkWidget *gmi = create_widget_from_menuitem(child->data);
+ kiran_sn_icon_menu_create_widget_from_dbusmenuitem(menu,child->data);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), gmi);
- gtk_widget_show(gmi);
+ // NOTE:只修改一个属性,可能会触发多个 PROPERTY_CHANGE 信号
+ const gchar *children_display = dbusmenu_menuitem_property_get(child->data, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY);
+ if (g_strcmp0(children_display, "submenu") == 0)
+ {
+ submenu_get_children_to_connect(child->data, menu);
+ }
- g_signal_connect(gmi,
- "activate",
- G_CALLBACK(activate_cb),
- child->data);
+ gboolean is_connected = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(child->data), DATA_KEY_SIGNAL_PROPERTY_CHANGED_IS_CONNECTED));
+ if (!is_connected)
+ {
+ g_signal_connect(child->data, DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(property_changed_cb), menu);
+ g_object_set_data(G_OBJECT(child->data), DATA_KEY_SIGNAL_PROPERTY_CHANGED_IS_CONNECTED, GINT_TO_POINTER(TRUE));
+ }
}
}
--
2.33.0

View File

@ -1,6 +1,6 @@
Name: kiran-menu
Version: 2.5.1
Release: 3
Release: 4
Summary: Applets for mate panel from Kiran Desktop
License: MulanPSL-2.0
@ -9,6 +9,7 @@ Source0: %{name}-%{version}.tar.gz
Patch0001: 0001-fix-coredump-Fix-crash-when-clicking-on-the-power-op.patch
Patch0002: 0002-fix-tray-Place-all-tray-icons-in-the-panel-and-no-lo.patch
Patch0003: 0003-fix-tray-Fixed-a-crash-issue-that-occurred-when-the-.patch
Patch0004: 0004-feature-sn-icon-menu-Support-dynamic-increase-or-dec.patch
BuildRequires: cmake > 3.0
BuildRequires: gcc-c++
@ -100,6 +101,9 @@ gtk-update-icon-cache -f /usr/share/icons/hicolor/
%changelog
* Fri Sep 15 2023 luoqing <luoqing@kylinsec.com.cn> - 2.5.1-4
- KYOS-F: Support dynamic increase or decrease of sub-item MenuItem in the tray right-click menu and property changes (#15944)
* Fri Sep 01 2023 luoqing <luoqing@kylinsec.com.cn> - 2.5.1-3
- KYOS-F: Place all tray icons in the panel and no longer in the tray container for the time being (#12490)
- KYOS-F: Fixed a crash issue that occurred when the tray icon was removed from the tray area (#14004)