aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Homer <mwh@mwh.geek.nz>2014-06-19 21:17:00 +1200
committerMichael Homer <mwh@mwh.geek.nz>2014-06-19 21:17:00 +1200
commit0692fd89fdb6473741055d020f3c5c0510132f9c (patch)
tree47a8125319c3ba6dc96b385ffdb4b5896f4aceb2
downloaddragon-0692fd89fdb6473741055d020f3c5c0510132f9c.tar.gz
dragon-0692fd89fdb6473741055d020f3c5c0510132f9c.tar.bz2
dragon-0692fd89fdb6473741055d020f3c5c0510132f9c.zip
Initial commit
-rw-r--r--Makefile9
-rw-r--r--dragon.c215
2 files changed, 224 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>.
+#define _POSIX_C_SOURCE 200809L
+#define _XOPEN_SOURCE 500
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#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<argc; i++) {
+ if (strcmp(argv[i], "--help") == 0) {
+ mode = MODE_HELP;
+ } else if (strcmp(argv[i], "--version") == 0) {
+ mode = MODE_VERSION;
+ } else if (strcmp(argv[i], "-v") == 0
+ || strcmp(argv[i], "--verbose") == 0) {
+ verbose = true;
+ } else if (argv[i][0] == '-') {
+ fprintf(stderr, "%s: error: unknown option `%s'.\n",
+ progname, argv[i]);
+ }
+ }
+ switch(mode) {
+ case MODE_VERSION:
+ puts("dragon " VERSION);
+ puts("Copyright (C) 2014 Michael Homer");
+ puts("This program comes with ABSOLUTELY NO WARRANTY.");
+ puts("See the source for copying conditions.");
+ exit(0);
+ case MODE_HELP:
+ printf("dragon - lightweight DnD source/target\n");
+ printf("Usage: %s [OPTION] [FILENAME]\n", argv[0]);
+ printf(" --verbose, -v be verbose\n");
+ printf(" --help show help\n");
+ printf(" --version show version details\n");
+ exit(0);
+ }
+ GtkAccelGroup *accelgroup;
+ GClosure *closure;
+
+ gtk_init(&argc, &argv);
+
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+ closure = g_cclosure_new(G_CALLBACK(do_quit), NULL, NULL);
+ accelgroup = gtk_accel_group_new();
+ gtk_accel_group_connect(accelgroup, GDK_KEY_Escape, 0, 0, closure);
+ gtk_window_add_accel_group(GTK_WINDOW(window), accelgroup);
+
+ gtk_window_set_title(GTK_WINDOW(window), "Run");
+ gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
+
+ g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
+
+ vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
+
+ bool had_filename = false;
+ for (int i=1; i<argc; i++) {
+ if (argv[i][0] != '-') {
+ filename = ufilename = argv[i];
+ if (!is_uri(filename)) {
+ filename = realpath(filename, NULL);
+ if (!filename) {
+ fprintf(stderr, "The file `%s' does not exist.\n",
+ ufilename);
+ exit(1);
+ }
+ add_file_button(ufilename, filename);
+ } else {
+ add_uri_button(filename);
+ }
+ had_filename = true;
+ }
+ }
+ if (!had_filename) {
+ printf("Usage: %s [OPTIONS] FILENAME\n", progname);
+ exit(0);
+ }
+
+ gtk_container_add(GTK_CONTAINER(window), vbox);
+
+ gtk_window_set_title(GTK_WINDOW(window), "dragon");
+
+ gtk_widget_show_all(window);
+
+ gtk_main();
+
+ return 0;
+}
bgstack15