diff --git a/src/chatview.cpp b/src/chatview.cpp
index 3d74df027eb970e0f78908571a10fce7069a4329..af39c7e60f0f6a4047d39679aa0fe31f5c6e9363 100644
--- a/src/chatview.cpp
+++ b/src/chatview.cpp
@@ -966,32 +966,12 @@ on_webkit_drag_drop(GtkWidget*, gchar* data, ChatView* self)
     if (!priv->conversation_) return;
     if (!data) return;
 
-    GError *error = nullptr;
-    auto* filename_uri = g_filename_from_uri(data, nullptr, &error);
-    if (error) {
-        g_warning("Unable to exec g_filename_from_uri on %s", data);
-        g_error_free(error);
-        return;
-    }
-    std::string data_str = filename_uri;
-    g_free(filename_uri);
-
-    // Only take files
-    if (data_str.find("\r\n") == std::string::npos) return;
-    const auto LEN_END = std::string("\r\n").length();
-    if (data_str.length() > LEN_END) {
-        // remove \r\n from the string
-        data_str = data_str.substr(0, data_str.length() - LEN_END);
-    } else {
-        // Nothing valid to drop, abort.
-        return;
-    }
-
-    if (auto model = (*priv->accountInfo_)->conversationModel.get()) {
-        model->sendFile(priv->conversation_->uid,
-                        data_str.c_str(),
-                        g_path_get_basename(data_str.c_str()));
-    }
+    foreach_file(data, [&](const char* file) {
+        if (auto model = (*priv->accountInfo_)->conversationModel.get()) {
+            model->sendFile(priv->conversation_->uid, file,
+                            g_path_get_basename(file));
+        }
+    });
 }
 
 static void
diff --git a/src/conversationsview.cpp b/src/conversationsview.cpp
index fa2a88317ad3d71823ad47cbe178f086c45f00b8..972d7b9d322af57a1a8c09318a4d271db338c8b1 100644
--- a/src/conversationsview.cpp
+++ b/src/conversationsview.cpp
@@ -41,9 +41,10 @@
 // Gnome client
 #include "native/pixbufmanipulator.h"
 #include "conversationpopupmenu.h"
+#include "utils/files.h"
 
-static constexpr const char* CALL_TARGET    = "CALL_TARGET";
-static constexpr int         CALL_TARGET_ID = 0;
+static constexpr const char* TEXT_URI_LIST_TARGET    = "text/uri-list";
+static constexpr int         TEXT_URI_LIST_TARGET_ID = 0;
 
 struct _ConversationsView
 {
@@ -504,66 +505,6 @@ show_popup_menu(ConversationsView *self, GdkEventButton *event)
         conversation_popup_menu_show(CONVERSATION_POPUP_MENU(priv->popupMenu_), event);
 }
 
