From c6505454dca4a33a1bceaf96484b9ed8c03e560a Mon Sep 17 00:00:00 2001
From: Benedikt Meurer <benny@xfce.org>
Date: Wed, 13 Sep 2006 23:36:10 +0000
Subject: [PATCH] 2006-09-14	Benedikt Meurer <benny@xfce.org>

	* thunarx/thunarx-menu-provider.{c,h}, thunarx/thunarx.symbols: Add a
	  new method get_dnd_actions() to the ThunarxMenuProvider, which allows
	  menu providers to install additional actions into the Drag'n'Drop
	  menu of the file manager.
	* docs/reference/thunarx/: Update the thunarx reference manual.
	* thunar/thunar-dnd.{c,h}, thunar/thunar-location-button.c,
	  thunar/thunar-shortcuts-view.c, thunar/thunar-standard-view.c,
	  thunar/thunar-tree-view.c: Insert the additional actions supplied
	  by the installed menu providers into the Drag'n'Drop menu.




(Old svn revision: 23151)
---
 ChangeLog                                     |  12 ++
 docs/reference/thunarx/thunarx-sections.txt   |   1 +
 .../thunarx/tmpl/thunarx-menu-provider.sgml   |  13 ++
 .../thunarx/tmpl/thunarx-renamer.sgml         |  10 +-
 thunar/thunar-dnd.c                           | 138 +++++++++++++-----
 thunar/thunar-dnd.h                           |   4 +-
 thunar/thunar-location-button.c               |   4 +-
 thunar/thunar-shortcuts-view.c                |  32 ++--
 thunar/thunar-standard-view.c                 |   4 +-
 thunar/thunar-tree-view.c                     |   4 +-
 thunarx/thunarx-menu-provider.c               |  67 ++++++++-
 thunarx/thunarx-menu-provider.h               |  17 ++-
 thunarx/thunarx.symbols                       |   5 +-
 13 files changed, 240 insertions(+), 71 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index aa591c386..3bee53476 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2006-09-14	Benedikt Meurer <benny@xfce.org>
+
+	* thunarx/thunarx-menu-provider.{c,h}, thunarx/thunarx.symbols: Add a
+	  new method get_dnd_actions() to the ThunarxMenuProvider, which allows
+	  menu providers to install additional actions into the Drag'n'Drop
+	  menu of the file manager.
+	* docs/reference/thunarx/: Update the thunarx reference manual.
+	* thunar/thunar-dnd.{c,h}, thunar/thunar-location-button.c,
+	  thunar/thunar-shortcuts-view.c, thunar/thunar-standard-view.c,
+	  thunar/thunar-tree-view.c: Insert the additional actions supplied
+	  by the installed menu providers into the Drag'n'Drop menu.
+
 2006-09-13	Benedikt Meurer <benny@xfce.org>
 
 	* thunar-vfs/thunar-vfs-monitor.c, thunar/thunar-standard-view.c:
diff --git a/docs/reference/thunarx/thunarx-sections.txt b/docs/reference/thunarx/thunarx-sections.txt
index 066342202..d03dc9054 100644
--- a/docs/reference/thunarx/thunarx-sections.txt
+++ b/docs/reference/thunarx/thunarx-sections.txt
@@ -35,6 +35,7 @@ ThunarxMenuProviderIface
 ThunarxMenuProvider
 thunarx_menu_provider_get_file_actions
 thunarx_menu_provider_get_folder_actions
+thunarx_menu_provider_get_dnd_actions
 <SUBSECTION Standard>
 THUNARX_TYPE_MENU_PROVIDER
 THUNARX_MENU_PROVIDER
diff --git a/docs/reference/thunarx/tmpl/thunarx-menu-provider.sgml b/docs/reference/thunarx/tmpl/thunarx-menu-provider.sgml
index 1ee6e3c22..bc71743e7 100644
--- a/docs/reference/thunarx/tmpl/thunarx-menu-provider.sgml
+++ b/docs/reference/thunarx/tmpl/thunarx-menu-provider.sgml
@@ -112,6 +112,7 @@ Stable
 
 @get_file_actions: See thunarx_menu_provider_get_file_actions().
 @get_folder_actions: See thunarx_menu_provider_get_folder_actions().
