[gnome-flashback] desktop: setup drop destination
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] desktop: setup drop destination
- Date: Sun, 24 Nov 2019 16:49:34 +0000 (UTC)
commit 1039b337b7e931aa106338857ed119d67148e9bd
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Sun Nov 24 18:44:16 2019 +0200
desktop: setup drop destination
gnome-flashback/libdesktop/gf-monitor-view.c | 300 +++++++++++++++++++++++++++
1 file changed, 300 insertions(+)
---
diff --git a/gnome-flashback/libdesktop/gf-monitor-view.c b/gnome-flashback/libdesktop/gf-monitor-view.c
index bd9e84f..519e38a 100644
--- a/gnome-flashback/libdesktop/gf-monitor-view.c
+++ b/gnome-flashback/libdesktop/gf-monitor-view.c
@@ -21,6 +21,7 @@
#include "gf-desktop-enum-types.h"
#include "gf-dummy-icon.h"
#include "gf-icon.h"
+#include "gf-utils.h"
struct _GfMonitorView
{
@@ -56,6 +57,8 @@ struct _GfMonitorView
int offset_y;
GHashTable *grid;
+
+ gboolean drop_pending;
};
enum
@@ -317,6 +320,301 @@ find_free_grid_position (GfMonitorView *self,
return FALSE;
}
+static void
+add_drag_rectangles_from_icon_list (GfMonitorView *self,
+ GfIcon *drag_icon,
+ GPtrArray *rectangles)
+{
+ GList *selected_icons;
+ GList *l;
+
+ selected_icons = gf_icon_view_get_selected_icons (self->icon_view);
+ if (selected_icons == NULL)
+ return;
+
+ for (l = selected_icons; l != NULL; l = l->next)
+ {
+ GfIcon *icon;
+ GtkWidget *image;
+ double press_x;
+ double press_y;
+ GdkRectangle *rectangle;
+
+ icon = l->data;
+
+ image = gf_icon_get_image (icon);
+ gf_icon_get_press (drag_icon, &press_x, &press_y);
+
+ rectangle = g_new0 (GdkRectangle, 1);
+ g_ptr_array_add (rectangles, rectangle);
+
+ gtk_widget_get_allocation (image, rectangle);
+ gtk_widget_translate_coordinates (image,
+ GTK_WIDGET (drag_icon),
+ -press_x,
+ -press_y,
+ &rectangle->x,
+ &rectangle->y);
+ }
+}
+
+static void
+add_drag_rectangles_from_gnome_icon_list (GfMonitorView *self,
+ const guchar *gnome_icon_list,
+ GPtrArray *rectangles)
+{
+ char **list;
+ double scale;
+ int i;
+
+ list = g_strsplit ((const char *) gnome_icon_list, "\r\n", -1);
+ if (list == NULL)
+ return;
+
+ scale = 1.0 / gf_get_nautilus_scale ();
+
+ for (i = 0; list[i] != NULL; i++)
+ {
+ int x;
+ int y;
+ unsigned short int width;
+ unsigned short int height;
+ GdkRectangle *rectangle;
+
+ if (sscanf (list[i], "%*s\r%d:%d:%hu:%hu", &x, &y, &width, &height) != 4)
+ continue;
+
+ rectangle = g_new0 (GdkRectangle, 1);
+ g_ptr_array_add (rectangles, rectangle);
+
+ rectangle->x = x / scale;
+ rectangle->y = y / scale;
+ rectangle->width = width / scale;
+ rectangle->height = height / scale;
+ }
+
+ g_strfreev (list);
+}
+
+static void
+drag_data_received_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint time,
+ GfMonitorView *self)
+{
+
+ if (data == NULL || gtk_selection_data_get_length (data) == 0)
+ {
+ gtk_drag_finish (context, FALSE, FALSE, time);
+ return;
+ }
+
+ if (self->drop_pending)
+ {
+ GdkWindow *window;
+ GdkDevice *device;
+ GdkModifierType mask;
+ GdkDragAction action;
+ GPtrArray *drag_rectangles;
+
+ window = gdk_drag_context_get_dest_window (context);
+ device = gdk_drag_context_get_device (context);
+
+ gdk_window_get_device_position (window, device, NULL, NULL, &mask);
+
+ action = 0;
+ drag_rectangles = g_ptr_array_new_with_free_func (g_free);
+
+ if (info == 100)
+ {
+ GfIcon *icon;
+
+ icon = *(gpointer *) gtk_selection_data_get_data (data);
+ add_drag_rectangles_from_icon_list (self, icon, drag_rectangles);
+
+ if (mask & GDK_CONTROL_MASK)
+ action = GDK_ACTION_COPY;
+ else
+ action = GDK_ACTION_MOVE;
+ }
+ else if (info == 200)
+ {
+ const guchar *selection_data;
+
+ selection_data = gtk_selection_data_get_data (data);
+ add_drag_rectangles_from_gnome_icon_list (self,
+ selection_data,
+ drag_rectangles);
+
+ if (mask & GDK_CONTROL_MASK)
+ action = GDK_ACTION_COPY;
+ else
+ action = GDK_ACTION_MOVE;
+ }
+ else if (info == 300)
+ {
+ action = GDK_ACTION_COPY;
+ }
+
+ gdk_drag_status (context, action, time);
+
+ gf_icon_view_set_drag_rectangles (self->icon_view, drag_rectangles);
+ g_ptr_array_unref (drag_rectangles);
+ }
+ else
+ {
+ gboolean success;
+ gboolean delete;
+ GdkDragAction action;
+
+ success = FALSE;
+ delete = FALSE;
+
+ action = gdk_drag_context_get_selected_action (context);
+
+ if (info == 100)
+ {
+ if (action == GDK_ACTION_MOVE &&
+ self->placement != GF_PLACEMENT_AUTO_ARRANGE_ICONS)
+ {
+ }
+ else if (action == GDK_ACTION_COPY)
+ {
+ }
+ }
+ else if (info == 200)
+ {
+ if (action == GDK_ACTION_MOVE)
+ {
+ }
+ else if (action == GDK_ACTION_COPY)
+ {
+ }
+ }
+ else if (info == 300)
+ {
+ if (action == GDK_ACTION_COPY)
+ {
+ }
+ }
+
+ gtk_drag_finish (context, success, delete, time);
+ }
+}
+
+static gboolean
+drag_drop_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time,
+ GfMonitorView *self)
+{
+ GtkTargetList *target_list;
+ GList *list_targets;
+ GList *l;
+
+ target_list = gtk_drag_dest_get_target_list (widget);
+ list_targets = gdk_drag_context_list_targets (context);
+
+ for (l = list_targets; l != NULL; l = l->next)
+ {
+ GdkAtom atom;
+
+ atom = GDK_POINTER_TO_ATOM (l->data);
+
+ if (gtk_target_list_find (target_list, atom, NULL))
+ {
+ self->drop_pending = FALSE;
+ gtk_drag_get_data (widget, context, atom, time);
+
+ return TRUE;
+ }
+ }
+
+ gtk_drag_finish (context, FALSE, FALSE, time);
+
+ return TRUE;
+}
+
+static void
+drag_leave_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time,
+ GfMonitorView *self)
+{
+ gf_icon_view_set_drag_rectangles (self->icon_view, NULL);
+}
+
+static gboolean
+drag_motion_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time,
+ GfMonitorView *self)
+{
+ GdkAtom target;
+
+ target = gtk_drag_dest_find_target (widget, context, NULL);
+
+ if (target == GDK_NONE ||
+ gdk_drag_context_get_suggested_action (context) == 0)
+ {
+ gdk_drag_status (context, 0, time);
+ return TRUE;
+ }
+
+ self->drop_pending = TRUE;
+ gtk_drag_get_data (widget, context, target, time);
+
+ return TRUE;
+}
+
+static void
+setup_drop_destination (GfMonitorView *self)
+{
+ GdkDragAction actions;
+ GtkDestDefaults defaults;
+ GtkTargetList *target_list;
+ GdkAtom target;
+
+ actions = GDK_ACTION_COPY | GDK_ACTION_MOVE;
+ defaults = 0;
+
+ gtk_drag_dest_set (GTK_WIDGET (self), 0, NULL, defaults, actions);
+
+ target_list = gtk_target_list_new (NULL, 0);
+
+ target = gdk_atom_intern_static_string ("x-gnome-flashback/icon-list");
+ gtk_target_list_add (target_list, target, GTK_TARGET_SAME_APP, 100);
+
+ target = gdk_atom_intern_static_string ("x-special/gnome-icon-list");
+ gtk_target_list_add (target_list, target, 0, 200);
+
+ target = gdk_atom_intern_static_string ("text/uri-list");
+ gtk_target_list_add (target_list, target, 0, 300);
+
+ gtk_drag_dest_set_target_list (GTK_WIDGET (self), target_list);
+ gtk_target_list_unref (target_list);
+
+ g_signal_connect (self, "drag-data-received",
+ G_CALLBACK (drag_data_received_cb), self);
+
+ g_signal_connect (self, "drag-drop",
+ G_CALLBACK (drag_drop_cb), self);
+
+ g_signal_connect (self, "drag-leave",
+ G_CALLBACK (drag_leave_cb), self);
+
+ g_signal_connect (self, "drag-motion",
+ G_CALLBACK (drag_motion_cb), self);
+}
+
static void
calculate_grid_size (GfMonitorView *self)
{
@@ -740,6 +1038,8 @@ gf_monitor_view_init (GfMonitorView *self)
{
self->grid = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
(GDestroyNotify) g_ptr_array_unref);
+
+ setup_drop_destination (self);
}
GtkWidget *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]