From 9ea7d82a148302d176af5fb2ffba7d690a24bf2e Mon Sep 17 00:00:00 2001
From: Alexander Schwinn <alexxcons@xfce.org>
Date: Sat, 16 May 2020 23:01:25 +0200
Subject: [PATCH] re-introduce support for thunarx (Issue #293)

---
 thunar/Makefile.am             |   2 -
 thunar/thunar-dnd.c            |   4 +-
 thunar/thunar-gtk-extensions.c |  60 ++++++++++
 thunar/thunar-gtk-extensions.h |   2 +
 thunar/thunar-launcher.c       | 126 +++++++++++++++++++++
 thunar/thunar-launcher.h       |   4 +
 thunar/thunar-menu-util.c      | 185 ------------------------------
 thunar/thunar-menu-util.h      |  39 -------
 thunar/thunar-menu.c           |   3 +-
 thunar/thunar-renamer-dialog.c |  47 ++------
 thunar/thunar-shortcuts-view.c |   4 +-
 thunar/thunar-tree-view.c      |   4 +-
 thunar/thunar-window.c         | 198 +++++----------------------------
 13 files changed, 237 insertions(+), 441 deletions(-)
 delete mode 100644 thunar/thunar-menu-util.c
 delete mode 100644 thunar/thunar-menu-util.h

diff --git a/thunar/Makefile.am b/thunar/Makefile.am
index d146a55dc..324e08041 100644
--- a/thunar/Makefile.am
+++ b/thunar/Makefile.am
@@ -140,8 +140,6 @@ thunar_SOURCES =							\
 	thunar-location-entry.h						\
 	thunar-menu.c							\
 	thunar-menu.h							\
-	thunar-menu-util.c						\
-	thunar-menu-util.h						\
 	thunar-notify.c							\
 	thunar-notify.h							\
 	thunar-navigator.c						\
diff --git a/thunar/thunar-dnd.c b/thunar/thunar-dnd.c
index fdb54ef49..92d7276dc 100644
--- a/thunar/thunar-dnd.c
+++ b/thunar/thunar-dnd.c
@@ -29,7 +29,6 @@
 #include <thunar/thunar-dialogs.h>
 #include <thunar/thunar-dnd.h>
 #include <thunar/thunar-gtk-extensions.h>
-#include <thunar/thunar-menu-util.h>
 #include <thunar/thunar-private.h>
 
 
@@ -154,7 +153,8 @@ G_GNUC_END_IGNORE_DEPRECATIONS
           if (G_UNLIKELY (items != NULL))
             {
               /* add menu items for all items */
-              thunar_menu_util_add_items_to_menu (menu, items);
+              for (lp = items; lp != NULL; lp = lp->next)
+                thunar_gtk_menu_thunarx_menu_item_new (lp->data, GTK_MENU_SHELL (menu));
               g_list_free (items);
 
               /* append another separator */
diff --git a/thunar/thunar-gtk-extensions.c b/thunar/thunar-gtk-extensions.c
index 541c1e67e..fb617b5f1 100644
--- a/thunar/thunar-gtk-extensions.c
+++ b/thunar/thunar-gtk-extensions.c
@@ -31,6 +31,7 @@
 #include <thunar/thunar-private.h>
 #include <thunar/thunar-util.h>
 
+#include <thunarx/thunarx.h>
 
 #include <libxfce4ui/libxfce4ui.h>
 
@@ -98,6 +99,65 @@ thunar_gtk_label_set_a11y_relation (GtkLabel  *label,
 
 
 
+/**
+ * thunar_gtk_menu_thunarx_menu_item_new:
+ * @thunarx_menu_item   : a #ThunarxMenuItem
+ * @menu_to_append_item : #GtkMenuShell on which the item should be appended, or NULL
+ *
+ * method to create a #GtkMenuItem from a #ThunarxMenuItem and append it to the passed #GtkMenuShell
+ * This method will as well add all sub-items in case the passed #ThunarxMenuItem is a submenu
+ *
+ * Return value: (transfer full): The new #GtkImageMenuItem.
+ **/
+GtkWidget*
+thunar_gtk_menu_thunarx_menu_item_new (GObject      *thunarx_menu_item,
+                                       GtkMenuShell *menu_to_append_item)
+{
+  gchar        *name, *label_text, *tooltip_text, *icon_name, *accel_path;
+  gboolean      sensitive;
+  GtkWidget    *gtk_menu_item;
+  ThunarxMenu  *thunarx_menu;
+  GList        *children;
+  GList        *lp;
+  GtkWidget    *submenu;
+
+  g_return_val_if_fail (THUNARX_IS_MENU_ITEM (thunarx_menu_item), NULL);
+
+  g_object_get (G_OBJECT (thunarx_menu_item),
+                "name", &name,
+                "label", &label_text,
+                "tooltip", &tooltip_text,
+                "icon", &icon_name,
+                "sensitive", &sensitive,
+                "menu", &thunarx_menu,
+                NULL);
+
+  accel_path = g_strconcat ("<Actions>/ThunarActions/", name, NULL);
+  gtk_menu_item = xfce_gtk_image_menu_item_new_from_icon_name (label_text, tooltip_text, accel_path,
+                                                               G_CALLBACK (thunarx_menu_item_activate),
+                                                               G_OBJECT (thunarx_menu_item), icon_name, menu_to_append_item);
+
+  /* recursively add submenu items if any */
+  if (gtk_menu_item != NULL && thunarx_menu != NULL)
+  {
+    children = thunarx_menu_get_items (thunarx_menu);
+    submenu = gtk_menu_new ();
+    for (lp = children; lp != NULL; lp = lp->next)
+      thunar_gtk_menu_thunarx_menu_item_new (lp->data, GTK_MENU_SHELL (submenu));
+    gtk_menu_item_set_submenu (GTK_MENU_ITEM (gtk_menu_item), submenu);
+    thunarx_menu_item_list_free (children);
+  }
+  g_free (name);
+  g_free (accel_path);
+  g_free (label_text);
+  g_free (tooltip_text);
+  g_free (icon_name);
+
+  return gtk_menu_item;
+}
+
+
+
 /**
  * thunar_gtk_menu_run:
  * @menu : a #GtkMenu.
diff --git a/thunar/thunar-gtk-extensions.h b/thunar/thunar-gtk-extensions.h
index b92e5361f..f0bc0f344 100644
--- a/thunar/thunar-gtk-extensions.h
+++ b/thunar/thunar-gtk-extensions.h
@@ -37,6 +37,8 @@ void             thunar_gtk_menu_run_at_event                 (GtkMenu
 void             thunar_gtk_widget_set_tooltip                (GtkWidget          *widget,
                                                                const gchar        *format,
                                                                ...) G_GNUC_PRINTF (2, 3);
+GtkWidget       *thunar_gtk_menu_thunarx_menu_item_new        (GObject            *thunarx_menu_item,
+                                                               GtkMenuShell       *menu_to_append_item);
 
 GMountOperation *thunar_gtk_mount_operation_new               (gpointer            parent);
 
diff --git a/thunar/thunar-launcher.c b/thunar/thunar-launcher.c
index 4210d3487..e42975b4b 100644
--- a/thunar/thunar-launcher.c
+++ b/thunar/thunar-launcher.c
@@ -1887,6 +1887,132 @@ thunar_launcher_action_duplicate (ThunarLauncher *launcher)
 
 
 
+/**
+ * thunar_launcher_append_custom_actions:
+ * @launcher : a #ThunarLauncher instance
+ * @menu : #GtkMenuShell on which the custom actions should be appended
+ *
+ * Will append all custom actions which match the file-type to the provided #GtkMenuShell
+ *
+ * Return value: TRUE if any custom action was added
+ **/
+gboolean
+thunar_launcher_append_custom_actions (ThunarLauncher *launcher,
+                                       GtkMenuShell   *menu)
+{
+  gboolean                uca_added = FALSE;
+  GtkWidget              *window;
+  GtkWidget              *gtk_menu_item;
+  ThunarxProviderFactory *provider_factory;
+  GList                  *providers;
+  GList                  *thunarx_menu_items = NULL;
+  GList                  *lp_provider;
+  GList                  *lp_item;
+
+  _thunar_return_val_if_fail (THUNAR_IS_LAUNCHER (launcher), FALSE);
+  _thunar_return_val_if_fail (GTK_IS_MENU (menu), FALSE);
+
+  /* determine the toplevel window we belong to */
+  window = gtk_widget_get_toplevel (launcher->widget);
+
+  /* load the menu providers from the provider factory */
+  provider_factory = thunarx_provider_factory_get_default ();
+  providers = thunarx_provider_factory_list_providers (provider_factory, THUNARX_TYPE_MENU_PROVIDER);
+  g_object_unref (provider_factory);
+
+  if (G_UNLIKELY (providers == NULL))
+    return FALSE;
+
+  /* This may occur when the thunar-window is build */
+  if (G_UNLIKELY (launcher->selected_files == NULL))
+    return FALSE;
+
+  /* load the menu items offered by the menu providers */
+  for (lp_provider = providers; lp_provider != NULL; lp_provider = lp_provider->next)
+    {
+
+      if (launcher->single_folder_selected)
+        {
+          if (thunar_file_is_directory (launcher->single_folder))
+            thunarx_menu_items = thunarx_menu_provider_get_folder_menu_items (lp_provider->data, window, THUNARX_FILE_INFO (launcher->single_folder));
+        }
+      else
+        thunarx_menu_items = thunarx_menu_provider_get_file_menu_items (lp_provider->data, window, launcher->selected_files);
+      for (lp_item = thunarx_menu_items; lp_item != NULL; lp_item = lp_item->next)
+        {
+          gtk_menu_item = thunar_gtk_menu_thunarx_menu_item_new (lp_item->data, menu);
+
+          /* Each thunarx_menu_item will be destroyed together with its related gtk_menu_item*/
+          g_signal_connect_swapped (G_OBJECT (gtk_menu_item), "destroy", G_CALLBACK (g_object_unref), lp_item->data);
+          uca_added = TRUE;
+        }
+      g_list_free (thunarx_menu_items);
+    }
+  g_list_free_full (providers, g_object_unref);
+  return uca_added;
+}
+
+
+
+gboolean
+thunar_launcher_check_uca_key_activation (ThunarLauncher *launcher,
+                                          GdkEventKey    *key_event)
+{
+  GtkWidget              *window;
+  ThunarxProviderFactory *provider_factory;
+  GList                  *providers;
+  GList                  *thunarx_menu_items = NULL;
+  GList                  *lp_provider;
+  GList                  *lp_item;
+  GtkAccelKey             uca_key;
+  gchar                  *name, *accel_path;
+  gboolean                uca_activated = FALSE;
+
+  /* determine the toplevel window we belong to */
+  window = gtk_widget_get_toplevel (launcher->widget);
+
+  /* load the menu providers from the provider factory */
+  provider_factory = thunarx_provider_factory_get_default ();
+  providers = thunarx_provider_factory_list_providers (provider_factory, THUNARX_TYPE_MENU_PROVIDER);
+  g_object_unref (provider_factory);
+
+  if (G_UNLIKELY (providers == NULL))
+    return uca_activated;
+
+  /* load the menu items offered by the menu providers */
+  for (lp_provider = providers; lp_provider != NULL; lp_provider = lp_provider->next)
+    {
+      if (launcher->single_folder_selected)
+        thunarx_menu_items = thunarx_menu_provider_get_folder_menu_items (lp_provider->data, window, THUNARX_FILE_INFO (launcher->single_folder));
+      else
+        thunarx_menu_items = thunarx_menu_provider_get_file_menu_items (lp_provider->data, window, launcher->selected_files);
+      for (lp_item = thunarx_menu_items; lp_item != NULL; lp_item = lp_item->next)
+        {
+          g_object_get (G_OBJECT (lp_item->data), "name", &name, NULL);
+          accel_path = g_strconcat ("<Actions>/ThunarActions/", name, NULL);
+          if (gtk_accel_map_lookup_entry (accel_path, &uca_key) == TRUE)
+            {
+              if (g_ascii_tolower (key_event->keyval) == g_ascii_tolower (uca_key.accel_key))
+                {
+                  if ((key_event->state & gtk_accelerator_get_default_mod_mask ()) == uca_key.accel_mods)
+                    {
+                      thunarx_menu_item_activate (lp_item->data);
+                      uca_activated = TRUE;
+                    }
+                }
+            }
+          g_free (name);
+          g_free (accel_path);
+          g_object_unref (lp_item->data);
+        }
+      g_list_free (thunarx_menu_items);
+    }
+  g_list_free_full (providers, g_object_unref);
+  return uca_activated;
+}
+
+
+
 static void
 thunar_launcher_rename_error (ExoJob    *job,
                               GError    *error,
diff --git a/thunar/thunar-launcher.h b/thunar/thunar-launcher.h
index bd5cdc36d..10820d05d 100644
--- a/thunar/thunar-launcher.h
+++ b/thunar/thunar-launcher.h
@@ -90,6 +90,10 @@ gboolean        thunar_launcher_append_open_section                  (ThunarLaun
                                                                       gboolean                        support_tabs,
                                                                       gboolean                        support_change_directory,
                                                                       gboolean                        force);
+gboolean        thunar_launcher_append_custom_actions                (ThunarLauncher                 *launcher,
+                                                                      GtkMenuShell                   *menu);
+gboolean        thunar_launcher_check_uca_key_activation             (ThunarLauncher                 *launcher,
+                                                                      GdkEventKey                    *key_event);
 G_END_DECLS;
 
 #endif /* !__THUNAR_LAUNCHER_H__ */
diff --git a/thunar/thunar-menu-util.c b/thunar/thunar-menu-util.c
deleted file mode 100644
index 5caacc416..000000000
--- a/thunar/thunar-menu-util.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/* vi:set et ai sw=2 sts=2 ts=2: */
-/*-
- * Copyright (c) 2017 Andre Miranda <andreldm@xfce.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include <thunar/thunar-menu-util.h>
-
-#include <thunarx/thunarx.h>
-
-
-
-static void
-extension_action_callback (GtkAction *action,
-                           gpointer callback_data)
-{
-  thunarx_menu_item_activate (THUNARX_MENU_ITEM (callback_data));
-}
-
-
-
-static GtkAction *
-action_from_menu_item (GObject *item)
-{
-  gchar *name, *label, *tooltip, *icon_str;
-  gboolean  sensitive, priority;
-  GtkAction *action;
-
-  g_return_val_if_fail (THUNARX_IS_MENU_ITEM (item), NULL);
-
-  g_object_get (G_OBJECT (item),
-                "name", &name,
-                "label", &label,
-                "tooltip", &tooltip,
-                "icon", &icon_str,
-                "sensitive", &sensitive,
-                "priority", &priority,
-                NULL);
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-  action = gtk_action_new (name, label, tooltip, NULL);
-
-  if (icon_str != NULL)
-    {
-      GIcon *icon = g_icon_new_for_string (icon_str, NULL);
-
-      if (icon)
-        {
-          gtk_action_set_gicon (action, icon);
-          g_object_unref (icon);
-        }
-    }
-
-  gtk_action_set_sensitive (action, sensitive);
-G_GNUC_END_IGNORE_DEPRECATIONS
-  g_object_set (action, "is-important", priority, NULL);
-
-  g_signal_connect_data (action, "activate",
-                         G_CALLBACK (extension_action_callback),
-                         g_object_ref (item),
-                         (GClosureNotify) (void (*)(void)) g_object_unref, 0);
-
-  g_free (name);
-  g_free (label);
-  g_free (tooltip);
-  g_free (icon_str);
-
-  return action;
-}
-
-
-
-void
-thunar_menu_util_add_items_to_ui_manager (GtkUIManager   *ui_manager,
-                                          GtkActionGroup *action_group,
-                                          gint            merge_id,
-                                          const gchar    *path,
-                                          GList          *items)
-{
-  GList           *lp;
-  GtkAction       *action;
-  ThunarxMenu     *menu;
-  char            *subpath;
-  char            *action_path;
-  GList           *children;
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-  /* add the menu items to the UI manager */
-  for (lp = items; lp != NULL; lp = lp->next)
-    {
-      action = action_from_menu_item (G_OBJECT (lp->data));
-      g_object_get (G_OBJECT (lp->data), "menu", &menu, NULL);
-
-      /* add the action to the action group */
-      gtk_action_group_add_action (action_group, action);
-
-      /* add the action to the UI manager */
-      gtk_ui_manager_add_ui (ui_manager, merge_id, path,
-                             gtk_action_get_name (GTK_ACTION (action)),
-                             gtk_action_get_name (GTK_ACTION (action)),
-                             (menu != NULL) ? GTK_UI_MANAGER_MENU : GTK_UI_MANAGER_MENUITEM, FALSE);
-
-      /* TODO: Receive action path from plugin as generic data as below or create a property in ThunarxMenuItem? */
-      action_path = g_object_steal_data (G_OBJECT (lp->data), "action_path");
-      if (action_path)
-        {
-          gtk_action_set_accel_path (action, action_path);
-          g_free (action_path);
-        }
-
-      /* add submenu items if any */
-      if (menu != NULL) {
-        children = thunarx_menu_get_items (menu);
-        subpath = g_build_path ("/", path, gtk_action_get_name (action), NULL);
-
-        thunar_menu_util_add_items_to_ui_manager (ui_manager, action_group, merge_id,
-                                                  subpath, children);
-
-        thunarx_menu_item_list_free (children);
-        g_free (subpath);
-      }
-G_GNUC_END_IGNORE_DEPRECATIONS
-
-      /* release the reference on item and action */
-      g_object_unref (G_OBJECT (lp->data));
-      g_object_unref (G_OBJECT (action));
-    }
-}
-
-
-
-void
-thunar_menu_util_add_items_to_menu (GtkWidget *menu,
-                                    GList     *items)
-{
-  GList           *lp;
-  GtkAction       *action;
-  GtkWidget       *item;
-  GtkWidget       *submenu;
-  ThunarxMenu     *thunarx_menu;
-  GList           *children;
-
-  /* add the menu items to the UI manager */
-  for (lp = items; lp != NULL; lp = lp->next)
-    {
-      action = action_from_menu_item (G_OBJECT (lp->data));
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-      item = gtk_action_create_menu_item (action);
-G_GNUC_END_IGNORE_DEPRECATIONS
-      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-      gtk_widget_show (item);
-
-      /* add submenu items if any */
-      g_object_get (G_OBJECT (lp->data), "menu", &thunarx_menu, NULL);
-      if (thunarx_menu != NULL) {
-        children = thunarx_menu_get_items (thunarx_menu);
-
-        submenu = gtk_menu_new ();
-        gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
-
-        thunar_menu_util_add_items_to_menu (submenu, children);
-
-        thunarx_menu_item_list_free (children);
-      }
-
-      /* release the reference on item and action */
-      g_object_unref (G_OBJECT (lp->data));
-      g_object_unref (G_OBJECT (action));
-    }
-}
diff --git a/thunar/thunar-menu-util.h b/thunar/thunar-menu-util.h
deleted file mode 100644
index 68efe81b0..000000000
--- a/thunar/thunar-menu-util.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* vi:set et ai sw=2 sts=2 ts=2: */
-/*-
- * Copyright (c) 2017 Andre Miranda <andreldm@xfce.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __THUNAR_MENU_UTIL_H__
-#define __THUNAR_MENU_UTIL_H__
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-void       thunar_menu_util_add_items_to_ui_manager  (GtkUIManager   *ui_manager,
-                                                      GtkActionGroup *action_group,
-                                                      gint            merge_id,
-                                                      const gchar    *path,
-                                                      GList          *items);
-
-void       thunar_menu_util_add_items_to_menu        (GtkWidget *menu,
-                                                      GList     *items);
-
-G_END_DECLS
-
-#endif /* !__THUNAR_MENU_UTIL_H__ */
diff --git a/thunar/thunar-menu.c b/thunar/thunar-menu.c
index 86ba8f2fc..4363ccc86 100644
--- a/thunar/thunar-menu.c
+++ b/thunar/thunar-menu.c
@@ -300,7 +300,8 @@ thunar_menu_add_sections (ThunarMenu         *menu,
 
   if (menu_sections & THUNAR_MENU_SECTION_CUSTOM_ACTIONS)
     {
-       // TODO
+      if (thunar_launcher_append_custom_actions (menu->launcher, GTK_MENU_SHELL (menu)))
+         xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
     }
 
   if (menu_sections & THUNAR_MENU_SECTION_ZOOM)
diff --git a/thunar/thunar-renamer-dialog.c b/thunar/thunar-renamer-dialog.c
index 3e8a2d291..f76e77e89 100644
--- a/thunar/thunar-renamer-dialog.c
+++ b/thunar/thunar-renamer-dialog.c
@@ -39,7 +39,6 @@
 #include <thunar/thunar-launcher.h>
 #include <thunar/thunar-launcher.h>
 #include <thunar/thunar-menu.h>
-#include <thunar/thunar-menu-util.h>
 #include <thunar/thunar-private.h>
 #include <thunar/thunar-properties-dialog.h>
 #include <thunar/thunar-renamer-dialog.h>
@@ -878,11 +877,10 @@ thunar_renamer_dialog_append_menu_item (ThunarRenamerDialog *renamer_dialog,
 static void
 thunar_renamer_dialog_context_menu (ThunarRenamerDialog *renamer_dialog)
 {
-  GtkActionGroup *renamer_actions = NULL;
   ThunarxRenamer *renamer;
   ThunarMenu     *menu;
   GList          *items = NULL;
-  gint            renamer_merge_id = 0;
+  GList          *lp = NULL;
 
   _thunar_return_if_fail (THUNAR_IS_RENAMER_DIALOG (renamer_dialog));
 
@@ -902,41 +900,18 @@ thunar_renamer_dialog_context_menu (ThunarRenamerDialog *renamer_dialog)
                                          "tab-support-disabled", TRUE,
                                          "change_directory-support-disabled", TRUE, NULL);
   thunar_menu_add_sections (menu, THUNAR_MENU_SECTION_OPEN | THUNAR_MENU_SECTION_SENDTO);
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-  /* check if we have any renamer menu items */
-  if (G_UNLIKELY (items != NULL))
-    {
-      /* allocate a new action group and the merge id for the custom items */
-      renamer_actions = gtk_action_group_new ("thunar-renamer-dialog-renamer-actions");
-      renamer_merge_id = gtk_ui_manager_new_merge_id (renamer_dialog->ui_manager);
-      gtk_ui_manager_insert_action_group (renamer_dialog->ui_manager, renamer_actions, -1);
-
-      /* add the items to the UI manager */
-      thunar_menu_util_add_items_to_ui_manager (renamer_dialog->ui_manager, renamer_actions, renamer_merge_id,
-                                                "/file-context-menu/placeholder-renamer-actions", items);
-
-      /* be sure to update the UI manager to avoid flickering */
-      gtk_ui_manager_ensure_update (renamer_dialog->ui_manager);
-
-      /* cleanup */
-      g_list_free (items);
-    }
-
-  /* remove the previously merge items from the UI manager */
-  if (G_UNLIKELY (renamer_merge_id != 0))
-    {
-      gtk_ui_manager_remove_ui (renamer_dialog->ui_manager, renamer_merge_id);
-      gtk_ui_manager_ensure_update (renamer_dialog->ui_manager);
-    }
-
-  /* disconnect the previously created action group */
-  if (G_UNLIKELY (renamer_actions != NULL))
+  if (G_LIKELY (renamer != NULL))
     {
-      gtk_ui_manager_remove_action_group (renamer_dialog->ui_manager, renamer_actions);
-      g_object_unref (G_OBJECT (renamer_actions));
+      /* determine the menu items provided by the active renamer */
+      items = thunarx_renamer_get_menu_items (renamer, GTK_WINDOW (renamer_dialog), renamer_dialog->selected_files);
+      if (items != NULL)
+        {
+          for(lp = items; lp != NULL; lp = lp->next)
+              thunar_gtk_menu_thunarx_menu_item_new (lp->data, GTK_MENU_SHELL (menu));
+          g_list_free (items);
+          xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
+        }
     }
-
-G_GNUC_END_IGNORE_DEPRECATIONS
   thunar_renamer_dialog_append_menu_item (renamer_dialog, GTK_MENU_SHELL (menu), THUNAR_RENAMER_ACTION_ADD_FILES);
   thunar_renamer_dialog_append_menu_item (renamer_dialog, GTK_MENU_SHELL (menu), THUNAR_RENAMER_ACTION_REMOVE_FILES);
   xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
diff --git a/thunar/thunar-shortcuts-view.c b/thunar/thunar-shortcuts-view.c
index 41215fccf..16fa36ef3 100644
--- a/thunar/thunar-shortcuts-view.c
+++ b/thunar/thunar-shortcuts-view.c
@@ -40,7 +40,6 @@
 #include <thunar/thunar-dnd.h>
 #include <thunar/thunar-gio-extensions.h>
 #include <thunar/thunar-gtk-extensions.h>
-#include <thunar/thunar-menu-util.h>
 #include <thunar/thunar-preferences.h>
 #include <thunar/thunar-private.h>
 #include <thunar/thunar-shortcuts-icon-renderer.h>
@@ -1263,7 +1262,8 @@ G_GNUC_END_IGNORE_DEPRECATIONS
             }
 
           /* add the menu items to the menu */
-          thunar_menu_util_add_items_to_menu (menu, items);
+          for (lp = items; lp != NULL; lp = lp->next)
+            thunar_gtk_menu_thunarx_menu_item_new (lp->data, GTK_MENU_SHELL (menu));
 
           /* cleanup */
           g_list_free (items);
diff --git a/thunar/thunar-tree-view.c b/thunar/thunar-tree-view.c
index ff572dc25..886553598 100644
--- a/thunar/thunar-tree-view.c
+++ b/thunar/thunar-tree-view.c
@@ -34,7 +34,6 @@
 #include <thunar/thunar-gtk-extensions.h>
 #include <thunar/thunar-job.h>
 #include <thunar/thunar-marshal.h>
-#include <thunar/thunar-menu-util.h>
 #include <thunar/thunar-preferences.h>
 #include <thunar/thunar-private.h>
 #include <thunar/thunar-properties-dialog.h>
@@ -1558,7 +1557,8 @@ G_GNUC_END_IGNORE_DEPRECATIONS
               g_list_free (providers);
 
               /* add the menu items to the menu */
-              thunar_menu_util_add_items_to_menu (menu, items);
+              for (lp = items; lp != NULL; lp = lp->next)
+                thunar_gtk_menu_thunarx_menu_item_new (lp->data, GTK_MENU_SHELL (menu));
 
               /* add a separator to the end of the menu */
               if (G_LIKELY (lp != items))
diff --git a/thunar/thunar-window.c b/thunar/thunar-window.c
index 4aaeb278b..417661315 100644
--- a/thunar/thunar-window.c
+++ b/thunar/thunar-window.c
@@ -49,7 +49,6 @@
 #include <thunar/thunar-location-entry.h>
 #include <thunar/thunar-marshal.h>
 #include <thunar/thunar-menu.h>
-#include <thunar/thunar-menu-util.h>
 #include <thunar/thunar-pango-extensions.h>
 #include <thunar/thunar-preferences-dialog.h>
 #include <thunar/thunar-preferences.h>
@@ -137,7 +136,6 @@ static gpointer  thunar_window_notebook_create_window     (GtkWidget
                                                            gint                    x,
                                                            gint                    y,
                                                            ThunarWindow           *window);
-static void     thunar_window_merge_custom_preferences    (ThunarWindow           *window);
 static gboolean thunar_window_bookmark_merge              (gpointer                user_data);
 static void      thunar_window_update_location_bar_visible(ThunarWindow           *window);
 static void      thunar_window_handle_reload_request      (ThunarWindow           *window);
@@ -199,9 +197,6 @@ static void      thunar_window_menu_item_selected         (ThunarWindow
                                                            GtkWidget              *menu_item);
 static void      thunar_window_menu_item_deselected       (ThunarWindow           *window,
                                                            GtkWidget              *menu_item);
-static void     thunar_window_update_custom_actions       (ThunarView             *view,
-                                                           GParamSpec             *pspec,
-                                                           ThunarWindow           *window);
 static void      thunar_window_notify_loading             (ThunarView             *view,
                                                            GParamSpec             *pspec,
                                                            ThunarWindow           *window);
@@ -277,7 +272,7 @@ struct _ThunarWindow
 
   /* support for custom preferences actions */
   ThunarxProviderFactory *provider_factory;
-  guint                   custom_preferences_merge_id;
+  GList                  *thunarx_preferences_providers;
 
   /* UI manager merge ID for go menu actions */
   guint                   go_items_actions_merge_id;
@@ -295,16 +290,11 @@ struct _ThunarWindow
 
   ThunarIconFactory      *icon_factory;
 
-  GtkActionGroup         *action_group;
   GtkUIManager           *ui_manager;
 
   /* to be able to change folder on "device-pre-unmount" if required */
   ThunarDeviceMonitor    *device_monitor;
 
-  /* custom menu actions for the file menu */
-  GtkActionGroup         *custom_actions;
-  guint                   custom_merge_id;
-
   GtkWidget              *grid;
   GtkWidget              *menubar;
   GtkWidget              *spinner;
@@ -635,8 +625,9 @@ thunar_window_init (ThunarWindow *window)
   /* unset the view type */
   window->view_type = G_TYPE_NONE;
 
-  /* grab a reference on the provider factory */
+  /* grab a reference on the provider factory and load the providers*/
   window->provider_factory = thunarx_provider_factory_get_default ();
+  window->thunarx_preferences_providers = thunarx_provider_factory_list_providers (window->provider_factory, THUNARX_TYPE_PREFERENCES_PROVIDER);
 
   /* grab a reference on the preferences */
   window->preferences = thunar_preferences_get ();
@@ -992,6 +983,9 @@ thunar_window_create_edit_menu (ThunarWindow     *window,
                                 GtkWidget        *menu)
 {
   ThunarMenu      *submenu;
+  GtkWidget       *gtk_menu_item;
+  GList           *thunarx_menu_items;
+  GList           *pp, *lp;
 
   _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
   _thunar_return_val_if_fail (GTK_IS_MENU_ITEM (menu), FALSE);
@@ -1016,6 +1010,26 @@ thunar_window_create_edit_menu (ThunarWindow     *window,
                                    | THUNAR_MENU_SECTION_RENAME
                                    | THUNAR_MENU_SECTION_RESTORE);
 
+  /* determine the available preferences providers */
+  if (G_LIKELY (window->thunarx_preferences_providers != NULL))
+    {
+      /* add menu items from all providers */
+      for (pp = window->thunarx_preferences_providers; pp != NULL; pp = pp->next)
+        {
+          /* determine the available menu items for the provider */
+          thunarx_menu_items = thunarx_preferences_provider_get_menu_items (THUNARX_PREFERENCES_PROVIDER (pp->data), GTK_WIDGET (window));
+          for (lp = thunarx_menu_items; lp != NULL; lp = lp->next)
+            {
+                gtk_menu_item = thunar_gtk_menu_thunarx_menu_item_new (lp->data, GTK_MENU_SHELL (submenu));
+
+                /* Each thunarx_menu_item will be destroyed together with its related gtk_menu_item */
+                g_signal_connect_swapped (G_OBJECT (gtk_menu_item), "destroy", G_CALLBACK (g_object_unref), lp->data);
+            }
+
+          /* release the list */
+          g_list_free (thunarx_menu_items);
+        }
+    }
   xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_PREFERENCES), G_OBJECT (window), GTK_MENU_SHELL (submenu));
   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu), GTK_WIDGET (submenu));
   gtk_widget_show_all (GTK_WIDGET (submenu));
@@ -1252,11 +1266,6 @@ thunar_window_finalize (GObject *object)
   g_signal_handlers_disconnect_matched (window->ui_manager, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, window);
   g_object_unref (window->ui_manager);
 
-  /* release the custom actions */
-  if (window->custom_actions != NULL)
-    g_object_unref (window->custom_actions);
-
-  g_object_unref (window->action_group);
   g_object_unref (window->icon_factory);
   g_object_unref (window->launcher);
 
@@ -2213,51 +2222,6 @@ thunar_window_install_sidepane (ThunarWindow *window,
 
 
 
-static void
-thunar_window_merge_custom_preferences (ThunarWindow *window)
-{
-  GList           *providers;
-  GList           *items;
-  GList           *pp;
-
-  _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
-  _thunar_return_if_fail (window->custom_preferences_merge_id == 0);
-
-  /* determine the available preferences providers */
-  providers = thunarx_provider_factory_list_providers (window->provider_factory, THUNARX_TYPE_PREFERENCES_PROVIDER);
-  if (G_LIKELY (providers != NULL))
-    {
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-      /* allocate a new merge id from the UI manager */
-      window->custom_preferences_merge_id = gtk_ui_manager_new_merge_id (window->ui_manager);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
-      /* add menu items from all providers */
-      for (pp = providers; pp != NULL; pp = pp->next)
-        {
-          /* determine the available menu items for the provider */
-          items = thunarx_preferences_provider_get_menu_items (THUNARX_PREFERENCES_PROVIDER (pp->data), GTK_WIDGET (window));
-
-          thunar_menu_util_add_items_to_ui_manager (window->ui_manager,
-                                                    window->action_group,
-                                                    window->custom_preferences_merge_id,
-                                                    "/main-menu/edit-menu/placeholder-custom-preferences",
-                                                    items);
-
-          /* release the reference on the provider */
-          g_object_unref (G_OBJECT (pp->data));
-
-          /* release the action list */
-          g_list_free (items);
-        }
-
-      /* release the provider list */
-      g_list_free (providers);
-    }
-}
-
-
-
 static void
 thunar_window_bookmark_changed (ThunarWindow *window)
 {
@@ -3537,111 +3501,6 @@ thunar_window_menu_item_deselected (ThunarWindow *window,
 
 
 
-static void
-thunar_window_update_custom_actions (ThunarView   *view,
-                                     GParamSpec   *pspec,
-                                     ThunarWindow *window)
-{
-  ThunarFile      *folder;
-  GList           *selected_files;
-  GList           *items = NULL;
-  GList           *lp;
-  GList           *providers;
-  GList           *tmp;
-
-  _thunar_return_if_fail (THUNAR_IS_VIEW (view));
-  _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
-
-  /* leave if the signal is emitted from a non-active tab */
-  if (!gtk_widget_get_realized (GTK_WIDGET (window))
-      || window->view != GTK_WIDGET (view))
-    return;
-
-  /* grab a reference to the current directory of the window */
-  folder = thunar_window_get_current_directory (window);
-
-  /* leave if current directory is invalid */
-  if (folder != NULL &&
-      !thunarx_file_info_is_directory (THUNARX_FILE_INFO (folder)))
-      return;
-
-  /* load the menu provides from the provider factory */
-  providers = thunarx_provider_factory_list_providers (window->provider_factory,
-                                                       THUNARX_TYPE_MENU_PROVIDER);
-  if (G_LIKELY (providers != NULL))
-    {
-      /* get a list of selected files */
-      selected_files = thunar_component_get_selected_files (THUNAR_COMPONENT (view));
-
-      /* load the actions offered by the menu providers */
-      for (lp = providers; lp != NULL; lp = lp->next)
-        {
-          if (G_LIKELY (selected_files != NULL))
-            {
-              tmp = thunarx_menu_provider_get_file_menu_items (lp->data,
-                                                               GTK_WIDGET (window),
-                                                               selected_files);
-            }
-          else if (G_LIKELY (folder != NULL))
-            {
-              tmp = thunarx_menu_provider_get_folder_menu_items (lp->data,
-                                                                 GTK_WIDGET (window),
-                                                                 THUNARX_FILE_INFO (folder));
-            }
-          else
-            {
-              tmp = NULL;
-            }
-
-          items = g_list_concat (items, tmp);
-          g_object_unref (G_OBJECT (lp->data));
-        }
-      g_list_free (providers);
-    }
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-  /* remove previously inserted menu actions from the UI manager */
-  if (window->custom_merge_id != 0)
-    {
-      gtk_ui_manager_remove_ui (window->ui_manager, window->custom_merge_id);
-      gtk_ui_manager_ensure_update (window->ui_manager);
-      window->custom_merge_id = 0;
-    }
-
-  /* drop any previous custom action group */
-  if (window->custom_actions != NULL)
-    {
-      gtk_ui_manager_remove_action_group (window->ui_manager, window->custom_actions);
-      g_object_unref (window->custom_actions);
-      window->custom_actions = NULL;
-    }
-
-  /* add the actions specified by the menu providers */
-  if (G_LIKELY (items != NULL))
-    {
-      /* allocate the action group and the merge id for the custom actions */
-      window->custom_actions = gtk_action_group_new ("ThunarActions");
-      window->custom_merge_id = gtk_ui_manager_new_merge_id (window->ui_manager);
-
-      /* insert the new action group and make sure the UI manager gets updated */
-      gtk_ui_manager_insert_action_group (window->ui_manager, window->custom_actions, 0);
-      gtk_ui_manager_ensure_update (window->ui_manager);
-
-      /* add the menu items to the UI manager */
-      thunar_menu_util_add_items_to_ui_manager (window->ui_manager,
-                                                window->custom_actions,
-                                                window->custom_merge_id,
-                                                "/main-menu/file-menu/placeholder-custom-actions",
-                                                items);
-
-      /* cleanup */
-      g_list_free (items);
-    }
-G_GNUC_END_IGNORE_DEPRECATIONS
-}
-
-
-
 static void
 thunar_window_notify_loading (ThunarView   *view,
                               GParamSpec   *pspec,
@@ -3728,11 +3587,6 @@ thunar_window_merge_idle (gpointer user_data)
 {
   ThunarWindow *window = THUNAR_WINDOW (user_data);
 
-  /* merge custom preferences from the providers */
-THUNAR_THREADS_ENTER
-  thunar_window_merge_custom_preferences (window);
-THUNAR_THREADS_LEAVE
-
   thunar_window_bookmark_merge (window);
 
   return FALSE;
-- 
GitLab