From 30b358a302ee2607752457c18a4b160d5e54e764 Mon Sep 17 00:00:00 2001 Message-Id: <30b358a302ee2607752457c18a4b160d5e54e764.1714992625.git.mdw@distorted.org.uk> From: Mark Wooding Date: Fri, 13 Nov 2009 21:00:31 +0000 Subject: [PATCH] Comments, esp. for multidrag Organization: Straylight/Edgeware From: Richard Kettlewell --- disobedience/multidrag.c | 31 ++++++++++++++++++++++++++++--- disobedience/queue-generic.c | 15 +++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/disobedience/multidrag.c b/disobedience/multidrag.c index 95a133a..650d1c4 100644 --- a/disobedience/multidrag.c +++ b/disobedience/multidrag.c @@ -17,6 +17,23 @@ */ /** @file disobedience/multidrag.c * @brief Drag multiple rows of a GtkTreeView + * + * Normally when you start a drag, GtkTreeView sets the selection to just row + * you dragged from (because it can't cope with dragging more than one row at a + * time). + * + * Disobedience needs more. To implement this it intercepts button-press-event + * and button-release event and for clicks that might be the start of drags, + * suppresses changes to the selection. A consequence of this is that it needs + * to intercept button-release-event too, to restore the effect of the click, + * if it turns out not to be drag after all. + * + * The location of the initial click is stored in object data called @c + * multidrag-where. + * + * Inspired by similar code in Quodlibet (another software + * jukebox, albeit as far as I can see a single-user one). */ #include "disobedience.h" @@ -25,16 +42,16 @@ static gboolean multidrag_selection_block(GtkTreeSelection attribute((unused)) * GtkTreePath attribute((unused)) *path, gboolean attribute((unused)) path_currently_selected, gpointer data) { - return *(gboolean *)data; + return *(const gboolean *)data; } static void block_selection(GtkWidget *w, gboolean block, int x, int y) { - static gboolean which[] = { FALSE, TRUE }; + static const gboolean which[] = { FALSE, TRUE }; GtkTreeSelection *s = gtk_tree_view_get_selection(GTK_TREE_VIEW(w)); gtk_tree_selection_set_select_function(s, multidrag_selection_block, - &which[!!block], + (gboolean *)&which[!!block], NULL); // Remember the pointer location int *where = g_object_get_data(G_OBJECT(w), "multidrag-where"); @@ -44,6 +61,7 @@ static void block_selection(GtkWidget *w, gboolean block, } where[0] = x; where[1] = y; + // TODO release 'where' when object is destroyed } static gboolean multidrag_button_press_event(GtkWidget *w, @@ -82,6 +100,8 @@ static gboolean multidrag_button_release_event(GtkWidget *w, gpointer attribute((unused)) user_data) { int *where = g_object_get_data(G_OBJECT(w), "multidrag-where"); + /* Did button-press-event do anything? We just check the outcome rather than + * going through all the conditions it tests. */ if(where && where[0] != -1) { // Remember where the down-click was const int x = where[0], y = where[1]; @@ -104,6 +124,11 @@ static gboolean multidrag_button_release_event(GtkWidget *w, return FALSE; /* propagate */ } +/** @brief Allow multi-row drag for @p w + * @param w A GtkTreeView widget + * + * Suppresses the restriction of selections when a drag is started. + */ void make_treeview_multidrag(GtkWidget *w) { g_signal_connect(w, "button-press-event", G_CALLBACK(multidrag_button_press_event), NULL); diff --git a/disobedience/queue-generic.c b/disobedience/queue-generic.c index 2db2e1d..045b38a 100644 --- a/disobedience/queue-generic.c +++ b/disobedience/queue-generic.c @@ -501,6 +501,15 @@ static void ql_drag_begin(GtkWidget attribute((unused)) *w, NULL); } +/** @brief Called when a drag moves within a candidate destination + * @param w Destination widget + * @param dc Drag context + * @param x Current pointer location + * @param y Current pointer location + * @param time_ Current time + * @param user_data Pointer to queuelike + * @return TRUE in a dropzone, otherwise FALSE + */ static gboolean ql_drag_motion(GtkWidget *w, GdkDragContext *dc, gint x, @@ -563,6 +572,12 @@ static gboolean ql_drag_motion(GtkWidget *w, return TRUE; } +/** @brief Called when a drag moves leaves a candidate destination + * @param w Destination widget + * @param dc Drag context + * @param time_ Current time + * @param user_data Pointer to queuelike + */ static void ql_drag_leave(GtkWidget *w, GdkDragContext attribute((unused)) *dc, guint attribute((unused)) time_, -- [mdw]