From dd1f933e7ab38196a994012f7956d3035769b553 Mon Sep 17 00:00:00 2001
From: Konstantin <ria.freelander@gmail.com>
Date: Fri, 16 Feb 2018 03:50:48 +0300
Subject: [PATCH] Importer: Truly force toplevel items enabled.

---
 lib/dbusmenu-importer/definitions.h |  1 +
 lib/dbusmenu-importer/item.c        | 32 ++++++++++++++---------------
 lib/dbusmenu-importer/item.h        |  4 +++-
 lib/dbusmenu-importer/model.c       | 14 ++++++++++---
 4 files changed, 31 insertions(+), 20 deletions(-)

diff --git a/lib/dbusmenu-importer/definitions.h b/lib/dbusmenu-importer/definitions.h
index d796f950..cabe6c48 100644
--- a/lib/dbusmenu-importer/definitions.h
+++ b/lib/dbusmenu-importer/definitions.h
@@ -28,6 +28,7 @@
 #define HAS_ICON_NAME "has-icon-name"
 
 typedef enum {
+	DBUS_MENU_ACTION_SECTION,
 	DBUS_MENU_ACTION_NORMAL,
 	DBUS_MENU_ACTION_CHECKMARK,
 	DBUS_MENU_ACTION_RADIO,
diff --git a/lib/dbusmenu-importer/item.c b/lib/dbusmenu-importer/item.c
index 0b2edc88..34af491f 100644
--- a/lib/dbusmenu-importer/item.c
+++ b/lib/dbusmenu-importer/item.c
@@ -42,7 +42,7 @@ G_GNUC_INTERNAL DBusMenuItem *dbus_menu_item_new_first_section(u_int32_t id,
 {
 	DBusMenuItem *item = g_slice_new0(DBusMenuItem);
 	item->id           = id;
-	item->is_section   = true;
+	item->action_type  = DBUS_MENU_ACTION_SECTION;
 	item->enabled      = false;
 	item->toggled      = false;
 	item->attributes =
@@ -63,10 +63,9 @@ G_GNUC_INTERNAL DBusMenuItem *dbus_menu_item_new(u_int32_t id, DBusMenuModel *pa
 	const char *prop;
 	GVariant *value;
 	item_set_magic(item);
-	item->is_section = false;
-	item->enabled    = true;
-	item->toggled    = false;
-	item->id         = id;
+	item->enabled = true;
+	item->toggled = false;
+	item->id      = id;
 	item->attributes =
 	    g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
 	item->links =
@@ -135,7 +134,8 @@ G_GNUC_INTERNAL DBusMenuItem *dbus_menu_item_new(u_int32_t id, DBusMenuModel *pa
 			const char *type = g_variant_get_string(value, NULL);
 			if (!g_strcmp0(type, DBUS_MENU_TYPE_SEPARATOR))
 			{
-				item->is_section = true;
+				item->action_type    = DBUS_MENU_ACTION_SECTION;
+				action_creator_found = true;
 			}
 			else if (!g_strcmp0(type, DBUS_MENU_TYPE_NORMAL))
 			{
@@ -150,10 +150,11 @@ G_GNUC_INTERNAL DBusMenuItem *dbus_menu_item_new(u_int32_t id, DBusMenuModel *pa
 		}
 		else if (g_strcmp0(prop, "x-kde-title") == 0)
 		{
-			item->is_section = true;
+			item->action_type = DBUS_MENU_ACTION_SECTION;
 			g_hash_table_insert(item->attributes,
 			                    g_strdup(G_MENU_ATTRIBUTE_LABEL),
 			                    value);
+			action_creator_found = true;
 		}
 		else if (!action_creator_found)
 		{
@@ -185,7 +186,6 @@ G_GNUC_INTERNAL void dbus_menu_item_free(gpointer data)
 G_GNUC_INTERNAL DBusMenuItem *dbus_menu_item_copy(DBusMenuItem *src)
 {
 	DBusMenuItem *dst            = g_slice_new0(DBusMenuItem);
-	dst->is_section              = src->is_section;
 	dst->id                      = src->id;
 	dst->action_type             = src->action_type;
 	dst->enabled                 = src->enabled;
@@ -211,7 +211,7 @@ static bool check_and_update_mutable_attribute(DBusMenuItem *item, const char *k
 	return false;
 }
 
-static bool dbus_menu_item_update_enabled(DBusMenuItem *item, bool enabled)
+G_GNUC_INTERNAL bool dbus_menu_item_update_enabled(DBusMenuItem *item, bool enabled)
 {
 	bool updated = false;
 	if (item->action_type == DBUS_MENU_ACTION_SUBMENU && !item->toggled)
@@ -272,8 +272,6 @@ G_GNUC_INTERNAL void dbus_menu_item_preload(DBusMenuItem *item)
 		if (DBUS_MENU_IS_MODEL(submenu))
 			dbus_menu_model_update_layout(submenu);
 	}
-	dbus_menu_item_update_enabled(item, true);
-	item->toggled = true;
 }
 
 G_GNUC_INTERNAL bool dbus_menu_item_copy_attributes(DBusMenuItem *src, DBusMenuItem *dst)
@@ -427,7 +425,7 @@ G_GNUC_INTERNAL bool dbus_menu_item_update_props(DBusMenuItem *item, GVariant *p
 		else if (g_strcmp0(prop, "visible") == 0)
 		{
 			bool vis = g_variant_get_boolean(value);
-			if (item->is_section)
+			if (item->action_type == DBUS_MENU_ACTION_SECTION)
 			{
 				item->toggled = !vis;
 				continue;
@@ -554,8 +552,6 @@ G_GNUC_INTERNAL bool dbus_menu_item_compare_immutable(DBusMenuItem *a, DBusMenuI
 {
 	if (a->id != b->id)
 		return false;
-	if (a->is_section != b->is_section)
-		return false;
 	if (a->referenced_action_group != b->referenced_action_group)
 		return false;
 	if (a->action_type != b->action_type)
@@ -569,12 +565,12 @@ G_GNUC_INTERNAL void dbus_menu_item_copy_submenu(DBusMenuItem *src, DBusMenuItem
 	DBusMenuXml *xml;
 	DBusMenuModel *submenu = NULL;
 	g_object_get(parent, "xml", &xml, NULL);
-	if (dst->toggled)
-		dst->enabled = true;
 	if (src == NULL)
 	{
 		if (dst->action_type == DBUS_MENU_ACTION_SUBMENU)
 		{
+			if (dst->toggled)
+				dst->enabled = true;
 			submenu =
 			    dbus_menu_model_new(dst->id, parent, xml, dst->referenced_action_group);
 			g_hash_table_insert(dst->links,
@@ -587,6 +583,8 @@ G_GNUC_INTERNAL void dbus_menu_item_copy_submenu(DBusMenuItem *src, DBusMenuItem
 	if (dst->action_type == DBUS_MENU_ACTION_SUBMENU &&
 	    src->action_type == DBUS_MENU_ACTION_SUBMENU)
 	{
+		if (src->toggled || dst->toggled)
+			dst->enabled = dst->toggled = true;
 		submenu =
 		    DBUS_MENU_MODEL(g_hash_table_lookup(src->links,
 		                                        src->enabled ? G_MENU_LINK_SUBMENU
@@ -601,6 +599,8 @@ G_GNUC_INTERNAL void dbus_menu_item_copy_submenu(DBusMenuItem *src, DBusMenuItem
 
 G_GNUC_INTERNAL void dbus_menu_item_generate_action(DBusMenuItem *item, DBusMenuModel *parent)
 {
+	if (item->action_type == DBUS_MENU_ACTION_SECTION)
+		return;
 	DBusMenuXml *xml;
 	DBusMenuModel *submenu =
 	    g_hash_table_lookup(item->links,
diff --git a/lib/dbusmenu-importer/item.h b/lib/dbusmenu-importer/item.h
index 8aabd13b..2731dd8c 100644
--- a/lib/dbusmenu-importer/item.h
+++ b/lib/dbusmenu-importer/item.h
@@ -31,7 +31,6 @@ G_BEGIN_DECLS
 typedef struct
 {
 	u_int32_t id;
-	bool is_section;
 	GActionGroup *referenced_action_group;
 	// FIXME: Cannot have activatable submenu item.
 	GAction *referenced_action;
@@ -50,6 +49,8 @@ G_GNUC_INTERNAL DBusMenuItem *dbus_menu_item_new_first_section(u_int32_t id,
 
 G_GNUC_INTERNAL void dbus_menu_item_free(gpointer data);
 
+G_GNUC_INTERNAL bool dbus_menu_item_update_enabled(DBusMenuItem *item, bool enabled);
+
 G_GNUC_INTERNAL bool dbus_menu_item_update_props(DBusMenuItem *item, GVariant *props);
 
 G_GNUC_INTERNAL bool dbus_menu_item_remove_props(DBusMenuItem *item, GVariant *props);
@@ -62,6 +63,7 @@ G_GNUC_INTERNAL void dbus_menu_item_copy_submenu(DBusMenuItem *src, DBusMenuItem
                                                  DBusMenuModel *parent);
 
 G_GNUC_INTERNAL void dbus_menu_item_generate_action(DBusMenuItem *item, DBusMenuModel *parent);
+
 G_GNUC_INTERNAL void dbus_menu_item_preload(DBusMenuItem *item);
 
 G_GNUC_INTERNAL int dbus_menu_item_id_compare_func(const DBusMenuItem *a, gconstpointer b,
diff --git a/lib/dbusmenu-importer/model.c b/lib/dbusmenu-importer/model.c
index 25d932cc..0557b262 100644
--- a/lib/dbusmenu-importer/model.c
+++ b/lib/dbusmenu-importer/model.c
@@ -213,7 +213,7 @@ static void layout_parse(DBusMenuModel *menu, GVariant *layout)
 		DBusMenuItem *old      = NULL;
 		DBusMenuItem *new_item = dbus_menu_item_new(cid, menu, cprops);
 		// We receive a section (separator or x-kde-title)
-		if (new_item->is_section)
+		if (new_item->action_type == DBUS_MENU_ACTION_SECTION)
 		{
 			bool is_valid_section = !new_item->toggled;
 			// Section is valid, so, parse it
@@ -291,11 +291,15 @@ static void layout_parse(DBusMenuModel *menu, GVariant *layout)
 				dbus_menu_item_copy_submenu(NULL, new_item, menu);
 				dbus_menu_item_generate_action(new_item, menu);
 				if (menu->parent_id == 0)
+				{
+					dbus_menu_item_update_enabled(new_item, true);
+					new_item->toggled = true;
 					g_timeout_add_full(100,
 					                   300,
 					                   (GSourceFunc)preload_idle,
 					                   new_item,
 					                   NULL);
+				}
 				current_iter = g_sequence_insert_before(current_iter, new_item);
 				added++;
 			}
@@ -313,11 +317,15 @@ static void layout_parse(DBusMenuModel *menu, GVariant *layout)
 					dbus_menu_item_generate_action(new_item, menu);
 					// if it is root, preload submenu
 					if (menu->parent_id == 0)
+					{
+						dbus_menu_item_update_enabled(new_item, true);
+						new_item->toggled = true;
 						g_timeout_add_full(100,
 						                   300,
 						                   (GSourceFunc)preload_idle,
 						                   new_item,
 						                   NULL);
+					}
 					g_sequence_set(current_iter, new_item);
 				}
 				else
@@ -522,7 +530,7 @@ static void items_properties_updated_cb(DBusMenuXml *proxy, GVariant *updated_pr
 		if (item != NULL)
 		{
 			// It is the best what we can do to update a section
-			if (item->is_section)
+			if (item->action_type == DBUS_MENU_ACTION_SECTION)
 			{
 				//                            dbus_menu_model_update_layout(menu);
 			}
@@ -548,7 +556,7 @@ static void items_properties_updated_cb(DBusMenuXml *proxy, GVariant *updated_pr
 		if (item != NULL)
 		{
 			// It is the best what we can do to update a section
-			if (item->is_section)
+			if (item->action_type == DBUS_MENU_ACTION_SECTION)
 			{
 				//				dbus_menu_model_update_layout(menu);
 			}