aboutsummaryrefslogtreecommitdiffstats
path: root/dropping.c
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2026-10-13 23:00:56 +0200
committerMattias Andrée <m@maandree.se>2026-10-13 23:00:56 +0200
commit0476071164c36b41de5b19e3e8a768feb422f27f (patch)
tree09d16e177042b14020a48030176d99e9024bea66 /dropping.c
parentThird commit (diff)
downloadgbild-0476071164c36b41de5b19e3e8a768feb422f27f.tar.gz
gbild-0476071164c36b41de5b19e3e8a768feb422f27f.tar.bz2
gbild-0476071164c36b41de5b19e3e8a768feb422f27f.tar.xz
Fourth commit
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to '')
-rw-r--r--dropping.c65
1 files changed, 64 insertions, 1 deletions
diff --git a/dropping.c b/dropping.c
index 412f0ab..e7bf20f 100644
--- a/dropping.c
+++ b/dropping.c
@@ -4,7 +4,12 @@
static char url_list_name[] = "text/uri-list";
static GtkTargetEntry url_list = {url_list_name, 0u, 0u};
-static size_t
+static unsigned int active_drop_timer;
+static GdkDragContext *active_drop_context;
+static GtkWidget *active_drop_widget;
+static GdkDragAction active_drop_action;
+
+size_t
get_dropped_files(struct file **files_out, char **uris)
{
GError *error = NULL;
@@ -55,6 +60,18 @@ drop_files(GtkWidget *widget, GdkDragContext *context, int x, int y,
(void) info;
(void) user;
+ if (active_drop_timer) {
+ g_source_remove(active_drop_timer);
+ active_drop_timer = 0;
+ }
+
+ if (gtk_drag_get_source_widget(context) == collection_view) {
+ if (widget == display_area)
+ navigate_collection_drag();
+ else
+ accepted = 0;
+ goto out;
+ }
if (gtk_drag_get_source_widget(context) == display_area) {
accepted = 0;
goto out;
@@ -85,6 +102,31 @@ out:
}
static int
+poll_modifiers(void *user)
+{
+ GdkModifierType modifiers;
+ GdkDragAction action = 0;
+
+ (void) user;
+
+ if (!GTK_WIDGET_REALIZED(active_drop_widget))
+ return 1;
+
+ gdk_window_get_pointer(active_drop_widget->window, NULL, NULL, &modifiers);
+
+ action = (modifiers & GDK_CONTROL_MASK) ? GDK_ACTION_COPY : GDK_ACTION_MOVE;
+ if (!(gdk_drag_context_get_actions(active_drop_context) & action))
+ action = 0;
+
+ if (action != active_drop_action) {
+ active_drop_action = action;
+ gdk_drag_status(active_drop_context, action, GDK_CURRENT_TIME);
+ }
+
+ return 1;
+}
+
+static int
drop_motion(GtkWidget *widget, GdkDragContext *context, int x, int y, unsigned int time, void *user)
{
GdkWindow *event_window = gtk_widget_get_window(widget);
@@ -107,14 +149,35 @@ drop_motion(GtkWidget *widget, GdkDragContext *context, int x, int y, unsigned i
out:
gdk_drag_status(context, action, time);
+
+ if (!active_drop_timer) {
+ active_drop_context = context;
+ active_drop_widget = widget;
+ active_drop_action = action;
+ active_drop_timer = g_timeout_add(50, &poll_modifiers, NULL);
+ }
return 1;
}
+static void
+drop_leave(GtkWidget *widget, GdkDragContext *context, unsigned int time, void *user)
+{
+ (void) widget;
+ (void) context;
+ (void) time;
+ (void) user;
+ if (active_drop_timer) {
+ g_source_remove(active_drop_timer);
+ active_drop_timer = 0;
+ }
+}
+
void
set_up_dropping(void)
{
gtk_drag_dest_set(window, GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP,
&url_list, 1u, GDK_ACTION_COPY | GDK_ACTION_MOVE);
g_signal_connect(window, "drag-motion", G_CALLBACK(&drop_motion), NULL);
+ g_signal_connect(window, "drag-leave", G_CALLBACK(&drop_leave), NULL);
g_signal_connect(window, "drag-data-received", G_CALLBACK(&drop_files), NULL);
}