+@get_dnd_actions: See thunarx_menu_provider_get_dnd_actions().
 
 <!-- ##### STRUCT ThunarxMenuProvider ##### -->
 <para>
@@ -141,3 +142,15 @@ Stable
 @Returns: 
 
 
+<!-- ##### FUNCTION thunarx_menu_provider_get_dnd_actions ##### -->
+<para>
+
+</para>
+
+@provider: 
+@window: 
+@folder: 
+@files: 
+@Returns: 
+
+
diff --git a/docs/reference/thunarx/tmpl/thunarx-renamer.sgml b/docs/reference/thunarx/tmpl/thunarx-renamer.sgml
index 09f379acc..05ff01464 100644
--- a/docs/reference/thunarx/tmpl/thunarx-renamer.sgml
+++ b/docs/reference/thunarx/tmpl/thunarx-renamer.sgml
@@ -73,11 +73,11 @@ The abstract base class for bulk renamers
   rename module in Thunar.
 </para>
 
-@process: see thunarx_renamer_process().
-@load:    see thunarx_renamer_load().
-@save:    see thunarx_renamer_save().
-@get_actions: 
-@changed: see thunarx_renamer_changed().
+@process: 	see thunarx_renamer_process().
+@load:    	see thunarx_renamer_load().
+@save:    	see thunarx_renamer_save().
+@get_actions:	see thunarx_renamer_get_actions().
+@changed: 	see thunarx_renamer_changed().
 
 <!-- ##### FUNCTION thunarx_renamer_get_help_url ##### -->
 <para>
diff --git a/thunar/thunar-dnd.c b/thunar/thunar-dnd.c
index cfef78898..4fb278c62 100644
--- a/thunar/thunar-dnd.c
+++ b/thunar/thunar-dnd.c
@@ -21,27 +21,32 @@
 #include <config.h>
 #endif
 
+#include <thunarx/thunarx.h>
+
 #include <thunar/thunar-application.h>
 #include <thunar/thunar-dialogs.h>
 #include <thunar/thunar-dnd.h>
+#include <thunar/thunar-gtk-extensions.h>
 #include <thunar/thunar-private.h>
 
 
 
 static void
