diff options
| author | Mattias Andrée <m@maandree.se> | 2026-10-11 23:01:38 +0200 |
|---|---|---|
| committer | Mattias Andrée <m@maandree.se> | 2026-10-11 23:29:28 +0200 |
| commit | 94659550993f454e12e4bcb8cf93a5ff258bc08c (patch) | |
| tree | f8e1cfe9fbcdec6f09b6cc18c761684dc34505d2 /dragging.c | |
| parent | First commit (diff) | |
| download | gbild-94659550993f454e12e4bcb8cf93a5ff258bc08c.tar.gz gbild-94659550993f454e12e4bcb8cf93a5ff258bc08c.tar.bz2 gbild-94659550993f454e12e4bcb8cf93a5ff258bc08c.tar.xz | |
Second commit
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to '')
| -rw-r--r-- | dragging.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/dragging.c b/dragging.c new file mode 100644 index 0000000..3ac3ff5 --- /dev/null +++ b/dragging.c @@ -0,0 +1,135 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +static char url_list_name[] = "text/uri-list"; +static GtkTargetEntry url_list = {url_list_name, 0u, 0u}; + +static int dragging = 0; +static int drag_source_disabled = 0; +static int drag_x, drag_y; + +static void +set_file_drag_source(GtkWidget *widget) +{ + gtk_drag_source_set(widget, GDK_BUTTON1_MASK, &url_list, 1u, + GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK); +} + +static int +button_pressed(GtkWidget *widget, GdkEventButton *event, void *user) +{ + (void) user; + if (event->button == 2u || (event->state & GDK_CONTROL_MASK)) { + if (event->button == 1u) { + gtk_drag_source_unset(widget); + drag_source_disabled = 1; + } + dragging = 1; + drag_x = (int)event->x_root; + drag_y = (int)event->y_root; + } + return dragging; +} + +static int +button_released(GtkWidget *widget, GdkEventButton *event, void *user) +{ + (void) event; + (void) user; + dragging = 0; + if (drag_source_disabled) { + set_file_drag_source(widget); + drag_source_disabled = 0; + } + return 0; +} + +static int +pointer_moved(GtkWidget *widget, GdkEventMotion *event, void *user) +{ + int x, y; + (void) event; + (void) user; + if (dragging) { + gdk_display_get_pointer(gtk_widget_get_display(widget), NULL, &x, &y, NULL); + scroll_by(drag_x - x, drag_y - y); + drag_x = x; + drag_y = y; + } + return dragging; +} + +static void +drag_begin(GtkWidget *widget, GdkDragContext *context, void *user) +{ + GdkPixbuf *image, *icon; + intmax_t height, width; + + (void) widget; + (void) user; + + image = get_original_image(); + if (!image) + return; + + width = gdk_pixbuf_get_width(image); + height = gdk_pixbuf_get_height(image); + if (width <= DRAG_ICON_SIZE && height <= DRAG_ICON_SIZE) { + gtk_drag_set_icon_pixbuf(context, image, 0, 0); + return; + } + if (width >= height) { + height = height * DRAG_ICON_SIZE / width; + height = MAX(1, height); + width = DRAG_ICON_SIZE; + } else { + width = width * DRAG_ICON_SIZE / height; + width = MAX(1, width); + height = DRAG_ICON_SIZE; + } + icon = gdk_pixbuf_scale_simple(image, (int)width, (int)height, GDK_INTERP_BILINEAR); + if (!icon) + return; + gtk_drag_set_icon_pixbuf(context, icon, 0, 0); + g_object_unref(icon); +} + +static void +drag_data_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *data, + unsigned int info, unsigned int time, void *user) +{ + struct file *file = get_file(); + GError *error = NULL; + char *uri; + + (void) widget; + (void) context; + (void) info; + (void) time; + (void) user; + + if (!file || !file->path) + return; + + uri = g_filename_to_uri(file->path, NULL, &error); + if (!uri) { + weprintf("g_filename_to_uri: %s", error->message); + g_error_free(error); + return; + } + gtk_selection_data_set_uris(data, (char *[]){uri, NULL}); + g_free(uri); +} + +void +set_up_dragging(void) +{ + set_file_drag_source(display_area); + + g_signal_connect(display_area, "button-press-event", G_CALLBACK(&button_pressed), NULL); + g_signal_connect(display_area, "button-release-event", G_CALLBACK(&button_released), NULL); + g_signal_connect(display_area, "motion-notify-event", G_CALLBACK(&pointer_moved), NULL); + + g_signal_connect(display_area, "drag-begin", G_CALLBACK(&drag_begin), NULL); + g_signal_connect(display_area, "drag-data-get", G_CALLBACK(&drag_data_get), NULL); +} |
