From 0692fd89fdb6473741055d020f3c5c0510132f9c Mon Sep 17 00:00:00 2001 From: Michael Homer Date: Thu, 19 Jun 2014 21:17:00 +1200 Subject: Initial commit --- Makefile | 9 +++ dragon.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 Makefile create mode 100644 dragon.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cf8bbb1 --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +PREFIX = $(HOME)/.local/bin + +all: dragon + +dragon: dragon.c + $(CC) --std=c99 -Wall $(DEFINES) dragon.c -o dragon `pkg-config --cflags gtk+-3.0` `pkg-config --libs gtk+-3.0` + +install: dragon + cp dragon $(PREFIX) diff --git a/dragon.c b/dragon.c new file mode 100644 index 0000000..a655df3 --- /dev/null +++ b/dragon.c @@ -0,0 +1,215 @@ +// dragon - very lightweight DnD file source/target +// Copyright 2014 Michael Homer. +// +// 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 3 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, see . +#define _POSIX_C_SOURCE 200809L +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include + +#define VERSION "0.3.0" + + +GtkWidget *window; +GtkWidget *vbox; + +char *progname; +bool verbose = false; +int mode = 0; + +#define MODE_HELP 1 +#define MODE_LIST_CONFIGS 2 +#define MODE_BACKENDS 3 +#define MODE_VERSION 4 + +#define TARGET_TYPE_TEXT 1 +#define TARGET_TYPE_URI 2 + +struct draggable_thing { + char *text; + char *uri; + guint last_time; +}; + +void do_quit(GtkWidget *widget, gpointer data) { + exit(0); +} + +void button_clicked(GtkWidget *widget, gpointer user_data) { + struct draggable_thing *dd = (struct draggable_thing *)user_data; + if (0 == fork()) { + execlp("xdg-open", "xdg-open", dd->uri, NULL); + } +} + +void drag_data_get(GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *data, + guint info, + guint time, + gpointer user_data) { + struct draggable_thing *dd = (struct draggable_thing *)user_data; + if (info == TARGET_TYPE_URI) { + if (verbose) + printf("Writing as URI: %s\n", dd->uri); + char *uris[] = {dd->uri, NULL}; + gtk_selection_data_set_uris(data, uris); + g_signal_stop_emission_by_name(widget, "drag-data-get"); + } else if (info == TARGET_TYPE_TEXT) { + if (verbose) + printf("Writing as TEXT: %s\n", dd->text); + gtk_selection_data_set_text(data, dd->text, -1); + } else { + fprintf(stderr, "Error: bad target type %i\n", info); + } +} + +void add_button(char *label, struct draggable_thing *dragdata, int type) { + GtkWidget *button = gtk_button_new(); + gtk_button_set_label(GTK_BUTTON(button), label); + GtkTargetList *targetlist = gtk_drag_source_get_target_list(GTK_WIDGET(button)); + if (targetlist) + gtk_target_list_ref(targetlist); + else + targetlist = gtk_target_list_new(NULL, 0); + if (type == TARGET_TYPE_URI) + gtk_target_list_add_uri_targets(targetlist, TARGET_TYPE_URI); + else + gtk_target_list_add_text_targets(targetlist, TARGET_TYPE_TEXT); + gtk_drag_source_set(GTK_WIDGET(button), GDK_BUTTON1_MASK, NULL, 0, + GDK_ACTION_DEFAULT | GDK_ACTION_LINK | GDK_ACTION_COPY); + gtk_drag_source_set_target_list(GTK_WIDGET(button), targetlist); + g_signal_connect(GTK_WIDGET(button), "drag-data-get", + G_CALLBACK(drag_data_get), dragdata); + g_signal_connect(GTK_WIDGET(button), "clicked", + G_CALLBACK(button_clicked), dragdata); + + gtk_container_add(GTK_CONTAINER(vbox), button); +} + +void add_file_button(char *ufilename, char *filename) { + char *uri = malloc(strlen(filename) + 8); // file:// + NULL + strcpy(uri, "file://"); + strcat(uri, filename); + struct draggable_thing *dragdata = malloc(sizeof(struct draggable_thing)); + dragdata->text = filename; + dragdata->uri = uri; + add_button(ufilename, dragdata, TARGET_TYPE_URI); +} + +void add_uri_button(char *uri) { + struct draggable_thing *dragdata = malloc(sizeof(struct draggable_thing)); + dragdata->text = uri; + dragdata->uri = uri; + add_button(uri, dragdata, TARGET_TYPE_URI); +} + +bool is_uri(char *uri) { + for (int i=0; uri[i]; i++) + if (uri[i] == '/') + return false; + else if (uri[i] == ':') + return true; + return false; +} + +int main (int argc, char **argv) { + progname = argv[0]; + char *filename = NULL; + char *ufilename = NULL; + for (int i=1; i