-action_selected (GtkWidget     *item,
-                 GdkDragAction *action)
+dnd_action_selected (GtkWidget     *item,
+                     GdkDragAction *dnd_action_return)
 {
-  *action = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (item), I_("action")));
+  *dnd_action_return = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (item), "dnd-action"));
 }
 
 
 
 /**
  * thunar_dnd_ask:
- * @widget  : the widget on which the drop was performed.
- * @time    : the time of the drop event.
- * @actions : the list of actions supported for the drop.
+ * @widget    : the widget on which the drop was performed.
+ * @folder    : the #ThunarFile to which the @path_list is being dropped.
+ * @path_list : the #ThunarVfsPath<!---->s of the files being dropped to @file.
+ * @time      : the time of the drop event.
+ * @actions   : the list of actions supported for the drop.
  *
  * Pops up a menu that asks the user to choose one of the
  * @actions or to cancel the drop. If the user chooses a
@@ -56,45 +61,51 @@ action_selected (GtkWidget     *item,
  **/
 GdkDragAction
 thunar_dnd_ask (GtkWidget    *widget,
+                ThunarFile   *folder,
+                GList        *path_list,
                 guint         time,
-                GdkDragAction actions)
+                GdkDragAction dnd_actions)
 {
-  static const GdkDragAction action_items[] = { GDK_ACTION_COPY, GDK_ACTION_MOVE, GDK_ACTION_LINK };
-  static const gchar        *action_names[] = { N_ ("_Copy here"), N_ ("_Move here"), N_ ("_Link here") };
-  static const gchar        *action_icons[] = { "stock_folder-copy", "stock_folder-move", NULL };
-
-  GdkDragAction action = 0;
-  GtkWidget    *image;
-  GtkWidget    *menu;
-  GtkWidget    *item;
-  GMainLoop    *loop;
-  guint         n;
-
+  static const GdkDragAction dnd_action_items[] = { GDK_ACTION_COPY, GDK_ACTION_MOVE, GDK_ACTION_LINK };
+  static const gchar        *dnd_action_names[] = { N_ ("_Copy here"), N_ ("_Move here"), N_ ("_Link here") };
+  static const gchar        *dnd_action_icons[] = { "stock_folder-copy", "stock_folder-move", NULL };
+
+  ThunarxProviderFactory *factory;
+  GdkDragAction           dnd_action = 0;
+  ThunarFile             *file;
+  GtkWidget              *window;
+  GtkWidget              *image;
+  GtkWidget              *menu;
+  GtkWidget              *item;
+  GList                  *file_list = NULL;
+  GList                  *providers = NULL;
+  GList                  *actions = NULL;
+  GList                  *lp;
+  guint                   n;
+
+  _thunar_return_val_if_fail (thunar_file_is_directory (folder), 0);
   _thunar_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
 
-  /* prepare the internal loop */
-  loop = g_main_loop_new (NULL, FALSE);
+  /* connect to the provider factory */
+  factory = thunarx_provider_factory_get_default ();
 
   /* prepare the popup menu */
   menu = gtk_menu_new ();
-  gtk_menu_set_screen (GTK_MENU (menu), gtk_widget_get_screen (widget));
-  g_signal_connect_swapped (G_OBJECT (menu), "deactivate", G_CALLBACK (g_main_loop_quit), loop);
-  exo_gtk_object_ref_sink (GTK_OBJECT (menu));
 
   /* append the various items */
-  for (n = 0; n < G_N_ELEMENTS (action_items); ++n)
-    if (G_LIKELY ((actions & action_items[n]) != 0))
+  for (n = 0; n < G_N_ELEMENTS (dnd_action_items); ++n)
+    if (G_LIKELY ((dnd_actions & dnd_action_items[n]) != 0))
       {
-        item = gtk_image_menu_item_new_with_mnemonic (_(action_names[n]));
-        g_object_set_data (G_OBJECT (item), I_("action"), GUINT_TO_POINTER (action_items[n]));
-        g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (action_selected), &action);
+        item = gtk_image_menu_item_new_with_mnemonic (_(dnd_action_names[n]));
+        g_object_set_data (G_OBJECT (item), I_("dnd-action"), GUINT_TO_POINTER (dnd_action_items[n]));
+        g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (dnd_action_selected), &dnd_action);
         gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
         gtk_widget_show (item);
 
         /* add image to the menu item */
-        if (G_LIKELY (action_icons[n] != NULL))
+        if (G_LIKELY (dnd_action_icons[n] != NULL))
           {
-            image = gtk_image_new_from_icon_name (action_icons[n], GTK_ICON_SIZE_MENU);
+            image = gtk_image_new_from_icon_name (dnd_action_icons[n], GTK_ICON_SIZE_MENU);
             gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
             gtk_widget_show (image);
           }
@@ -105,22 +116,71 @@ thunar_dnd_ask (GtkWidget    *widget,
   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
   gtk_widget_show (item);
 
+  /* determine the toplevel window the widget belongs to */
+  window = gtk_widget_get_toplevel (widget);
+  if (G_LIKELY (window != NULL && GTK_WIDGET_TOPLEVEL (window)))
+    {
+      /* check if we can resolve all paths */
+      for (lp = path_list; lp != NULL; lp = lp->next)
+        {
+          /* try to resolve this path */
+          file = thunar_file_cache_lookup (lp->data);
+          if (G_LIKELY (file != NULL))
+            file_list = g_list_prepend (file_list, file);
+          else
+            break;
+        }
+
+      /* check if we resolved all paths (and have atleast one file) */
+      if (G_LIKELY (file_list != NULL && lp == NULL))
+        {
+          /* load the menu providers from the provider factory */
+          providers = thunarx_provider_factory_list_providers (factory, THUNARX_TYPE_MENU_PROVIDER);
+
+          /* load the dnd actions offered by the menu providers */
+          for (lp = providers; lp != NULL; lp = lp->next)
+            {
+              /* merge the actions from this provider */
+              actions = g_list_concat (actions, thunarx_menu_provider_get_dnd_actions (lp->data, window, THUNARX_FILE_INFO (folder), file_list));
+              g_object_unref (G_OBJECT (lp->data));
+            }
+          g_list_free (providers);
+
+          /* check if we have atleast one action */
+          if (G_UNLIKELY (actions != NULL))
+            {
+              /* add menu items for all actions */
+              for (lp = actions; lp != NULL; lp = lp->next)
+                {
+                  /* add a menu item for the action */
+                  item = gtk_action_create_menu_item (lp->data);
+                  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+                  g_object_unref (G_OBJECT (lp->data));
+                  gtk_widget_show (item);
+                }
+              g_list_free (actions);
+
+              /* append another separator */
+              item = gtk_separator_menu_item_new ();
+              gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+              gtk_widget_show (item);
+            }
+        }
+    }
+
   /* append the cancel item */
   item = gtk_image_menu_item_new_from_stock (GTK_STOCK_CANCEL, NULL);
   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
   gtk_widget_show (item);
 
-  /* run the internal loop */
-  gtk_grab_add (menu);
-  gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3, time);
-  g_main_loop_run (loop);
-  gtk_grab_remove (menu);
+  /* run the menu on the widget's screen (takes over the floating reference of menu) */
+  thunar_gtk_menu_run (GTK_MENU (menu), widget, NULL, NULL, 3, time);
 
