From 1386b313021068921f13d3385fdaa0a371a661b1 Mon Sep 17 00:00:00 2001 From: Olaf Wintermann Date: Sat, 5 Apr 2025 22:12:55 +0200 Subject: [PATCH] implement gtk3 textview dnd handler --- application/gtk-text.c | 121 ++++++++++++++++++++++++++++++----------- 1 file changed, 89 insertions(+), 32 deletions(-) diff --git a/application/gtk-text.c b/application/gtk-text.c index 43f755c..ab238bf 100644 --- a/application/gtk-text.c +++ b/application/gtk-text.c @@ -88,6 +88,16 @@ static gboolean editor_drop_cb( static gboolean editor_textview_event_after(GtkWidget *textview, GdkEvent *ev, NoteEditor *editor); +static void editor_drop_cb( + GtkWidget *textview, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time, + NoteEditor *editor); + #endif void editor_global_init() { @@ -136,6 +146,20 @@ void editor_init_textview(UiObject *obj, UIWIDGET textview) { gtk_widget_add_controller(textview, GTK_EVENT_CONTROLLER(dndtarget)); #else g_signal_connect(textview, "event-after", G_CALLBACK(editor_textview_event_after), editor); + + // dnd + GtkTargetEntry targets[] = { + { "text/uri-list", 0, 0 }, + { "text/plain", 0, 0 } + }; + + gtk_drag_dest_set(textview, + 0, + targets, + G_N_ELEMENTS(targets), + GDK_ACTION_COPY); + + g_signal_connect(textview, "drag-data-received", G_CALLBACK(editor_drop_cb), editor); #endif g_signal_connect(textview, "notify::buffer", G_CALLBACK(editor_set_buffer_cb), editor); @@ -314,6 +338,44 @@ static void editor_attach_image(NoteEditor *editor, GdkPixbuf *pixbuf, char *att ui_list_update(model->attachments); } +static gboolean editor_dnd_add_file(NoteEditor *editor, GFile *file) { + char *scheme = g_file_get_uri_scheme(file); + if(scheme && strcmp(scheme, "file")) { + g_free(scheme); + return FALSE; + } + g_free(scheme); + + gboolean success = 1; + + GdkPixbuf *pixbuf = NULL; + + char *path = g_file_get_path(file); + char *attachment_path = strdup(path); + printf("dnd file: %s\n", path); + + if(path_is_image_file(cx_str(path))) { + GError *error = NULL; + pixbuf = gdk_pixbuf_new_from_file(path, &error); + if(!pixbuf) { + // cannot load image, attach as generic file + success = editor_attach_file(editor, path); + } + } else { + // attach generic file + success = editor_attach_file(editor, path); + } + g_free(path); + + if(pixbuf && success) { + editor_attach_image(editor, pixbuf, attachment_path); + } else { + free(attachment_path); + } + + return success; +} + #if GTK_CHECK_VERSION(4, 0, 0) /* @@ -366,50 +428,45 @@ static gboolean editor_drop_cb( if(G_VALUE_HOLDS(value, G_TYPE_FILE)) { // dnd type: uri GFile *file = g_value_get_object(value); - if(!file) { - return FALSE; - } - char *scheme = g_file_get_uri_scheme(file); - if(scheme && strcmp(scheme, "file")) { - g_free(scheme); - return FALSE; - } - g_free(scheme); - - char *path = g_file_get_path(file); - attachment_path = strdup(path); - printf("dnd file: %s\n", path); - - if(path_is_image_file(cx_str(path))) { - GError *error = NULL; - pixbuf = gdk_pixbuf_new_from_file(path, &error); - if(!pixbuf) { - // cannot load image, attach as generic file - success = editor_attach_file(editor, path); - } - } else { - // attach generic file - success = editor_attach_file(editor, path); - } - g_free(path); + success = editor_dnd_add_file(editor, file); } else if(G_VALUE_HOLDS (value, GDK_TYPE_PIXBUF)) { // dnd type image pixbuf = g_value_get_object(value); + editor_attach_image(editor, pixbuf, NULL); } else { return FALSE; } - if(pixbuf && success) { - editor_attach_image(editor, pixbuf, attachment_path); - } else { - free(attachment_path); - } - return success; } #else +static void editor_drop_cb( + GtkWidget *textview, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time, + NoteEditor *editor) +{ + char **uris = gtk_selection_data_get_uris(data); + if(uris) { + char **uri = uris; + while(*uri) { + GFile *file = g_file_new_for_uri(*uri); + editor_dnd_add_file(editor, file); // TODO: handle error? + g_object_unref(file); + uri++; + } + g_strfreev(uris); + } + + gtk_drag_finish(context, TRUE, FALSE, time); +} + static gboolean editor_textview_event_after(GtkWidget *textview, GdkEvent *ev, NoteEditor *editor) { int x, y; if(ev->type == GDK_BUTTON_RELEASE) { -- 2.43.5