-static void
-on_drag_data_get(GtkWidget        *treeview,
-                 G_GNUC_UNUSED GdkDragContext *context,
-                 GtkSelectionData *data,
-                 G_GNUC_UNUSED guint info,
-                 G_GNUC_UNUSED guint time,
-                 G_GNUC_UNUSED gpointer user_data)
-{
-    g_return_if_fail(IS_CONVERSATIONS_VIEW(treeview));
-
-    /* we always drag the selected row */
-    auto selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
-    GtkTreeModel *model = NULL;
-    GtkTreeIter iter;
-
-    if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
-        auto path_str = gtk_tree_model_get_string_from_iter(model, &iter);
-
-        gtk_selection_data_set(data,
-                               gdk_atom_intern_static_string(CALL_TARGET),
-                               8, /* bytes */
-                               (guchar *)path_str,
-                               strlen(path_str) + 1);
-
-        g_free(path_str);
-    } else {
-        g_warning("drag selection not valid");
-    }
-}
-
-static gboolean
-on_drag_drop(GtkWidget      *treeview,
-             GdkDragContext *context,
-             gint            x,
-             gint            y,
-             guint           time,
-             G_GNUC_UNUSED gpointer user_data)
-{
-    g_return_val_if_fail(IS_CONVERSATIONS_VIEW(treeview), FALSE);
-
-    GtkTreePath *path = NULL;
-    GtkTreeViewDropPosition drop_pos;
-
-    if (gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(treeview),
-                                          x, y, &path, &drop_pos)) {
-
-        GdkAtom target_type = gtk_drag_dest_find_target(treeview, context, NULL);
-
-        if (target_type != GDK_NONE) {
-            g_debug("can drop");
-            gtk_drag_get_data(treeview, context, target_type, time);
-            return TRUE;
-        }
-
-        gtk_tree_path_free(path);
-    }
-
-    return FALSE;
-}
-
 static gboolean
 on_drag_motion(GtkWidget      *treeview,
                GdkDragContext *context,
@@ -599,7 +540,7 @@ on_drag_data_received(GtkWidget        *treeview,
                       gint              x,
                       gint              y,
                       GtkSelectionData *data,
-                      G_GNUC_UNUSED guint info,
+                      guint             target_type,
                       guint             time,
                       G_GNUC_UNUSED gpointer user_data)
 {
@@ -612,6 +553,7 @@ on_drag_data_received(GtkWidget        *treeview,
     auto path_str_source = (gchar *)gtk_selection_data_get_data(data);
     auto type = gtk_selection_data_get_data_type(data);
     g_debug("data type: %s", gdk_atom_name(type));
+
     if (path_str_source && strlen(path_str_source) > 0) {
         g_debug("source path: %s", path_str_source);
 
@@ -620,30 +562,27 @@ on_drag_data_received(GtkWidget        *treeview,
         if (gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(treeview), x, y, &dest_path, NULL)) {
             auto model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
 
-            GtkTreeIter source, dest;
-            gtk_tree_model_get_iter_from_string(model, &source, path_str_source);
-            gtk_tree_model_get_iter(model, &dest, dest_path);
-
-            gchar *conversationUidSrc = nullptr;
-            gchar *conversationUidDest = nullptr;
-
-            gtk_tree_model_get(model, &source,
-                               0, &conversationUidSrc,
-                               -1);
-            gtk_tree_model_get(model, &dest,
-                               0, &conversationUidDest,
-                               -1);
-
-            (*priv->accountInfo_)->conversationModel->joinConversations(
-                conversationUidSrc,
-                conversationUidDest
-            );
-
-            gtk_tree_path_free(dest_path);
-            g_free(conversationUidSrc);
-            g_free(conversationUidDest);
-
-            success = TRUE;
+            switch (target_type) {
+                case TEXT_URI_LIST_TARGET_ID: {
+                    GtkTreeIter dest;
+                    gtk_tree_model_get_iter(model, &dest, dest_path);
+                    gchar *conversationUid = nullptr;
+                    gtk_tree_model_get(model, &dest, 0, &conversationUid, -1);
+
+                    foreach_file(path_str_source, [&](const char* file) {
+                        (*priv->accountInfo_)->conversationModel->sendFile(
+                            conversationUid, file, g_path_get_basename(file));
+                    });
+
+                    gtk_tree_path_free(dest_path);
+                    g_free(conversationUid);
+                    success = TRUE;
+                    break;
+                }
+                default:
+                    g_warning("unhandled drag and drop target type");
+                    success = FALSE;
+            }
         }
     }
 
@@ -826,20 +765,16 @@ build_conversations_view(ConversationsView *self)
     g_signal_connect_swapped(self, "button-press-event", G_CALLBACK(show_popup_menu), self);
 
     /* drag and drop */
-    static GtkTargetEntry targetentries[] = {
-        { (gchar *)CALL_TARGET, GTK_TARGET_SAME_WIDGET, CALL_TARGET_ID },
+    static GtkTargetEntry target_entries[] = {
+        { (gchar *)TEXT_URI_LIST_TARGET, GTK_TARGET_OTHER_APP, TEXT_URI_LIST_TARGET_ID },
     };
 
-    gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(self),
-        GDK_BUTTON1_MASK, targetentries, 1, (GdkDragAction)(GDK_ACTION_DEFAULT | GDK_ACTION_MOVE));
-
     gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(self),
-        targetentries, 1, GDK_ACTION_DEFAULT);
+        target_entries, 1,
+        (GdkDragAction)(GDK_ACTION_DEFAULT | GDK_ACTION_COPY));
 
-    g_signal_connect(self, "drag-data-get", G_CALLBACK(on_drag_data_get), nullptr);
-    g_signal_connect(self, "drag-drop", G_CALLBACK(on_drag_drop), nullptr);
     g_signal_connect(self, "drag-motion", G_CALLBACK(on_drag_motion), nullptr);
-    g_signal_connect(self, "drag_data_received", G_CALLBACK(on_drag_data_received), nullptr);
+    g_signal_connect(self, "drag-data-received", G_CALLBACK(on_drag_data_received), nullptr);
 
     priv->cpp = new details::CppImpl();
 }
diff --git a/src/utils/files.cpp b/src/utils/files.cpp
index 9d11137639a0f20662dc6a6f52fba7f116375c8b..dedce6e231121bc66a7a6e2fa3e28eaf5210aee8 100644
--- a/src/utils/files.cpp
+++ b/src/utils/files.cpp
@@ -206,3 +206,25 @@ get_settings_schema()
 
     return schema.get();
 }
+
+void
+foreach_file(const gchar *uris, const std::function<void(const char*)>& cb)
+{
+    guint i;
+    gchar **res = g_strsplit(uris, "\r\n", 0);
+    for (i = 0; res[i] != nullptr; i++) {
+        if (g_strcmp0(res[i], "") != 0) {
+            GError *error = nullptr;
+            auto* filename = g_filename_from_uri(res[i], nullptr, &error);
+            if (error) {
+                g_warning("Unable to exec g_filename_from_uri on %s", res[i]);
+                g_error_free(error);
+            }
+            else {
+                cb(filename);
+            }
+            g_free(filename);
+        }
+    }
+    g_strfreev(res);
+}
diff --git a/src/utils/files.h b/src/utils/files.h
index 9f7bc47621db71b58e9d3e27abd0d695414a662d..8f4bd27c5fe90927cf2781a3165e95b47b685070 100644
--- a/src/utils/files.h
+++ b/src/utils/files.h
@@ -20,6 +20,7 @@
 #ifndef _FILES_H
 #define _FILES_H
 
+#include <functional>
 #include <gio/gio.h>
 
 G_BEGIN_DECLS
@@ -28,6 +29,14 @@ void autostart_symlink(gboolean autostart);
 
 GSettingsSchema *get_settings_schema();
 
+/**
+ * Split the string `uris' using `g_strsplit()' with "\r\n" as the delimiter,
+ * passing each split part through `g_filename_from_uri()', and passing the
+ * result as an argument to the provided `cb' callback function.
+ */
+void
+foreach_file(const gchar *uris, const std::function<void(const char*)>& cb);
+
 G_END_DECLS
 
 #endif /* _FILES_H */