-  /* clean up */
-  g_object_unref (G_OBJECT (menu));
-  g_main_loop_unref (loop);
+  /* cleanup */
+  g_object_unref (G_OBJECT (factory));
+  g_list_free (file_list);
 
-  return action;
+  return dnd_action;
 }
 
 
diff --git a/thunar/thunar-dnd.h b/thunar/thunar-dnd.h
index 7163d11fe..f1e83555a 100644
--- a/thunar/thunar-dnd.h
+++ b/thunar/thunar-dnd.h
@@ -1,6 +1,6 @@
 /* $Id$ */
 /*-
- * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org>
+ * Copyright (c) 2005-2006 Benedikt Meurer <benny@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
@@ -25,6 +25,8 @@
 G_BEGIN_DECLS;
 
 GdkDragAction thunar_dnd_ask     (GtkWidget    *widget,
+                                  ThunarFile   *folder,
+                                  GList        *path_list,
                                   guint         time,
                                   GdkDragAction actions);
 
diff --git a/thunar/thunar-location-button.c b/thunar/thunar-location-button.c
index ad5d65324..2c3d6257a 100644
--- a/thunar/thunar-location-button.c
+++ b/thunar/thunar-location-button.c
@@ -703,7 +703,9 @@ thunar_location_button_drag_data_received (GtkWidget            *button,
       if (G_LIKELY ((actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK)) != 0))
         {
           /* as the user what to do with the drop data */
-          action = (context->action == GDK_ACTION_ASK) ? thunar_dnd_ask (button, time, actions) : context->action;
+          action = (context->action == GDK_ACTION_ASK)
+                 ? thunar_dnd_ask (button, location_button->file, location_button->drop_path_list, time, actions)
+                 : context->action;
 
           /* perform the requested action */
           if (G_LIKELY (action != 0))
diff --git a/thunar/thunar-shortcuts-view.c b/thunar/thunar-shortcuts-view.c
index ce3b998c1..5c88b9771 100644
--- a/thunar/thunar-shortcuts-view.c
+++ b/thunar/thunar-shortcuts-view.c
@@ -487,29 +487,29 @@ thunar_shortcuts_view_drag_data_received (GtkWidget        *widget,
                 }
               else if (G_LIKELY ((actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK)) != 0))
                 {
-                  /* ask the user what to do with the drop data */
-                  if (G_UNLIKELY (action == GDK_ACTION_ASK))
-                    action = thunar_dnd_ask (widget, time, actions);
+                  /* get the shortcuts model */
+                  model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
 
-                  /* perform the requested action */
-                  if (G_LIKELY (action != 0))
+                  /* determine the iterator for the path */
+                  if (gtk_tree_model_get_iter (model, &iter, path))
                     {
-                      /* get the shortcuts model */
-                      model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
-
-                      /* determine the iterator for the path */
-                      if (gtk_tree_model_get_iter (model, &iter, path))
+                      /* determine the file for the iter */
+                      gtk_tree_model_get (model, &iter, THUNAR_SHORTCUTS_MODEL_COLUMN_FILE, &file, -1);
+                      if (G_LIKELY (file != NULL))
                         {
-                          /* determine the file for the iter */
-                          gtk_tree_model_get (model, &iter, THUNAR_SHORTCUTS_MODEL_COLUMN_FILE, &file, -1);
-                          if (G_LIKELY (file != NULL))
+                          /* ask the user what to do with the drop data */
+                          if (G_UNLIKELY (action == GDK_ACTION_ASK))
+                            action = thunar_dnd_ask (widget, file, view->drop_path_list, time, actions);
+
+                          /* perform the requested action */
+                          if (G_LIKELY (action != 0))
                             {
                               /* really perform the drop :-) */
                               succeed = thunar_dnd_perform (widget, file, view->drop_path_list, action, NULL);
-
-                              /* release the file */
-                              g_object_unref (G_OBJECT (file));
                             }
+
+                          /* release the file */
+                          g_object_unref (G_OBJECT (file));
                         }
                     }
                 }
