[gnome-applets/wip/segeiger/windowpicker: 2/2] windowpicker: fix drag and drop crash
- From: Sebastian Geiger <segeiger src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-applets/wip/segeiger/windowpicker: 2/2] windowpicker: fix drag and drop crash
- Date: Tue, 15 Oct 2019 18:16:09 +0000 (UTC)
commit b09b560c193bd1131d4ca13c6d9b21b473ed50bb
Author: Sebastian Geiger <sbastig gmx net>
Date: Tue Oct 15 19:51:40 2019 +0200
windowpicker: fix drag and drop crash
This fixes several issues in the drag and drop logic:
* The value 0 for info parameter in drop_types of 'STRING',
'text/plain' and 'text/uri-list' collided with the first enum value
of TARGET_WIDGET_DRAGGED.
This caused a crash in the applet when strings were dragged onto
a task item.
* The entries for TARGET_ITEM_DRAGGED in drag_types and drop_types were unnecessary,
since they only applied with flag GTK_TARGET_SAME_WIDGET, but we are only
interested in dragging a task item onto another task item.
* The lookup for the target atom in the 'on_drag_motion' handler was incorrect,
since it ignored the type of the drag source and assumed that a lookup
of the target atom was possible with a fixed index of TARGET_WIDGET_DRAGGED.
The correct solution is to check each target atom of the context against the
possible targets in drop_types and return the first match.
windowpicker/src/task-item.c | 134 +++++++++++++++++++++++++++----------------
1 file changed, 85 insertions(+), 49 deletions(-)
---
diff --git a/windowpicker/src/task-item.c b/windowpicker/src/task-item.c
index bd36a2481..a029479d4 100644
--- a/windowpicker/src/task-item.c
+++ b/windowpicker/src/task-item.c
@@ -56,23 +56,21 @@ static guint task_item_signals[LAST_SIGNAL] = { 0 };
/* D&D stuff */
enum {
- TARGET_WIDGET_DRAGGED, /* if this item is dragged */
- TARGET_ITEM_DRAGGED
+ TARGET_STRING_DRAGGED,
+ TARGET_TASK_ITEM_DRAGGED /* if this item is dragged */
};
static const GtkTargetEntry drop_types[] = {
- { (gchar *) "STRING", 0, 0 },
- { (gchar *) "text/plain", 0, 0},
- { (gchar *) "text/uri-list", 0, 0},
- { (gchar *) "widget", GTK_TARGET_OTHER_WIDGET, TARGET_WIDGET_DRAGGED }, //drag and drop target
- { (gchar *) "item", GTK_TARGET_SAME_WIDGET, TARGET_ITEM_DRAGGED }
+ { (gchar *) "STRING", 0, TARGET_STRING_DRAGGED },
+ { (gchar *) "text/plain", 0, TARGET_STRING_DRAGGED },
+ { (gchar *) "text/uri-list", 0, TARGET_STRING_DRAGGED },
+ { (gchar *) "task-item", GTK_TARGET_OTHER_WIDGET | GTK_TARGET_SAME_APP, TARGET_TASK_ITEM_DRAGGED } //
drag and drop target
};
static const gint n_drop_types = G_N_ELEMENTS(drop_types);
static const GtkTargetEntry drag_types[] = {
- { (gchar *) "widget", GTK_TARGET_OTHER_WIDGET, TARGET_WIDGET_DRAGGED }, //drag and drop source
- { (gchar *) "item", GTK_TARGET_SAME_WIDGET, TARGET_ITEM_DRAGGED }
+ { (gchar *) "task-item", GTK_TARGET_OTHER_WIDGET | GTK_TARGET_SAME_APP, TARGET_TASK_ITEM_DRAGGED } //
drag and drop source
};
static const gint n_drag_types = G_N_ELEMENTS(drag_types);
@@ -630,36 +628,74 @@ static void on_drag_leave (
g_object_set_data (G_OBJECT (item), "drag-true", GINT_TO_POINTER (0));
}
+static gboolean
+find_drop_type_by_name (char *source_name)
+{
+ for (gulong i = 0; i < G_N_ELEMENTS (drop_types); i++)
+ {
+ gchar * target_name;
+
+ target_name = drop_types[i].target;
+
+ if (g_strcmp0 (source_name, target_name) == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/* Emitted when a drag is over the destination */
-static gboolean on_drag_motion (
- GtkWidget *item,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time)
+static gboolean
+on_drag_motion (GtkWidget *item,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time)
{
- GdkAtom target_type = NULL;
+ GdkAtom target;
+ GList *targets;
+ GList *current;
- if (gdk_drag_context_list_targets(context)) {
- /* Choose the best target type */
- target_type = GDK_POINTER_TO_ATOM (
- g_list_nth_data (
- gdk_drag_context_list_targets(context),
- TARGET_WIDGET_DRAGGED
- )
- );
- g_assert(target_type != NULL);
+ target = NULL;
+ targets = gdk_drag_context_list_targets(context);
- gtk_drag_get_data (
- item, // will receive 'drag-data-received' signal
- context, // represents the current state of the DnD
- target_type, // the target type we want
- time // time stamp
- );
- } else {
+ if (targets == NULL)
+ {
g_warning("Drag ended without target");
- }
- return FALSE;
+ return FALSE;
+ }
+
+ current = targets;
+
+ while (current != NULL)
+ {
+ GdkAtom *atom = current->data;
+ char *name;
+ gboolean found;
+
+ found = FALSE;
+
+ /* Choose the best target type */
+ target = GDK_POINTER_TO_ATOM (atom);
+ name = gdk_atom_name (target);
+
+ found = find_drop_type_by_name (name);
+ g_free (name);
+
+ if (found)
+ break;
+
+ current = g_list_next (current);
+ }
+
+ g_assert(target != NULL);
+
+ gtk_drag_get_data (item, // will receive 'drag-data-received' signal
+ context, // represents the current state of the DnD
+ target, // the target type we want
+ time); // time stamp
+
+ return FALSE;
}
@@ -685,20 +721,20 @@ on_drag_get_data (GtkWidget *widget,
guint time,
gpointer user_data)
{
- switch(target_type) {
- case TARGET_WIDGET_DRAGGED:
- g_assert(user_data != NULL && TASK_IS_ITEM(user_data));
- gtk_selection_data_set(
- selection_data,
- gtk_selection_data_get_target (selection_data),
- 8,
- (guchar*) &user_data,
- sizeof(gpointer*)
- );
- break;
- default:
- g_assert_not_reached ();
- }
+ TaskItem *item;
+
+ g_assert(user_data != NULL && TASK_IS_ITEM(user_data));
+
+ item = TASK_ITEM (user_data);
+
+ if (target_type != TARGET_TASK_ITEM_DRAGGED)
+ g_assert_not_reached ();
+
+ gtk_selection_data_set (selection_data,
+ gtk_selection_data_get_target (selection_data),
+ 8,
+ (guchar*) &item,
+ sizeof (TaskItem*));
}
static void on_drag_end (
@@ -737,7 +773,7 @@ static void on_drag_received_data (
if((selection_data != NULL) && (gtk_selection_data_get_length(selection_data) >= 0)) {
gint active;
switch (target_type) {
- case TARGET_WIDGET_DRAGGED: {
+ case TARGET_TASK_ITEM_DRAGGED: {
GtkWidget *taskItem;
GtkWidget *taskList;
gint target_position;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]