ui/gtk/dnd.c

changeset 90
f501f0efc9a8
parent 32
e5f4d8af567e
--- a/ui/gtk/dnd.c	Tue Nov 26 11:38:10 2024 +0100
+++ b/ui/gtk/dnd.c	Wed Nov 27 13:27:30 2024 +0100
@@ -32,6 +32,7 @@
 
 #include "dnd.h"
 #include <cx/buffer.h>
+#include <cx/array_list.h>
 
 #ifdef UI_GTK2LEGACY
 static gboolean selection_data_set_uris(GtkSelectionData *selection_data, char **uris) {
@@ -102,18 +103,193 @@
 }
 */
 
+#if GTK_MAJOR_VERSION >= 4
+
 void ui_selection_settext(UiDnD *sel, char *str, int len) {
+    if(!sel->providers) {
+        return;
+    }
     
+    if(len == -1) {
+        len = strlen(str);
+    }
+    GBytes *bytes = g_bytes_new(str, len);
+    GdkContentProvider *provider = gdk_content_provider_new_for_bytes("text/plain;charset=utf-8", bytes);
+    g_bytes_unref(bytes);
+    
+    cxListAdd(sel->providers, &provider);
 }
 
 void ui_selection_seturis(UiDnD *sel, char **uris, int nelm) {
+    if(!sel->providers) {
+        return;
+    }
     
+    GFile **files = calloc(nelm, sizeof(GFile*));
+    for(int i=0;i<nelm;i++) {
+        GFile *file = uris[i][0] == '/' ? g_file_new_for_path(uris[i]) : g_file_new_for_uri(uris[i]);
+        files[i] = file;
+    }
+    GdkFileList *list = gdk_file_list_new_from_array(files, nelm);
+    
+    GdkContentProvider *provider = gdk_content_provider_new_typed(GDK_TYPE_FILE_LIST, list);
+    cxListAdd(sel->providers, &provider);
+    
+    g_slist_free_full ((GSList*)list, g_object_unref);
+    free(files);
 }
 
 char* ui_selection_gettext(UiDnD *sel) {
+    if(!sel->value) {
+        return NULL;
+    }
+    
+    if(G_VALUE_HOLDS(sel->value, G_TYPE_STRING)) {
+        const char *str = g_value_get_string(sel->value);
+        return str ? strdup(str) : NULL;
+    }
+    
     return NULL;
 }
 
 UiFileList ui_selection_geturis(UiDnD *sel) {
+    if(!sel->value) {
+        return (UiFileList){NULL,0};
+    }
+    
+    if(G_VALUE_HOLDS(sel->value, GDK_TYPE_FILE_LIST)) {
+        GSList *list = g_value_get_boxed(sel->value);
+        if(!list) {
+            return (UiFileList){NULL,0};
+        }
+        guint size = g_slist_length(list);
+        
+        UiFileList flist;
+        flist.nfiles = size;
+        flist.files = calloc(size, sizeof(char*));
+        int i=0;
+        while(list) {
+            GFile *file = list->data;
+            char *uri = g_file_get_uri(file);
+            flist.files[i++] = strdup(uri);
+            g_free(uri);
+            list = list->next;
+        }
+        return flist;
+    }
     return (UiFileList){NULL,0};
 }
+
+
+UiDnD* ui_create_dnd(void) {
+    UiDnD *dnd = malloc(sizeof(UiDnD));
+    memset(dnd, 0, sizeof(UiDnD));
+    dnd->providers = cxArrayListCreateSimple(sizeof(void*), 16);
+    dnd->selected_action = 0;
+    dnd->delete = FALSE;
+    return dnd;
+}
+
+void ui_dnd_free(UiDnD *dnd) {
+    cxListDestroy(dnd->providers);
+    free(dnd);
+}
+
+UiDnDAction ui_dnd_result(UiDnD *dnd) {
+    switch(dnd->selected_action) {
+        case 0: return UI_DND_ACTION_NONE;
+        case GDK_ACTION_COPY: return UI_DND_ACTION_COPY;
+        case GDK_ACTION_MOVE: return UI_DND_ACTION_MOVE;
+        case GDK_ACTION_LINK: return UI_DND_ACTION_LINK;
+        default: break;
+    }
+    return UI_DND_ACTION_CUSTOM;
+}
+
+#else
+
+void ui_selection_settext(UiDnD *sel, char *str, int len) {
+    gtk_selection_data_set_text(sel->data, str, len);
+}
+
+void ui_selection_seturis(UiDnD *sel, char **uris, int nelm) {
+    char **uriarray = calloc(nelm+1, sizeof(char*));
+    for(int i=0;i<nelm;i++) {
+        uriarray[i] = uris[i];
+    }
+    uriarray[nelm] = NULL;
+    gtk_selection_data_set_uris(sel->data, uriarray);
+    free(uriarray);
+}
+
+char* ui_selection_gettext(UiDnD *sel) {
+    if(!sel->data) {
+        return NULL;
+    }
+    
+    guchar *text = gtk_selection_data_get_text(sel->data);
+    if(text) {
+        char *textcp = strdup((char*)text);
+        g_free(text);
+        return textcp;
+    }
+    return NULL;
+}
+
+UiFileList ui_selection_geturis(UiDnD *sel) {
+    if(!sel->data) {
+        return (UiFileList){NULL,0};
+    }
+    
+    gchar **uris = gtk_selection_data_get_uris(sel->data);
+    if(uris) {
+        size_t al = 32;
+        char **array = malloc(al * sizeof(char*));
+        size_t i = 0;
+        while(uris[i] != NULL) {
+            if(i >= al) {
+                al *= 2;
+                array = realloc(array, al * sizeof(char*));
+            }
+            array[i] = strdup((char*)uris[i]);
+            i++;
+        }
+        g_strfreev(uris);
+        return (UiFileList){array,i};
+    }
+    
+    return (UiFileList){NULL,0};
+}
+
+UiDnDAction ui_dnd_result(UiDnD *dnd) {
+    switch(dnd->selected_action) {
+        case 0: return UI_DND_ACTION_NONE;
+        case GDK_ACTION_COPY: return UI_DND_ACTION_COPY;
+        case GDK_ACTION_MOVE: return UI_DND_ACTION_MOVE;
+        case GDK_ACTION_LINK: return UI_DND_ACTION_LINK;
+        default: break;
+    }
+    return UI_DND_ACTION_CUSTOM;
+}
+
+
+UiDnD* ui_create_dnd(void) {
+    UiDnD *dnd = malloc(sizeof(UiDnD));
+    memset(dnd, 0, sizeof(UiDnD));
+    return dnd;
+}
+
+void ui_dnd_free(UiDnD *dnd) {
+    free(dnd);
+}
+
+#endif
+
+UiBool ui_dnd_need_delete(UiDnD *dnd) {
+    return dnd->delete;
+}
+
+void ui_dnd_accept(UiDnD *dnd, UiBool accept) {
+    dnd->accept = accept;
+}
+

mercurial