diff --git a/thunar/thunar-standard-view.c b/thunar/thunar-standard-view.c
index 8aab7c2f8..89e55c7f1 100644
--- a/thunar/thunar-standard-view.c
+++ b/thunar/thunar-standard-view.c
@@ -2770,7 +2770,9 @@ thunar_standard_view_drag_data_received (GtkWidget          *view,
           if (G_LIKELY ((actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK)) != 0))
             {
               /* ask the user what to do with the drop data */
-              action = (context->action == GDK_ACTION_ASK) ? thunar_dnd_ask (GTK_WIDGET (standard_view), time, actions) : context->action;
+              action = (context->action == GDK_ACTION_ASK)
+                     ? thunar_dnd_ask (GTK_WIDGET (standard_view), file, standard_view->priv->drop_path_list, time, actions)
+                     : context->action;
 
               /* perform the requested action */
               if (G_LIKELY (action != 0))
diff --git a/thunar/thunar-tree-view.c b/thunar/thunar-tree-view.c
index d71105850..189f8fbda 100644
--- a/thunar/thunar-tree-view.c
+++ b/thunar/thunar-tree-view.c
@@ -734,7 +734,9 @@ thunar_tree_view_drag_data_received (GtkWidget        *widget,
       if (G_LIKELY ((actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK)) != 0))
         {
           /* ask the user what to do with the drop data */
-          action = (context->action == GDK_ACTION_ASK) ? thunar_dnd_ask (GTK_WIDGET (view), time, actions) : context->action;
+          action = (context->action == GDK_ACTION_ASK)
+                 ? thunar_dnd_ask (GTK_WIDGET (view), file, view->drop_path_list, time, actions)
+                 : context->action;
 
           /* perform the requested action */
           if (G_LIKELY (action != 0))
diff --git a/thunarx/thunarx-menu-provider.c b/thunarx/thunarx-menu-provider.c
index 7c6f5f113..5bb5be29b 100644
--- a/thunarx/thunarx-menu-provider.c
+++ b/thunarx/thunarx-menu-provider.c
@@ -1,6 +1,6 @@
 /* $Id$ */
 /*-
- * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org>
+ * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -172,5 +172,70 @@ thunarx_menu_provider_get_folder_actions (ThunarxMenuProvider *provider,
 
 
 
+/**
+ * thunarx_menu_provider_get_dnd_actions:
+ * @provider : a #ThunarxMenuProvider.
+ * @window   : the #GtkWindow within which the actions will be used.
+ * @folder   : the folder into which the @files are being dropped
+ * @files    : the list of #ThunarxFileInfo<!---->s for the files that are 
+ *             being dropped to @folder in @window.
+ *
+ * Returns the list of #GtkAction<!---->s that @provider has to offer for
+ * dropping the @files into the @folder. For example, the thunar-archive-plugin
+ * provides <guilabel>Extract Here</guilabel> actions when dropping archive
+ * files into a folder that is writable by the user.
+ *
+ * As a special note, this method automatically takes a reference on the
+ * @provider for every #GtkAction object returned from the real implementation
+ * of this method in @provider. This is to make sure that the extension stays
+ * in memory for atleast the time that the actions are used. If the extension
+ * wants to stay in memory for a longer time, it'll need to take care of this
+ * itself (e.g. by taking an additional reference on the @provider itself,
+ * that's released at a later time).
+ *
+ * The caller is responsible to free the returned list of actions using
+ * something like this when no longer needed:
+ * <informalexample><programlisting>
+ * g_list_foreach (list, (GFunc) g_object_unref, NULL);
+ * g_list_free (list);
+ * </programlisting></informalexample>
+ *
+ * Return value: the list of #GtkAction<!---->s that @provider has to offer
+ *               for dropping @files to @folder.
+ *
+ * Since: 0.4.1
+ **/
+GList*
+thunarx_menu_provider_get_dnd_actions (ThunarxMenuProvider *provider,
+                                       GtkWidget           *window,
+                                       ThunarxFileInfo     *folder,
+                                       GList               *files)
+{
+  GList *actions;
+
+  g_return_val_if_fail (THUNARX_IS_MENU_PROVIDER (provider), NULL);
+  g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
+  g_return_val_if_fail (THUNARX_IS_FILE_INFO (folder), NULL);
+  g_return_val_if_fail (thunarx_file_info_is_directory (folder), NULL);
+  g_return_val_if_fail (files != NULL, NULL);
+
+  if (THUNARX_MENU_PROVIDER_GET_IFACE (provider)->get_dnd_actions != NULL)
+    {
+      /* query the actions from the implementation */
+      actions = (*THUNARX_MENU_PROVIDER_GET_IFACE (provider)->get_dnd_actions) (provider, window, folder, files);
+
+      /* take a reference on the provider for each action */
+      thunarx_object_list_take_reference (actions, provider);
+    }
+  else
+    {
+      actions = NULL;
+    }
+
+  return actions;
+}
+
+
+
 #define __THUNARX_MENU_PROVIDER_C__
 #include <thunarx/thunarx-aliasdef.c>
diff --git a/thunarx/thunarx-menu-provider.h b/thunarx/thunarx-menu-provider.h
index d6efdd98f..018babc2b 100644
--- a/thunarx/thunarx-menu-provider.h
+++ b/thunarx/thunarx-menu-provider.h
@@ -1,6 +1,6 @@
 /* $Id$ */
 /*-
- * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org>
+ * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -53,22 +53,31 @@ struct _ThunarxMenuProviderIface
                                  GtkWidget           *window,
                                  ThunarxFileInfo     *folder);
 
+  GList *(*get_dnd_actions)     (ThunarxMenuProvider *provider,
+                                 GtkWidget           *window,
+                                 ThunarxFileInfo     *folder,
+                                 GList               *files);
+
   /*< private >*/
   void (*reserved1) (void);
   void (*reserved2) (void);
   void (*reserved3) (void);
-  void (*reserved4) (void);
 };
 
 GType  thunarx_menu_provider_get_type           (void) G_GNUC_CONST;
 
 GList *thunarx_menu_provider_get_file_actions   (ThunarxMenuProvider *provider,
                                                  GtkWidget           *window,
-                                                 GList               *files);
+                                                 GList               *files) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
 
 GList *thunarx_menu_provider_get_folder_actions (ThunarxMenuProvider *provider,
                                                  GtkWidget           *window,
-                                                 ThunarxFileInfo     *folder);
+                                                 ThunarxFileInfo     *folder) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+
+GList *thunarx_menu_provider_get_dnd_actions    (ThunarxMenuProvider *provider,
+                                                 GtkWidget           *window,
+                                                 ThunarxFileInfo     *folder,
+                                                 GList               *files) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
 
 G_END_DECLS;
 
diff --git a/thunarx/thunarx.symbols b/thunarx/thunarx.symbols
index 849cdb9c5..ebb82cee5 100644
--- a/thunarx/thunarx.symbols
+++ b/thunarx/thunarx.symbols
@@ -68,8 +68,9 @@ thunarx_file_info_list_free
 #if IN_HEADER(__THUNARX_MENU_PROVIDER_H__)
 #if IN_SOURCE(__THUNARX_MENU_PROVIDER_C__)
 thunarx_menu_provider_get_type G_GNUC_CONST
-thunarx_menu_provider_get_file_actions
-thunarx_menu_provider_get_folder_actions
+thunarx_menu_provider_get_file_actions G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT
+thunarx_menu_provider_get_folder_actions G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT
+thunarx_menu_provider_get_dnd_actions G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT
 #endif
 #endif
 
-- 
GitLab