Bug Summary

File:libbaul-private/baul-icon-dnd.c
Warning:line 1905, column 22
This statement is never executed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name baul-icon-dnd.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/libbaul-private -fcoverage-compilation-dir=/rootdir/libbaul-private -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/cafe-desktop-2.0 -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/startup-notification-1.0 -I /usr/include/dconf -I /usr/include/cail-3.0 -I /usr/include/libxml2 -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D DATADIR="/usr/share" -D SYSCONFDIR="/usr/etc" -D BAUL_DATADIR="/usr/share/baul" -D BAUL_EXTENSIONDIR="/usr/lib/baul/extensions-2.0" -D PIC -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2025-01-24-095740-27604-1 -x c baul-icon-dnd.c
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* baul-icon-dnd.c - Drag & drop handling for the icon container widget.
4
5 Copyright (C) 1999, 2000 Free Software Foundation
6 Copyright (C) 2000 Eazel, Inc.
7
8 The Cafe Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
12
13 The Cafe Library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
17
18 You should have received a copy of the GNU Library General Public
19 License along with the Cafe Library; see the file COPYING.LIB. If not,
20 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22
23 Authors: Ettore Perazzoli <ettore@gnu.org>,
24 Darin Adler <darin@bentspoon.com>,
25 Andy Hertzfeld <andy@eazel.com>
26 Pavel Cisler <pavel@eazel.com>
27
28
29 XDS support: Benedikt Meurer <benny@xfce.org> (adapted by Amos Brocco <amos.brocco@unifr.ch>)
30
31*/
32
33
34#include <config.h>
35#include <math.h>
36#include <stdio.h>
37#include <string.h>
38
39#include <cdk/cdkkeysyms.h>
40#include <cdk/cdkx.h>
41#include <ctk/ctk.h>
42#include <glib/gi18n.h>
43
44#include <eel/eel-background.h>
45#include <eel/eel-gdk-pixbuf-extensions.h>
46#include <eel/eel-glib-extensions.h>
47#include <eel/eel-cafe-extensions.h>
48#include <eel/eel-graphic-effects.h>
49#include <eel/eel-ctk-extensions.h>
50#include <eel/eel-ctk-macros.h>
51#include <eel/eel-stock-dialogs.h>
52#include <eel/eel-string.h>
53#include <eel/eel-vfs-extensions.h>
54#include <eel/eel-canvas-rect-ellipse.h>
55
56#include "baul-icon-dnd.h"
57#include "baul-debug-log.h"
58#include "baul-file-dnd.h"
59#include "baul-icon-private.h"
60#include "baul-link.h"
61#include "baul-metadata.h"
62#include "baul-file-utilities.h"
63#include "baul-file-changes-queue.h"
64
65static const CtkTargetEntry drag_types [] =
66{
67 { BAUL_ICON_DND_CAFE_ICON_LIST_TYPE"x-special/cafe-icon-list", 0, BAUL_ICON_DND_CAFE_ICON_LIST },
68 { BAUL_ICON_DND_URI_LIST_TYPE"text/uri-list", 0, BAUL_ICON_DND_URI_LIST },
69};
70
71static const CtkTargetEntry drop_types [] =
72{
73 { BAUL_ICON_DND_CAFE_ICON_LIST_TYPE"x-special/cafe-icon-list", 0, BAUL_ICON_DND_CAFE_ICON_LIST },
74 /* prefer "_NETSCAPE_URL" over "text/uri-list" to satisfy web browsers. */
75 { BAUL_ICON_DND_NETSCAPE_URL_TYPE"_NETSCAPE_URL", 0, BAUL_ICON_DND_NETSCAPE_URL },
76 { BAUL_ICON_DND_URI_LIST_TYPE"text/uri-list", 0, BAUL_ICON_DND_URI_LIST },
77 { BAUL_ICON_DND_COLOR_TYPE"application/x-color", 0, BAUL_ICON_DND_COLOR },
78 { BAUL_ICON_DND_BGIMAGE_TYPE"property/bgimage", 0, BAUL_ICON_DND_BGIMAGE },
79 { BAUL_ICON_DND_KEYWORD_TYPE"property/keyword", 0, BAUL_ICON_DND_KEYWORD },
80 { BAUL_ICON_DND_RESET_BACKGROUND_TYPE"x-special/cafe-reset-background", 0, BAUL_ICON_DND_RESET_BACKGROUND },
81 { BAUL_ICON_DND_XDNDDIRECTSAVE_TYPE"XdndDirectSave0", 0, BAUL_ICON_DND_XDNDDIRECTSAVE }, /* XDS Protocol Type */
82 { BAUL_ICON_DND_RAW_TYPE"application/octet-stream", 0, BAUL_ICON_DND_RAW },
83 /* Must be last: */
84 { BAUL_ICON_DND_ROOTWINDOW_DROP_TYPE"application/x-rootwindow-drop", 0, BAUL_ICON_DND_ROOTWINDOW_DROP }
85};
86static void stop_dnd_highlight (CtkWidget *widget);
87static void dnd_highlight_queue_redraw (CtkWidget *widget);
88
89static CtkTargetList *drop_types_list = NULL((void*)0);
90static CtkTargetList *drop_types_list_root = NULL((void*)0);
91
92static char * baul_icon_container_find_drop_target (BaulIconContainer *container,
93 CdkDragContext *context,
94 int x, int y, gboolean *icon_hit,
95 gboolean rewrite_desktop);
96
97static EelCanvasItem *
98create_selection_shadow (BaulIconContainer *container,
99 GList *list)
100{
101 EelCanvasGroup *group;
102 EelCanvas *canvas;
103 int max_x, max_y;
104 int min_x, min_y;
105 GList *p;
106 CtkAllocation allocation;
107
108 if (list == NULL((void*)0))
109 {
110 return NULL((void*)0);
111 }
112
113 /* if we're only dragging a single item, don't worry about the shadow */
114 if (list->next == NULL((void*)0))
115 {
116 return NULL((void*)0);
117 }
118
119 canvas = EEL_CANVAS (container)((((EelCanvas*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((eel_canvas_get_type ()))))))
;
120 ctk_widget_get_allocation (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
, &allocation);
121
122 /* Creating a big set of rectangles in the canvas can be expensive, so
123 we try to be smart and only create the maximum number of rectangles
124 that we will need, in the vertical/horizontal directions. */
125
126 max_x = allocation.width;
127 min_x = -max_x;
128
129 max_y = allocation.height;
130 min_y = -max_y;
131
132 /* Create a group, so that it's easier to move all the items around at
133 once. */
134 group = EEL_CANVAS_GROUP((((EelCanvasGroup*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((eel_canvas_item_new (((((EelCanvasGroup*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((canvas->root)), ((eel_canvas_group_get_type
())))))), eel_canvas_group_get_type (), ((void*)0)))), ((eel_canvas_group_get_type
()))))))
135 (eel_canvas_item_new (EEL_CANVAS_GROUP (canvas->root),((((EelCanvasGroup*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((eel_canvas_item_new (((((EelCanvasGroup*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((canvas->root)), ((eel_canvas_group_get_type
())))))), eel_canvas_group_get_type (), ((void*)0)))), ((eel_canvas_group_get_type
()))))))
136 eel_canvas_group_get_type (),((((EelCanvasGroup*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((eel_canvas_item_new (((((EelCanvasGroup*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((canvas->root)), ((eel_canvas_group_get_type
())))))), eel_canvas_group_get_type (), ((void*)0)))), ((eel_canvas_group_get_type
()))))))
137 NULL))((((EelCanvasGroup*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((eel_canvas_item_new (((((EelCanvasGroup*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((canvas->root)), ((eel_canvas_group_get_type
())))))), eel_canvas_group_get_type (), ((void*)0)))), ((eel_canvas_group_get_type
()))))))
;
138
139 for (p = list; p != NULL((void*)0); p = p->next)
140 {
141 BaulDragSelectionItem *item;
142 int x1, y1, x2, y2;
143 CdkRGBA black = { 0, 0, 0, 1 };
144
145 item = p->data;
146
147 if (!item->got_icon_position)
148 {
149 continue;
150 }
151
152 x1 = item->icon_x;
153 y1 = item->icon_y;
154 x2 = x1 + item->icon_width;
155 y2 = y1 + item->icon_height;
156
157 if (x2 >= min_x && x1 <= max_x && y2 >= min_y && y1 <= max_y)
158 eel_canvas_item_new
159 (group,
160 eel_canvas_rect_get_type (),
161 "x1", (double) x1,
162 "y1", (double) y1,
163 "x2", (double) x2,
164 "y2", (double) y2,
165 "outline-color-rgba", &black,
166 "outline-stippling", TRUE(!(0)),
167 "width_pixels", 1,
168 NULL((void*)0));
169 }
170
171 return EEL_CANVAS_ITEM (group)((((EelCanvasItem*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((group)), ((eel_canvas_item_get_type ()))))))
;
172}
173
174/* Set the affine instead of the x and y position.
175 * Simple, and setting x and y was broken at one point.
176 */
177static void
178set_shadow_position (EelCanvasItem *shadow,
179 double x, double y)
180{
181 eel_canvas_item_set (shadow,
182 "x", x, "y", y,
183 NULL((void*)0));
184}
185
186
187/* Source-side handling of the drag. */
188
189/* iteration glue struct */
190typedef struct
191{
192 gpointer iterator_context;
193 BaulDragEachSelectedItemDataGet iteratee;
194 gpointer iteratee_data;
195} IconGetDataBinderContext;
196
197static void
198canvas_rect_world_to_widget (EelCanvas *canvas,
199 EelDRect *world_rect,
200 EelIRect *widget_rect)
201{
202 EelDRect window_rect;
203 CtkAdjustment *hadj, *vadj;
204
205 hadj = ctk_scrollable_get_hadjustment (CTK_SCROLLABLE (canvas)((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((canvas)), ((ctk_scrollable_get_type ()))))))
);
206 vadj = ctk_scrollable_get_vadjustment (CTK_SCROLLABLE (canvas)((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((canvas)), ((ctk_scrollable_get_type ()))))))
);
207
208 eel_canvas_world_to_window (canvas,
209 world_rect->x0, world_rect->y0,
210 &window_rect.x0, &window_rect.y0);
211 eel_canvas_world_to_window (canvas,
212 world_rect->x1, world_rect->y1,
213 &window_rect.x1, &window_rect.y1);
214 widget_rect->x0 = (int) window_rect.x0 - ctk_adjustment_get_value (hadj);
215 widget_rect->y0 = (int) window_rect.y0 - ctk_adjustment_get_value (vadj);
216 widget_rect->x1 = (int) window_rect.x1 - ctk_adjustment_get_value (hadj);
217 widget_rect->y1 = (int) window_rect.y1 - ctk_adjustment_get_value (vadj);
218}
219
220static void
221canvas_widget_to_world (EelCanvas *canvas,
222 double widget_x, double widget_y,
223 double *world_x, double *world_y)
224{
225 eel_canvas_window_to_world (canvas,
226 widget_x + ctk_adjustment_get_value (ctk_scrollable_get_hadjustment (CTK_SCROLLABLE (canvas)((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((canvas)), ((ctk_scrollable_get_type ()))))))
)),
227 widget_y + ctk_adjustment_get_value (ctk_scrollable_get_vadjustment (CTK_SCROLLABLE (canvas)((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((canvas)), ((ctk_scrollable_get_type ()))))))
)),
228 world_x, world_y);
229}
230
231static gboolean
232icon_get_data_binder (BaulIcon *icon, gpointer data)
233{
234 IconGetDataBinderContext *context;
235 EelDRect world_rect;
236 EelIRect widget_rect;
237 char *uri;
238 BaulIconContainer *container;
239
240 context = (IconGetDataBinderContext *)data;
241
242 g_assert (BAUL_IS_ICON_CONTAINER (context->iterator_context))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((context->iterator_context)); GType __t = (baul_icon_container_get_type
()); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) ; else g_assertion_message_expr (((gchar*) 0), "baul-icon-dnd.c"
, 242, ((const char*) (__func__)), "BAUL_IS_ICON_CONTAINER (context->iterator_context)"
); } while (0)
;
243
244 container = BAUL_ICON_CONTAINER (context->iterator_context)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context->iterator_context)), (baul_icon_container_get_type
())))))
;
245
246 world_rect = baul_icon_canvas_item_get_icon_rectangle (icon->item);
247
248 canvas_rect_world_to_widget (EEL_CANVAS (container)((((EelCanvas*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((eel_canvas_get_type ()))))))
, &world_rect, &widget_rect);
249
250 uri = baul_icon_container_get_icon_uri (container, icon);
251 if (uri == NULL((void*)0))
252 {
253 g_warning ("no URI for one of the iterated icons");
254 return TRUE(!(0));
255 }
256
257 widget_rect = eel_irect_offset_by (widget_rect,
258 - container->details->dnd_info->drag_info.start_x,
259 - container->details->dnd_info->drag_info.start_y);
260
261 widget_rect = eel_irect_scale_by (widget_rect,
262 1 / EEL_CANVAS (container)((((EelCanvas*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((eel_canvas_get_type ()))))))
->pixels_per_unit);
263
264 /* pass the uri, mouse-relative x/y and icon width/height */
265 context->iteratee (uri,
266 (int) widget_rect.x0,
267 (int) widget_rect.y0,
268 widget_rect.x1 - widget_rect.x0,
269 widget_rect.y1 - widget_rect.y0,
270 context->iteratee_data);
271
272 g_free (uri);
273
274 return TRUE(!(0));
275}
276
277/* Iterate over each selected icon in a BaulIconContainer,
278 * calling each_function on each.
279 */
280static void
281baul_icon_container_each_selected_icon (BaulIconContainer *container,
282 gboolean (*each_function) (BaulIcon *, gpointer), gpointer data)
283{
284 GList *p;
285 BaulIcon *icon = NULL((void*)0);
286
287 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
288 {
289 icon = p->data;
290 if (!icon->is_selected)
291 {
292 continue;
293 }
294 if (!each_function (icon, data))
295 {
296 return;
297 }
298 }
299}
300
301/* Adaptor function used with baul_icon_container_each_selected_icon
302 * to help iterate over all selected items, passing uris, x, y, w and h
303 * values to the iteratee
304 */
305static void
306each_icon_get_data_binder (BaulDragEachSelectedItemDataGet iteratee,
307 gpointer iterator_context, gpointer data)
308{
309 IconGetDataBinderContext context;
310 BaulIconContainer *container;
311
312 g_assert (BAUL_IS_ICON_CONTAINER (iterator_context))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((iterator_context)); GType __t = (baul_icon_container_get_type
()); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) ; else g_assertion_message_expr (((gchar*) 0), "baul-icon-dnd.c"
, 312, ((const char*) (__func__)), "BAUL_IS_ICON_CONTAINER (iterator_context)"
); } while (0)
;
313 container = BAUL_ICON_CONTAINER (iterator_context)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((iterator_context)), (baul_icon_container_get_type
())))))
;
314
315 context.iterator_context = iterator_context;
316 context.iteratee = iteratee;
317 context.iteratee_data = data;
318 baul_icon_container_each_selected_icon (container, icon_get_data_binder, &context);
319}
320
321/* Called when the data for drag&drop is needed */
322static void
323drag_data_get_callback (CtkWidget *widget,
324 CdkDragContext *context,
325 CtkSelectionData *selection_data,
326 guint info,
327 guint32 time,
328 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
329{
330 g_assert (widget != NULL)do { if (widget != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-icon-dnd.c", 330, ((const char*) (__func__
)), "widget != NULL"); } while (0)
;
331 g_assert (BAUL_IS_ICON_CONTAINER (widget))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = (baul_icon_container_get_type()); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "baul-icon-dnd.c", 331
, ((const char*) (__func__)), "BAUL_IS_ICON_CONTAINER (widget)"
); } while (0)
;
332 g_return_if_fail (context != NULL)do { if ((context != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "context != NULL"
); return; } } while (0)
;
333
334 /* Call common function from baul-drag that set's up
335 * the selection data in the right format. Pass it means to
336 * iterate all the selected icons.
337 */
338 baul_drag_drag_data_get (widget, context, selection_data,
339 info, time, widget, each_icon_get_data_binder);
340}
341
342
343/* Target-side handling of the drag. */
344
345static void
346baul_icon_container_position_shadow (BaulIconContainer *container,
347 int x, int y)
348{
349 EelCanvasItem *shadow;
350 double world_x, world_y;
351
352 shadow = container->details->dnd_info->shadow;
353 if (shadow == NULL((void*)0))
354 {
355 return;
356 }
357
358 canvas_widget_to_world (EEL_CANVAS (container)((((EelCanvas*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((eel_canvas_get_type ()))))))
, x, y,
359 &world_x, &world_y);
360
361 set_shadow_position (shadow, world_x, world_y);
362 eel_canvas_item_show (shadow);
363}
364
365static void
366baul_icon_container_dropped_icon_feedback (CtkWidget *widget,
367 CtkSelectionData *data,
368 int x, int y)
369{
370 BaulIconContainer *container;
371 BaulIconDndInfo *dnd_info;
372
373 container = BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
;
374 dnd_info = container->details->dnd_info;
375
376 /* Delete old selection list. */
377 baul_drag_destroy_selection_list (dnd_info->drag_info.selection_list);
378 dnd_info->drag_info.selection_list = NULL((void*)0);
379
380 /* Delete old shadow if any. */
381 if (dnd_info->shadow != NULL((void*)0))
382 {
383 /* FIXME bugzilla.gnome.org 42484:
384 * Is a destroy really sufficient here? Who does the unref? */
385 eel_canvas_item_destroy (dnd_info->shadow);
386 }
387
388 /* Build the selection list and the shadow. */
389 dnd_info->drag_info.selection_list = baul_drag_build_selection_list (data);
390 dnd_info->shadow = create_selection_shadow (container, dnd_info->drag_info.selection_list);
391 baul_icon_container_position_shadow (container, x, y);
392}
393
394static char *
395get_direct_save_filename (CdkDragContext *context)
396{
397 guchar *prop_text;
398 gint prop_len;
399
400 if (!cdk_property_get (cdk_drag_context_get_source_window (context), cdk_atom_intern (BAUL_ICON_DND_XDNDDIRECTSAVE_TYPE"XdndDirectSave0", FALSE(0)),
401 cdk_atom_intern ("text/plain", FALSE(0)), 0, 1024, FALSE(0), NULL((void*)0), NULL((void*)0),
402 &prop_len, &prop_text))
403 {
404 return NULL((void*)0);
405 }
406
407 /* Zero-terminate the string */
408 prop_text = g_realloc (prop_text, prop_len + 1);
409 prop_text[prop_len] = '\0';
410
411 /* Verify that the file name provided by the source is valid */
412 if (*prop_text == '\0' ||
413 strchr ((const gchar *) prop_text, G_DIR_SEPARATOR'/') != NULL((void*)0))
414 {
415 baul_debug_log (FALSE(0), BAUL_DEBUG_LOG_DOMAIN_USER"USER",
416 "Invalid filename provided by XDS drag site");
417 g_free (prop_text);
418 return NULL((void*)0);
419 }
420
421 return prop_text;
422}
423
424static void
425set_direct_save_uri (CtkWidget *widget, CdkDragContext *context, BaulDragInfo *drag_info, int x, int y)
426{
427 char *filename, *drop_target;
428 gchar *uri;
429
430 drag_info->got_drop_data_type = TRUE(!(0));
431 drag_info->data_type = BAUL_ICON_DND_XDNDDIRECTSAVE;
432
433 uri = NULL((void*)0);
434
435 filename = get_direct_save_filename (context);
436 drop_target = baul_icon_container_find_drop_target (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
,
437 context, x, y, NULL((void*)0), TRUE(!(0)));
438
439 if (drop_target && eel_uri_is_trash (drop_target))
440 {
441 g_free (drop_target);
442 drop_target = NULL((void*)0); /* Cannot save to trash ...*/
443 }
444
445 if (filename != NULL((void*)0) && drop_target != NULL((void*)0))
446 {
447 GFile *base, *child;
448
449 /* Resolve relative path */
450 base = g_file_new_for_uri (drop_target);
451 child = g_file_get_child (base, filename);
452 uri = g_file_get_uri (child);
453 g_object_unref (base);
454 g_object_unref (child);
455
456 /* Change the uri property */
457 cdk_property_change (cdk_drag_context_get_source_window (context),
458 cdk_atom_intern (BAUL_ICON_DND_XDNDDIRECTSAVE_TYPE"XdndDirectSave0", FALSE(0)),
459 cdk_atom_intern ("text/plain", FALSE(0)), 8,
460 CDK_PROP_MODE_REPLACE, (const guchar *) uri,
461 strlen (uri));
462
463 drag_info->direct_save_uri = uri;
464 }
465
466 g_free (filename);
467 g_free (drop_target);
468}
469
470/* FIXME bugzilla.gnome.org 47445: Needs to become a shared function */
471static void
472get_data_on_first_target_we_support (CtkWidget *widget, CdkDragContext *context, guint32 time, int x, int y)
473{
474 CtkTargetList *list;
475 CdkAtom target;
476
477 if (drop_types_list == NULL((void*)0))
478 {
479 drop_types_list = ctk_target_list_new (drop_types,
480 G_N_ELEMENTS (drop_types)(sizeof (drop_types) / sizeof ((drop_types)[0])) - 1);
481 ctk_target_list_add_text_targets (drop_types_list, BAUL_ICON_DND_TEXT);
482 }
483 if (drop_types_list_root == NULL((void*)0))
484 {
485 drop_types_list_root = ctk_target_list_new (drop_types,
486 G_N_ELEMENTS (drop_types)(sizeof (drop_types) / sizeof ((drop_types)[0])));
487 ctk_target_list_add_text_targets (drop_types_list_root, BAUL_ICON_DND_TEXT);
488 }
489
490 if (baul_icon_container_get_is_desktop (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
))
491 {
492 list = drop_types_list_root;
493 }
494 else
495 {
496 list = drop_types_list;
497 }
498
499 target = ctk_drag_dest_find_target (widget, context, list);
500 if (target != CDK_NONE((CdkAtom)((gpointer) (gulong) (0))))
501 {
502 guint info;
503 BaulDragInfo *drag_info;
504 gboolean found;
505
506 drag_info = &(BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
->details->dnd_info->drag_info);
507
508 found = ctk_target_list_find (list, target, &info);
509 g_assert (found)do { if (found) ; else g_assertion_message_expr (((gchar*) 0)
, "baul-icon-dnd.c", 509, ((const char*) (__func__)), "found"
); } while (0)
;
510
511 /* Don't get_data for destructive ops */
512 if ((info == BAUL_ICON_DND_ROOTWINDOW_DROP ||
513 info == BAUL_ICON_DND_XDNDDIRECTSAVE) &&
514 !drag_info->drop_occured)
515 {
516 /* We can't call get_data here, because that would
517 make the source execute the rootwin action or the direct save */
518 drag_info->got_drop_data_type = TRUE(!(0));
519 drag_info->data_type = info;
520 }
521 else
522 {
523 if (info == BAUL_ICON_DND_XDNDDIRECTSAVE)
524 {
525 set_direct_save_uri (widget, context, drag_info, x, y);
526 }
527 ctk_drag_get_data (CTK_WIDGET (widget)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_widget_get_type ()))))))
, context,
528 target, time);
529 }
530 }
531}
532
533static void
534baul_icon_container_ensure_drag_data (BaulIconContainer *container,
535 CdkDragContext *context,
536 guint32 time)
537{
538 BaulIconDndInfo *dnd_info;
539
540 dnd_info = container->details->dnd_info;
541
542 if (!dnd_info->drag_info.got_drop_data_type)
543 {
544 get_data_on_first_target_we_support (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
, context, time, 0, 0);
545 }
546}
547
548static void
549drag_end_callback (CtkWidget *widget,
550 CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
551 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
552{
553 BaulIconContainer *container;
554 BaulIconDndInfo *dnd_info;
555
556 container = BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
;
557 dnd_info = container->details->dnd_info;
558
559 baul_drag_destroy_selection_list (dnd_info->drag_info.selection_list);
560 dnd_info->drag_info.selection_list = NULL((void*)0);
561}
562
563static BaulIcon *
564baul_icon_container_item_at (BaulIconContainer *container,
565 int x, int y)
566{
567 GList *p;
568 int size;
569 EelDRect point;
570 EelIRect canvas_point;
571
572 /* build the hit-test rectangle. Base the size on the scale factor to ensure that it is
573 * non-empty even at the smallest scale factor
574 */
575
576 size = MAX (1, 1 + (1 / EEL_CANVAS (container)->pixels_per_unit))(((1) > (1 + (1 / ((((EelCanvas*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((container)), ((eel_canvas_get_type ())))
)))->pixels_per_unit))) ? (1) : (1 + (1 / ((((EelCanvas*) (
void *) g_type_check_instance_cast ((GTypeInstance*) ((container
)), ((eel_canvas_get_type ()))))))->pixels_per_unit)))
;
577 point.x0 = x;
578 point.y0 = y;
579 point.x1 = x + size;
580 point.y1 = y + size;
581
582 for (p = container->details->icons; p != NULL((void*)0); p = p->next)
583 {
584 BaulIcon *icon;
585 icon = p->data;
586
587 eel_canvas_w2c (EEL_CANVAS (container)((((EelCanvas*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((eel_canvas_get_type ()))))))
,
588 point.x0,
589 point.y0,
590 &canvas_point.x0,
591 &canvas_point.y0);
592 eel_canvas_w2c (EEL_CANVAS (container)((((EelCanvas*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((eel_canvas_get_type ()))))))
,
593 point.x1,
594 point.y1,
595 &canvas_point.x1,
596 &canvas_point.y1);
597 if (baul_icon_canvas_item_hit_test_rectangle (icon->item, canvas_point))
598 {
599 return icon;
600 }
601 }
602
603 return NULL((void*)0);
604}
605
606static char *
607get_container_uri (BaulIconContainer *container)
608{
609 char *uri;
610
611 /* get the URI associated with the container */
612 uri = NULL((void*)0);
613 g_signal_emit_by_name (container, "get_container_uri", &uri);
614 return uri;
615}
616
617static gboolean
618baul_icon_container_selection_items_local (BaulIconContainer *container,
619 GList *items)
620{
621 char *container_uri_string;
622 gboolean result;
623
624 /* must have at least one item */
625 g_assert (items)do { if (items) ; else g_assertion_message_expr (((gchar*) 0)
, "baul-icon-dnd.c", 625, ((const char*) (__func__)), "items"
); } while (0)
;
626
627 result = FALSE(0);
628
629 /* get the URI associated with the container */
630 container_uri_string = get_container_uri (container);
631
632 if (eel_uri_is_desktop (container_uri_string))
633 {
634 result = baul_drag_items_on_desktop (items);
635 }
636 else
637 {
638 result = baul_drag_items_local (container_uri_string, items);
639 }
640 g_free (container_uri_string);
641
642 return result;
643}
644
645static CdkDragAction
646get_background_drag_action (BaulIconContainer *container,
647 CdkDragAction action)
648{
649 /* FIXME: This function is very FMDirectoryView specific, and
650 * should be moved out of baul-icon-dnd.c */
651 CdkDragAction valid_actions;
652
653 if (action == CDK_ACTION_ASK)
654 {
655 valid_actions = BAUL_DND_ACTION_SET_AS_FOLDER_BACKGROUND;
656 if (!eel_background_is_desktop (eel_get_widget_background (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
)))
657 {
658 valid_actions |= BAUL_DND_ACTION_SET_AS_GLOBAL_BACKGROUND;
659 }
660
661 action = baul_drag_drop_background_ask
662 (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
, valid_actions);
663 }
664
665 return action;
666}
667
668static void
669receive_dropped_color (BaulIconContainer *container,
670 int x, int y,
671 CdkDragAction action,
672 CtkSelectionData *data)
673{
674 action = get_background_drag_action (container, action);
675
676 if (action > 0)
677 {
678 char *uri;
679
680 uri = get_container_uri (container);
681 baul_debug_log (FALSE(0), BAUL_DEBUG_LOG_DOMAIN_USER"USER",
682 "dropped color on icon container displaying %s", uri);
683 g_free (uri);
684
685 eel_background_set_dropped_color (eel_get_widget_background (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
),
686 CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
,
687 action, x, y, data);
688 }
689}
690
691/* handle dropped tile images */
692static void
693receive_dropped_tile_image (BaulIconContainer *container, CdkDragAction action, CtkSelectionData *data)
694{
695 g_assert (data != NULL)do { if (data != ((void*)0)) ; else g_assertion_message_expr (
((gchar*) 0), "baul-icon-dnd.c", 695, ((const char*) (__func__
)), "data != NULL"); } while (0)
;
696
697 action = get_background_drag_action (container, action);
698
699 if (action > 0)
700 {
701 char *uri;
702
703 uri = get_container_uri (container);
704 baul_debug_log (FALSE(0), BAUL_DEBUG_LOG_DOMAIN_USER"USER",
705 "dropped tile image on icon container displaying %s", uri);
706 g_free (uri);
707
708 eel_background_set_dropped_image (eel_get_widget_background (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
),
709 action, ctk_selection_data_get_data (data));
710 }
711}
712
713/* handle dropped keywords */
714static void
715receive_dropped_keyword (BaulIconContainer *container, const char *keyword, int x, int y)
716{
717 char *uri;
718 double world_x, world_y;
719
720 BaulIcon *drop_target_icon;
721 BaulFile *file;
722
723 g_assert (keyword != NULL)do { if (keyword != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-icon-dnd.c", 723, ((const char*) (__func__
)), "keyword != NULL"); } while (0)
;
724
725 /* find the item we hit with our drop, if any */
726 canvas_widget_to_world (EEL_CANVAS (container)((((EelCanvas*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((eel_canvas_get_type ()))))))
, x, y, &world_x, &world_y);
727 drop_target_icon = baul_icon_container_item_at (container, world_x, world_y);
728 if (drop_target_icon == NULL((void*)0))
729 {
730 return;
731 }
732
733 /* FIXME bugzilla.gnome.org 42485:
734 * This does not belong in the icon code.
735 * It has to be in the file manager.
736 * The icon code has no right to deal with the file directly.
737 * But luckily there's no issue of not getting a file object,
738 * so we don't have to worry about async. issues here.
739 */
740 uri = baul_icon_container_get_icon_uri (container, drop_target_icon);
741
742 baul_debug_log (FALSE(0), BAUL_DEBUG_LOG_DOMAIN_USER"USER",
743 "dropped emblem '%s' on icon container URI: %s",
744 keyword, uri);
745
746 file = baul_file_get_by_uri (uri);
747 g_free (uri);
748
749 baul_drag_file_receive_dropped_keyword (file, keyword);
750
751 baul_file_unref (file);
752 baul_icon_container_update_icon (container, drop_target_icon);
753}
754
755/* handle dropped url */
756static void
757receive_dropped_netscape_url (BaulIconContainer *container, const char *encoded_url, CdkDragContext *context, int x, int y)
758{
759 char *drop_target;
760
761 if (encoded_url == NULL((void*)0))
762 {
763 return;
764 }
765
766 drop_target = baul_icon_container_find_drop_target (container, context, x, y, NULL((void*)0), TRUE(!(0)));
767
768 g_signal_emit_by_name (container, "handle_netscape_url",
769 encoded_url,
770 drop_target,
771 cdk_drag_context_get_selected_action (context),
772 x, y);
773
774 g_free (drop_target);
775}
776
777/* handle dropped uri list */
778static void
779receive_dropped_uri_list (BaulIconContainer *container, const char *uri_list, CdkDragContext *context, int x, int y)
780{
781 char *drop_target;
782
783 if (uri_list == NULL((void*)0))
784 {
785 return;
786 }
787
788 drop_target = baul_icon_container_find_drop_target (container, context, x, y, NULL((void*)0), TRUE(!(0)));
789
790 g_signal_emit_by_name (container, "handle_uri_list",
791 uri_list,
792 drop_target,
793 cdk_drag_context_get_selected_action (context),
794 x, y);
795
796 g_free (drop_target);
797}
798
799/* handle dropped text */
800static void
801receive_dropped_text (BaulIconContainer *container, const char *text, CdkDragContext *context, int x, int y)
802{
803 char *drop_target;
804
805 if (text == NULL((void*)0))
806 {
807 return;
808 }
809
810 drop_target = baul_icon_container_find_drop_target (container, context, x, y, NULL((void*)0), TRUE(!(0)));
811
812 g_signal_emit_by_name (container, "handle_text",
813 text,
814 drop_target,
815 cdk_drag_context_get_selected_action (context),
816 x, y);
817
818 g_free (drop_target);
819}
820
821/* handle dropped raw data */
822static void
823receive_dropped_raw (BaulIconContainer *container, const char *raw_data, int length, const char *direct_save_uri, CdkDragContext *context, int x, int y)
824{
825 char *drop_target;
826
827 if (raw_data == NULL((void*)0))
828 {
829 return;
830 }
831
832 drop_target = baul_icon_container_find_drop_target (container, context, x, y, NULL((void*)0), TRUE(!(0)));
833
834 g_signal_emit_by_name (container, "handle_raw",
835 raw_data,
836 length,
837 drop_target,
838 direct_save_uri,
839 cdk_drag_context_get_selected_action (context),
840 x, y);
841
842 g_free (drop_target);
843}
844
845static int
846auto_scroll_timeout_callback (gpointer data)
847{
848 BaulIconContainer *container;
849 CtkWidget *widget;
850 float x_scroll_delta, y_scroll_delta;
851 CdkRectangle exposed_area;
852 CtkAllocation allocation;
853
854 g_assert (BAUL_IS_ICON_CONTAINER (data))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((data)); GType __t = (baul_icon_container_get_type()); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "baul-icon-dnd.c", 854
, ((const char*) (__func__)), "BAUL_IS_ICON_CONTAINER (data)"
); } while (0)
;
855 widget = CTK_WIDGET (data)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_widget_get_type ()))))))
;
856 container = BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
;
857
858 if (container->details->dnd_info->drag_info.waiting_to_autoscroll
859 && container->details->dnd_info->drag_info.start_auto_scroll_in > g_get_monotonic_time())
860 {
861 /* not yet */
862 return TRUE(!(0));
863 }
864
865 container->details->dnd_info->drag_info.waiting_to_autoscroll = FALSE(0);
866
867 baul_drag_autoscroll_calculate_delta (widget, &x_scroll_delta, &y_scroll_delta);
868 if (x_scroll_delta == 0 && y_scroll_delta == 0)
869 {
870 /* no work */
871 return TRUE(!(0));
872 }
873
874 /* Clear the old dnd highlight frame */
875 dnd_highlight_queue_redraw (widget);
876
877 if (!baul_icon_container_scroll (container, (int)x_scroll_delta, (int)y_scroll_delta))
878 {
879 /* the scroll value got pinned to a min or max adjustment value,
880 * we ended up not scrolling
881 */
882 return TRUE(!(0));
883 }
884
885 /* Make sure the dnd highlight frame is redrawn */
886 dnd_highlight_queue_redraw (widget);
887
888 /* update cached drag start offsets */
889 container->details->dnd_info->drag_info.start_x -= x_scroll_delta;
890 container->details->dnd_info->drag_info.start_y -= y_scroll_delta;
891
892 /* Due to a glitch in CtkLayout, whe need to do an explicit draw of the exposed
893 * area.
894 * Calculate the size of the area we need to draw
895 */
896 ctk_widget_get_allocation (widget, &allocation);
897 exposed_area.x = allocation.x;
898 exposed_area.y = allocation.y;
899 exposed_area.width = allocation.width;
900 exposed_area.height = allocation.height;
901
902 if (x_scroll_delta > 0)
903 {
904 exposed_area.x = exposed_area.width - x_scroll_delta;
905 }
906 else if (x_scroll_delta < 0)
907 {
908 exposed_area.width = -x_scroll_delta;
909 }
910
911 if (y_scroll_delta > 0)
912 {
913 exposed_area.y = exposed_area.height - y_scroll_delta;
914 }
915 else if (y_scroll_delta < 0)
916 {
917 exposed_area.height = -y_scroll_delta;
918 }
919
920 /* offset it to 0, 0 */
921 exposed_area.x -= allocation.x;
922 exposed_area.y -= allocation.y;
923
924 ctk_widget_queue_draw_area (widget,
925 exposed_area.x,
926 exposed_area.y,
927 exposed_area.width,
928 exposed_area.height);
929
930 return TRUE(!(0));
931}
932
933static void
934set_up_auto_scroll_if_needed (BaulIconContainer *container)
935{
936 baul_drag_autoscroll_start (&container->details->dnd_info->drag_info,
937 CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
,
938 auto_scroll_timeout_callback,
939 container);
940}
941
942static void
943stop_auto_scroll (BaulIconContainer *container)
944{
945 baul_drag_autoscroll_stop (&container->details->dnd_info->drag_info);
946}
947
948static void
949handle_local_move (BaulIconContainer *container,
950 double world_x, double world_y)
951{
952 GList *moved_icons, *p;
953 BaulFile *file;
954 char screen_string[32];
955 CdkScreen *screen;
956 time_t now;
957 BaulDragSelectionItem *item = NULL((void*)0);
958 BaulIcon *icon = NULL((void*)0);
959
960 if (container->details->auto_layout)
961 {
962 return;
963 }
964
965 time (&now);
966
967 /* Move and select the icons. */
968 moved_icons = NULL((void*)0);
969 for (p = container->details->dnd_info->drag_info.selection_list; p != NULL((void*)0); p = p->next)
970 {
971 item = p->data;
972
973 icon = baul_icon_container_get_icon_by_uri
974 (container, item->uri);
975
976 if (icon == NULL((void*)0))
977 {
978 /* probably dragged from another screen. Add it to
979 * this screen
980 */
981
982 file = baul_file_get_by_uri (item->uri);
983
984 screen = ctk_widget_get_screen (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
);
985 g_snprintf (screen_string, sizeof (screen_string), "%d",
986 cdk_x11_screen_get_screen_number (screen));
987 baul_file_set_metadata (file,
988 BAUL_METADATA_KEY_SCREEN"screen",
989 NULL((void*)0), screen_string);
990 baul_file_set_time_metadata (file,
991 BAUL_METADATA_KEY_ICON_POSITION_TIMESTAMP"baul-icon-position-timestamp", now);
992
993 baul_icon_container_add (container, BAUL_ICON_CONTAINER_ICON_DATA (file)((BaulIconData *) (file)));
994
995 icon = baul_icon_container_get_icon_by_uri
996 (container, item->uri);
997 }
998
999 if (item->got_icon_position)
1000 {
1001 baul_icon_container_move_icon
1002 (container, icon,
1003 world_x + item->icon_x, world_y + item->icon_y,
1004 icon->scale,
1005 TRUE(!(0)), TRUE(!(0)), TRUE(!(0)));
1006 }
1007 moved_icons = g_list_prepend (moved_icons, icon);
1008 }
1009 baul_icon_container_select_list_unselect_others
1010 (container, moved_icons);
1011 /* Might have been moved in a way that requires adjusting scroll region. */
1012 baul_icon_container_update_scroll_region (container);
1013 g_list_free (moved_icons);
1014}
1015
1016static void
1017handle_nonlocal_move (BaulIconContainer *container,
1018 CdkDragAction action,
1019 int x, int y,
1020 const char *target_uri,
1021 gboolean icon_hit)
1022{
1023 GList *source_uris, *p;
1024 GArray *source_item_locations;
1025 gboolean free_target_uri, is_rtl;
1026 CtkAllocation allocation;
1027
1028 if (container->details->dnd_info->drag_info.selection_list == NULL((void*)0))
1029 {
1030 return;
1031 }
1032
1033 source_uris = NULL((void*)0);
1034 for (p = container->details->dnd_info->drag_info.selection_list; p != NULL((void*)0); p = p->next)
1035 {
1036 /* do a shallow copy of all the uri strings of the copied files */
1037 source_uris = g_list_prepend (source_uris, ((BaulDragSelectionItem *)p->data)->uri);
1038 }
1039 source_uris = g_list_reverse (source_uris);
1040
1041 is_rtl = baul_icon_container_is_layout_rtl (container);
1042
1043 source_item_locations = g_array_new (FALSE(0), TRUE(!(0)), sizeof (CdkPoint));
1044 if (!icon_hit)
1045 {
1046 int index;
1047
1048 /* Drop onto a container. Pass along the item points to allow placing
1049 * the items in their same relative positions in the new container.
1050 */
1051 source_item_locations = g_array_set_size (source_item_locations,
1052 g_list_length (container->details->dnd_info->drag_info.selection_list));
1053
1054 for (index = 0, p = container->details->dnd_info->drag_info.selection_list;
1055 p != NULL((void*)0); index++, p = p->next)
1056 {
1057 int item_x;
1058
1059 item_x = ((BaulDragSelectionItem *)p->data)->icon_x;
1060 if (is_rtl)
1061 item_x = -item_x - ((BaulDragSelectionItem *)p->data)->icon_width;
1062 g_array_index (source_item_locations, CdkPoint, index)(((CdkPoint*) (void *) (source_item_locations)->data) [(index
)])
.x = item_x;
1063 g_array_index (source_item_locations, CdkPoint, index)(((CdkPoint*) (void *) (source_item_locations)->data) [(index
)])
.y =
1064 ((BaulDragSelectionItem *)p->data)->icon_y;
1065 }
1066 }
1067
1068 free_target_uri = FALSE(0);
1069 /* Rewrite internal desktop URIs to the normal target uri */
1070 if (eel_uri_is_desktop (target_uri))
1071 {
1072 target_uri = baul_get_desktop_directory_uri ();
1073 free_target_uri = TRUE(!(0));
1074 }
1075
1076 if (is_rtl)
1077 {
1078 ctk_widget_get_allocation (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
, &allocation);
1079 x = CANVAS_WIDTH (container, allocation)((allocation.width - container->details->left_margin - container
->details->right_margin) / ((((EelCanvas*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((container)), ((eel_canvas_get_type ())))
)))->pixels_per_unit)
- x;
1080 }
1081
1082 /* start the copy */
1083 g_signal_emit_by_name (container, "move_copy_items",
1084 source_uris,
1085 source_item_locations,
1086 target_uri,
1087 action,
1088 x, y);
1089
1090 if (free_target_uri)
1091 {
1092 g_free ((char *)target_uri);
1093 }
1094
1095 g_list_free (source_uris);
1096 g_array_free (source_item_locations, TRUE(!(0)));
1097}
1098
1099static char *
1100baul_icon_container_find_drop_target (BaulIconContainer *container,
1101 CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
1102 int x,
1103 int y,
1104 gboolean *icon_hit,
1105 gboolean rewrite_desktop)
1106{
1107 BaulIcon *drop_target_icon;
1108 double world_x, world_y;
1109
1110 if (icon_hit)
1111 {
1112 *icon_hit = FALSE(0);
1113 }
1114
1115 if (!container->details->dnd_info->drag_info.got_drop_data_type)
1116 {
1117 return NULL((void*)0);
1118 }
1119
1120 canvas_widget_to_world (EEL_CANVAS (container)((((EelCanvas*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((eel_canvas_get_type ()))))))
, x, y, &world_x, &world_y);
1121
1122 /* FIXME bugzilla.gnome.org 42485:
1123 * These "can_accept_items" tests need to be done by
1124 * the icon view, not here. This file is not supposed to know
1125 * that the target is a file.
1126 */
1127
1128 /* Find the item we hit with our drop, if any */
1129 drop_target_icon = baul_icon_container_item_at (container, world_x, world_y);
1130 if (drop_target_icon != NULL((void*)0))
1131 {
1132 char *icon_uri;
1133
1134 icon_uri = baul_icon_container_get_icon_uri (container, drop_target_icon);
1135 if (icon_uri != NULL((void*)0))
1136 {
1137 BaulFile *file;
1138
1139 file = baul_file_get_by_uri (icon_uri);
1140
1141 if (!baul_drag_can_accept_info (file,
1142 container->details->dnd_info->drag_info.data_type,
1143 container->details->dnd_info->drag_info.selection_list))
1144 {
1145 /* the item we dropped our selection on cannot accept the items,
1146 * do the same thing as if we just dropped the items on the canvas
1147 */
1148 drop_target_icon = NULL((void*)0);
1149 }
1150
1151 g_free (icon_uri);
1152 baul_file_unref (file);
1153 }
1154 }
1155
1156 if (drop_target_icon == NULL((void*)0))
1157 {
1158 char *container_uri;
1159
1160 if (icon_hit)
1161 {
1162 *icon_hit = FALSE(0);
1163 }
1164
1165 container_uri = get_container_uri (container);
1166
1167 if (rewrite_desktop &&
1168 container_uri != NULL((void*)0) &&
1169 eel_uri_is_desktop (container_uri))
1170 {
1171 g_free (container_uri);
1172 container_uri = baul_get_desktop_directory_uri ();
1173 }
1174
1175 return container_uri;
1176 }
1177
1178 if (icon_hit)
1179 {
1180 *icon_hit = TRUE(!(0));
1181 }
1182 return baul_icon_container_get_icon_drop_target_uri (container, drop_target_icon);
1183}
1184
1185static gboolean
1186selection_is_image_file (GList *selection_list)
1187{
1188 const char *mime_type;
1189 BaulDragSelectionItem *selected_item;
1190 gboolean result;
1191 GFile *location;
1192 GFileInfo *info;
1193
1194 /* Make sure only one item is selected */
1195 if (selection_list == NULL((void*)0) ||
1196 selection_list->next != NULL((void*)0))
1197 {
1198 return FALSE(0);
1199 }
1200
1201 selected_item = selection_list->data;
1202
1203 mime_type = NULL((void*)0);
1204
1205 location = g_file_new_for_uri (selected_item->uri);
1206 info = g_file_query_info (location,
1207 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE"standard::content-type",
1208 0, NULL((void*)0), NULL((void*)0));
1209 if (info)
1210 {
1211 mime_type = g_file_info_get_content_type (info);
1212 }
1213
1214 result = eel_istr_has_prefix (mime_type, "image/");
1215
1216 if (info)
1217 {
1218 g_object_unref (info);
1219 }
1220 g_object_unref (location);
1221
1222 return result;
1223}
1224
1225
1226static void
1227baul_icon_container_receive_dropped_icons (BaulIconContainer *container,
1228 CdkDragContext *context,
1229 int x, int y)
1230{
1231 char *drop_target;
1232 gboolean local_move_only;
1233 double world_x, world_y;
1234 gboolean icon_hit;
1235 CdkDragAction action, real_action;
1236
1237 drop_target = NULL((void*)0);
1238
1239 if (container->details->dnd_info->drag_info.selection_list == NULL((void*)0))
1240 {
1241 return;
1242 }
1243
1244 real_action = cdk_drag_context_get_selected_action (context);
1245
1246 if (real_action == CDK_ACTION_ASK)
1247 {
1248 /* FIXME bugzilla.gnome.org 42485: This belongs in FMDirectoryView, not here. */
1249 /* Check for special case items in selection list */
1250 if (baul_drag_selection_includes_special_link (container->details->dnd_info->drag_info.selection_list))
1251 {
1252 /* We only want to move the trash */
1253 action = CDK_ACTION_MOVE;
1254 }
1255 else
1256 {
1257 action = CDK_ACTION_MOVE | CDK_ACTION_COPY | CDK_ACTION_LINK;
1258
1259 if (selection_is_image_file (container->details->dnd_info->drag_info.selection_list))
1260 {
1261 action |= BAUL_DND_ACTION_SET_AS_BACKGROUND;
1262 }
1263 }
1264 real_action = baul_drag_drop_action_ask (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
, action);
1265 }
1266
1267 if (real_action == (CdkDragAction) BAUL_DND_ACTION_SET_AS_BACKGROUND)
1268 {
1269 BaulDragSelectionItem *selected_item;
1270
1271 selected_item = container->details->dnd_info->drag_info.selection_list->data;
1272 eel_background_set_dropped_image (eel_get_widget_background (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
),
1273 real_action, selected_item->uri);
1274 return;
1275 }
1276
1277 if (real_action > 0)
1278 {
1279 eel_canvas_window_to_world (EEL_CANVAS (container)((((EelCanvas*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((eel_canvas_get_type ()))))))
,
1280 x + ctk_adjustment_get_value (ctk_scrollable_get_hadjustment (CTK_SCROLLABLE (container)((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_scrollable_get_type ()))))))
)),
1281 y + ctk_adjustment_get_value (ctk_scrollable_get_vadjustment (CTK_SCROLLABLE (container)((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_scrollable_get_type ()))))))
)),
1282 &world_x, &world_y);
1283
1284 drop_target = baul_icon_container_find_drop_target (container,
1285 context, x, y, &icon_hit, FALSE(0));
1286
1287 local_move_only = FALSE(0);
1288 if (!icon_hit && real_action == CDK_ACTION_MOVE)
1289 {
1290 /* we can just move the icon positions if the move ended up in
1291 * the item's parent container
1292 */
1293 local_move_only = baul_icon_container_selection_items_local
1294 (container, container->details->dnd_info->drag_info.selection_list);
1295 }
1296
1297 if (local_move_only)
1298 {
1299 handle_local_move (container, world_x, world_y);
1300 }
1301 else
1302 {
1303 handle_nonlocal_move (container, real_action, world_x, world_y, drop_target, icon_hit);
1304 }
1305 }
1306
1307 g_free (drop_target);
1308 baul_drag_destroy_selection_list (container->details->dnd_info->drag_info.selection_list);
1309 container->details->dnd_info->drag_info.selection_list = NULL((void*)0);
1310}
1311
1312static void
1313baul_icon_container_get_drop_action (BaulIconContainer *container,
1314 CdkDragContext *context,
1315 int x, int y,
1316 int *action)
1317{
1318 char *drop_target;
1319 gboolean icon_hit;
1320 BaulIcon *icon;
1321 double world_x, world_y;
1322
1323 icon_hit = FALSE(0);
1324 if (!container->details->dnd_info->drag_info.got_drop_data_type)
1325 {
1326 /* drag_data_received_callback didn't get called yet */
1327 return;
1328 }
1329
1330 /* find out if we're over an icon */
1331 canvas_widget_to_world (EEL_CANVAS (container)((((EelCanvas*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((eel_canvas_get_type ()))))))
, x, y, &world_x, &world_y);
1332
1333 icon = baul_icon_container_item_at (container, world_x, world_y);
1334
1335 *action = 0;
1336
1337 /* case out on the type of object being dragged */
1338 switch (container->details->dnd_info->drag_info.data_type)
1339 {
1340 case BAUL_ICON_DND_CAFE_ICON_LIST:
1341 if (container->details->dnd_info->drag_info.selection_list == NULL((void*)0))
1342 {
1343 return;
1344 }
1345 drop_target = baul_icon_container_find_drop_target (container,
1346 context, x, y, &icon_hit, FALSE(0));
1347 if (!drop_target)
1348 {
1349 return;
1350 }
1351 baul_drag_default_drop_action_for_icons (context, drop_target,
1352 container->details->dnd_info->drag_info.selection_list,
1353 action);
1354 g_free (drop_target);
1355 break;
1356 case BAUL_ICON_DND_URI_LIST:
1357 drop_target = baul_icon_container_find_drop_target (container,
1358 context, x, y, &icon_hit, FALSE(0));
1359 *action = baul_drag_default_drop_action_for_uri_list (context, drop_target);
1360
1361 g_free (drop_target);
1362 break;
1363
1364 /* handle emblems by setting the action if we're over an object */
1365 case BAUL_ICON_DND_KEYWORD:
1366 if (icon != NULL((void*)0))
1367 {
1368 *action = cdk_drag_context_get_suggested_action (context);
1369 }
1370 break;
1371
1372 case BAUL_ICON_DND_NETSCAPE_URL:
1373 *action = baul_drag_default_drop_action_for_netscape_url (context);
1374 break;
1375
1376 case BAUL_ICON_DND_COLOR:
1377 case BAUL_ICON_DND_BGIMAGE:
1378 case BAUL_ICON_DND_RESET_BACKGROUND:
1379 case BAUL_ICON_DND_ROOTWINDOW_DROP:
1380 *action = cdk_drag_context_get_suggested_action (context);
1381 break;
1382
1383 case BAUL_ICON_DND_TEXT:
1384 case BAUL_ICON_DND_XDNDDIRECTSAVE:
1385 case BAUL_ICON_DND_RAW:
1386 *action = CDK_ACTION_COPY;
1387 break;
1388 }
1389}
1390
1391static void
1392set_drop_target (BaulIconContainer *container,
1393 BaulIcon *icon)
1394{
1395 BaulIcon *old_icon;
1396
1397 /* Check if current drop target changed, update icon drop
1398 * higlight if needed.
1399 */
1400 old_icon = container->details->drop_target;
1401 if (icon == old_icon)
1402 {
1403 return;
1404 }
1405
1406 /* Remember the new drop target for the next round. */
1407 container->details->drop_target = icon;
1408 baul_icon_container_update_icon (container, old_icon);
1409 baul_icon_container_update_icon (container, icon);
1410}
1411
1412static void
1413baul_icon_dnd_update_drop_target (BaulIconContainer *container,
1414 CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
1415 int x,
1416 int y)
1417{
1418 BaulIcon *icon;
1419 double world_x, world_y;
1420
1421 g_assert (BAUL_IS_ICON_CONTAINER (container))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (baul_icon_container_get_type()
); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) ; else g_assertion_message_expr (((gchar*) 0), "baul-icon-dnd.c"
, 1421, ((const char*) (__func__)), "BAUL_IS_ICON_CONTAINER (container)"
); } while (0)
;
1422
1423 canvas_widget_to_world (EEL_CANVAS (container)((((EelCanvas*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((eel_canvas_get_type ()))))))
, x, y, &world_x, &world_y);
1424
1425 /* Find the item we hit with our drop, if any. */
1426 icon = baul_icon_container_item_at (container, world_x, world_y);
1427
1428 /* FIXME bugzilla.gnome.org 42485:
1429 * These "can_accept_items" tests need to be done by
1430 * the icon view, not here. This file is not supposed to know
1431 * that the target is a file.
1432 */
1433
1434 /* Find if target icon accepts our drop. */
1435 if (icon != NULL((void*)0) && (container->details->dnd_info->drag_info.data_type != BAUL_ICON_DND_KEYWORD))
1436 {
1437 BaulFile *file;
1438 char *uri;
1439
1440 uri = baul_icon_container_get_icon_uri (container, icon);
1441 file = baul_file_get_by_uri (uri);
1442 g_free (uri);
1443
1444 if (!baul_drag_can_accept_info (file,
1445 container->details->dnd_info->drag_info.data_type,
1446 container->details->dnd_info->drag_info.selection_list))
1447 {
1448 icon = NULL((void*)0);
1449 }
1450
1451 baul_file_unref (file);
1452 }
1453
1454 set_drop_target (container, icon);
1455}
1456
1457static void
1458baul_icon_container_free_drag_data (BaulIconContainer *container)
1459{
1460 BaulIconDndInfo *dnd_info;
1461
1462 dnd_info = container->details->dnd_info;
1463
1464 dnd_info->drag_info.got_drop_data_type = FALSE(0);
1465
1466 if (dnd_info->shadow != NULL((void*)0))
1467 {
1468 eel_canvas_item_destroy (dnd_info->shadow);
1469 dnd_info->shadow = NULL((void*)0);
1470 }
1471
1472 if (dnd_info->drag_info.selection_data != NULL((void*)0))
1473 {
1474 ctk_selection_data_free (dnd_info->drag_info.selection_data);
1475 dnd_info->drag_info.selection_data = NULL((void*)0);
1476 }
1477
1478 if (dnd_info->drag_info.direct_save_uri != NULL((void*)0))
1479 {
1480 g_free (dnd_info->drag_info.direct_save_uri);
1481 dnd_info->drag_info.direct_save_uri = NULL((void*)0);
1482 }
1483}
1484
1485static void
1486drag_leave_callback (CtkWidget *widget,
1487 CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
1488 guint32 time G_GNUC_UNUSED__attribute__ ((__unused__)),
1489 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
1490{
1491 BaulIconDndInfo *dnd_info;
1492
1493 dnd_info = BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
->details->dnd_info;
1494
1495 if (dnd_info->shadow != NULL((void*)0))
1496 eel_canvas_item_hide (dnd_info->shadow);
1497
1498 stop_dnd_highlight (widget);
1499
1500 set_drop_target (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
, NULL((void*)0));
1501 stop_auto_scroll (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
);
1502 baul_icon_container_free_drag_data(BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
);
1503}
1504
1505static void
1506drag_begin_callback (CtkWidget *widget,
1507 CdkDragContext *context,
1508 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
1509{
1510 BaulIconContainer *container;
1511 cairo_surface_t *surface;
1512 double x1, y1, x2, y2, winx, winy;
1513 int x_offset, y_offset;
1514 int start_x, start_y;
1515
1516 container = BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
;
1517
1518 start_x = container->details->dnd_info->drag_info.start_x +
1519 ctk_adjustment_get_value (ctk_scrollable_get_hadjustment (CTK_SCROLLABLE (container)((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_scrollable_get_type ()))))))
));
1520 start_y = container->details->dnd_info->drag_info.start_y +
1521 ctk_adjustment_get_value (ctk_scrollable_get_vadjustment (CTK_SCROLLABLE (container)((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_scrollable_get_type ()))))))
));
1522
1523 /* create a pixmap and mask to drag with */
1524 surface = baul_icon_canvas_item_get_drag_surface (container->details->drag_icon->item);
1525
1526 /* compute the image's offset */
1527 eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (container->details->drag_icon->item)((((EelCanvasItem*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container->details->drag_icon->item)), ((eel_canvas_item_get_type
()))))))
,
1528 &x1, &y1, &x2, &y2);
1529 eel_canvas_world_to_window (EEL_CANVAS (container)((((EelCanvas*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((eel_canvas_get_type ()))))))
,
1530 x1, y1, &winx, &winy);
1531 x_offset = start_x - winx;
1532 y_offset = start_y - winy;
1533
1534 cairo_surface_set_device_offset (surface, -x_offset, -y_offset);
1535 ctk_drag_set_icon_surface (context, surface);
1536 cairo_surface_destroy (surface);
1537}
1538
1539void
1540baul_icon_dnd_begin_drag (BaulIconContainer *container,
1541 CdkDragAction actions,
1542 int button,
1543 CdkEventMotion *event,
1544 int start_x,
1545 int start_y)
1546{
1547 BaulIconDndInfo *dnd_info;
1548
1549 g_return_if_fail (BAUL_IS_ICON_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (baul_icon_container_get_type()
); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning (((gchar*) 0
), ((const char*) (__func__)), "BAUL_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
1550 g_return_if_fail (event != NULL)do { if ((event != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "event != NULL");
return; } } while (0)
;
1551
1552 dnd_info = container->details->dnd_info;
1553 g_return_if_fail (dnd_info != NULL)do { if ((dnd_info != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "dnd_info != NULL"
); return; } } while (0)
;
1554
1555 /* Notice that the event is in bin_window coordinates, because of
1556 the way the canvas handles events.
1557 */
1558 dnd_info->drag_info.start_x = start_x -
1559 ctk_adjustment_get_value (ctk_scrollable_get_hadjustment (CTK_SCROLLABLE (container)((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_scrollable_get_type ()))))))
));
1560 dnd_info->drag_info.start_y = start_y -
1561 ctk_adjustment_get_value (ctk_scrollable_get_vadjustment (CTK_SCROLLABLE (container)((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_scrollable_get_type ()))))))
));
1562
1563 /* start the drag */
1564 ctk_drag_begin_with_coordinates (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
,
1565 dnd_info->drag_info.target_list,
1566 actions,
1567 button,
1568 (CdkEvent *) event,
1569 dnd_info->drag_info.start_x,
1570 dnd_info->drag_info.start_y);
1571}
1572
1573static gboolean
1574drag_highlight_draw (CtkWidget *widget,
1575 cairo_t *cr,
1576 gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
1577{
1578 gint width, height;
1579 CdkWindow *window;
1580 CtkStyleContext *style;
1581
1582 window = ctk_widget_get_window (widget);
1583 width = cdk_window_get_width (window);
1584 height = cdk_window_get_height (window);
1585
1586 style = ctk_widget_get_style_context (widget);
1587
1588 ctk_style_context_save (style);
1589 ctk_style_context_add_class (style, CTK_STYLE_CLASS_DND"dnd");
1590 ctk_style_context_set_state (style, CTK_STATE_FLAG_FOCUSED);
1591
1592 ctk_render_frame (style,
1593 cr,
1594 0, 0, width, height);
1595
1596 ctk_style_context_restore (style);
1597
1598 return FALSE(0);
1599}
1600
1601/* Queue a redraw of the dnd highlight rect */
1602static void
1603dnd_highlight_queue_redraw (CtkWidget *widget)
1604{
1605 BaulIconDndInfo *dnd_info;
1606 int width, height;
1607 CtkAllocation allocation;
1608
1609 dnd_info = BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
->details->dnd_info;
1610
1611 if (!dnd_info->highlighted)
1612 {
1613 return;
1614 }
1615
1616 ctk_widget_get_allocation (widget, &allocation);
1617 width = allocation.width;
1618 height = allocation.height;
1619
1620 /* we don't know how wide the shadow is exactly,
1621 * so we expose a 10-pixel wide border
1622 */
1623 ctk_widget_queue_draw_area (widget,
1624 0, 0,
1625 width, 10);
1626 ctk_widget_queue_draw_area (widget,
1627 0, 0,
1628 10, height);
1629 ctk_widget_queue_draw_area (widget,
1630 0, height - 10,
1631 width, 10);
1632 ctk_widget_queue_draw_area (widget,
1633 width - 10, 0,
1634 10, height);
1635}
1636
1637static void
1638start_dnd_highlight (CtkWidget *widget)
1639{
1640 BaulIconDndInfo *dnd_info;
1641 CtkWidget *toplevel;
1642
1643 dnd_info = BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
->details->dnd_info;
1644
1645 toplevel = ctk_widget_get_toplevel (widget);
1646 if (toplevel != NULL((void*)0) &&
1647 g_object_get_data (G_OBJECT (toplevel)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), (((GType) ((20) << (2))))))))
, "is_desktop_window"))
1648 {
1649 return;
1650 }
1651
1652 if (!dnd_info->highlighted)
1653 {
1654 dnd_info->highlighted = TRUE(!(0));
1655 g_signal_connect_after (widget, "draw",g_signal_connect_data ((widget), ("draw"), (((GCallback) (drag_highlight_draw
))), (((void*)0)), ((void*)0), G_CONNECT_AFTER)
1656 G_CALLBACK (drag_highlight_draw),g_signal_connect_data ((widget), ("draw"), (((GCallback) (drag_highlight_draw
))), (((void*)0)), ((void*)0), G_CONNECT_AFTER)
1657 NULL)g_signal_connect_data ((widget), ("draw"), (((GCallback) (drag_highlight_draw
))), (((void*)0)), ((void*)0), G_CONNECT_AFTER)
;
1658 dnd_highlight_queue_redraw (widget);
1659 }
1660}
1661
1662static void
1663stop_dnd_highlight (CtkWidget *widget)
1664{
1665 BaulIconDndInfo *dnd_info;
1666
1667 dnd_info = BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
->details->dnd_info;
1668
1669 if (dnd_info->highlighted)
1670 {
1671 g_signal_handlers_disconnect_by_func (widget,g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (drag_highlight_draw), (((void*)0)))
1672 drag_highlight_draw,g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (drag_highlight_draw), (((void*)0)))
1673 NULL)g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (drag_highlight_draw), (((void*)0)))
;
1674 dnd_highlight_queue_redraw (widget);
1675 dnd_info->highlighted = FALSE(0);
1676 }
1677}
1678
1679static gboolean
1680drag_motion_callback (CtkWidget *widget,
1681 CdkDragContext *context,
1682 int x, int y,
1683 guint32 time)
1684{
1685 int action;
1686
1687 baul_icon_container_ensure_drag_data (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
, context, time);
1688 baul_icon_container_position_shadow (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
, x, y);
1689 baul_icon_dnd_update_drop_target (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
, context, x, y);
1690 set_up_auto_scroll_if_needed (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
);
1691 /* Find out what the drop actions are based on our drag selection and
1692 * the drop target.
1693 */
1694 action = 0;
1695 baul_icon_container_get_drop_action (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
, context, x, y,
1696 &action);
1697 if (action != 0)
1698 {
1699 start_dnd_highlight (widget);
1700 }
1701
1702 cdk_drag_status (context, action, time);
1703
1704 return TRUE(!(0));
1705}
1706
1707static gboolean
1708drag_drop_callback (CtkWidget *widget,
1709 CdkDragContext *context,
1710 int x,
1711 int y,
1712 guint32 time,
1713 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
1714{
1715 BaulIconDndInfo *dnd_info;
1716
1717 dnd_info = BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
->details->dnd_info;
1718
1719 /* tell the drag_data_received callback that
1720 the drop occured and that it can actually
1721 process the actions.
1722 make sure it is going to be called at least once.
1723 */
1724 dnd_info->drag_info.drop_occured = TRUE(!(0));
1725
1726 get_data_on_first_target_we_support (widget, context, time, x, y);
1727
1728 return TRUE(!(0));
1729}
1730
1731void
1732baul_icon_dnd_end_drag (BaulIconContainer *container)
1733{
1734 BaulIconDndInfo *dnd_info;
1735
1736 g_return_if_fail (BAUL_IS_ICON_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (baul_icon_container_get_type()
); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning (((gchar*) 0
), ((const char*) (__func__)), "BAUL_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
1737
1738 dnd_info = container->details->dnd_info;
1739 g_return_if_fail (dnd_info != NULL)do { if ((dnd_info != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "dnd_info != NULL"
); return; } } while (0)
;
1740 stop_auto_scroll (container);
1741 /* Do nothing.
1742 * Can that possibly be right?
1743 */
1744}
1745
1746/** this callback is called in 2 cases.
1747 It is called upon drag_motion events to get the actual data
1748 In that case, it just makes sure it gets the data.
1749 It is called upon drop_drop events to execute the actual
1750 actions on the received action. In that case, it actually first makes sure
1751 that we have got the data then processes it.
1752*/
1753
1754static void
1755drag_data_received_callback (CtkWidget *widget,
1756 CdkDragContext *context,
1757 int x,
1758 int y,
1759 CtkSelectionData *data,
1760 guint info,
1761 guint32 time,
1762 gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
1763{
1764 BaulDragInfo *drag_info;
1765 gboolean success;
1766
1767 drag_info = &(BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
->details->dnd_info->drag_info);
1768
1769 drag_info->got_drop_data_type = TRUE(!(0));
1770 drag_info->data_type = info;
1771
1772 switch (info)
1773 {
1774 case BAUL_ICON_DND_CAFE_ICON_LIST:
1775 baul_icon_container_dropped_icon_feedback (widget, data, x, y);
1776 break;
1777 case BAUL_ICON_DND_COLOR:
1778 case BAUL_ICON_DND_BGIMAGE:
1779 case BAUL_ICON_DND_KEYWORD:
1780 case BAUL_ICON_DND_URI_LIST:
1781 case BAUL_ICON_DND_TEXT:
1782 case BAUL_ICON_DND_RESET_BACKGROUND:
1783 case BAUL_ICON_DND_XDNDDIRECTSAVE:
1784 case BAUL_ICON_DND_RAW:
1785 /* Save the data so we can do the actual work on drop. */
1786 if (drag_info->selection_data != NULL((void*)0))
1787 {
1788 ctk_selection_data_free (drag_info->selection_data);
1789 }
1790 drag_info->selection_data = ctk_selection_data_copy (data);
1791 break;
1792
1793 /* Netscape keeps sending us the data, even though we accept the first drag */
1794 case BAUL_ICON_DND_NETSCAPE_URL:
1795 if (drag_info->selection_data != NULL((void*)0))
1796 {
1797 ctk_selection_data_free (drag_info->selection_data);
1798 drag_info->selection_data = ctk_selection_data_copy (data);
1799 }
1800 break;
1801 case BAUL_ICON_DND_ROOTWINDOW_DROP:
1802 /* Do nothing, this won't even happen, since we don't want to call get_data twice */
1803 break;
1804 }
1805
1806 /* this is the second use case of this callback.
1807 * we have to do the actual work for the drop.
1808 */
1809 if (drag_info->drop_occured)
1810 {
1811 EelBackground *background;
1812 char *tmp;
1813 const char *tmp_raw;
1814 int length;
1815
1816 success = FALSE(0);
1817 switch (info)
1818 {
1819 case BAUL_ICON_DND_CAFE_ICON_LIST:
1820 baul_icon_container_receive_dropped_icons
1821 (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
,
1822 context, x, y);
1823 break;
1824 case BAUL_ICON_DND_COLOR:
1825 receive_dropped_color (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
,
1826 x, y,
1827 cdk_drag_context_get_selected_action (context),
1828 data);
1829 success = TRUE(!(0));
1830 break;
1831 case BAUL_ICON_DND_BGIMAGE:
1832 receive_dropped_tile_image
1833 (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
,
1834 cdk_drag_context_get_selected_action (context),
1835 data);
1836 break;
1837 case BAUL_ICON_DND_KEYWORD:
1838 receive_dropped_keyword
1839 (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
,
1840 (char *) ctk_selection_data_get_data (data), x, y);
1841 break;
1842 case BAUL_ICON_DND_NETSCAPE_URL:
1843 receive_dropped_netscape_url
1844 (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
,
1845 (char *) ctk_selection_data_get_data (data), context, x, y);
1846 success = TRUE(!(0));
1847 break;
1848 case BAUL_ICON_DND_URI_LIST:
1849 receive_dropped_uri_list
1850 (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
,
1851 (char *) ctk_selection_data_get_data (data), context, x, y);
1852 success = TRUE(!(0));
1853 break;
1854 case BAUL_ICON_DND_TEXT:
1855 tmp = ctk_selection_data_get_text (data);
1856 receive_dropped_text
1857 (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
,
1858 (char *) tmp, context, x, y);
1859 success = TRUE(!(0));
1860 g_free (tmp);
1861 break;
1862 case BAUL_ICON_DND_RAW:
1863 length = ctk_selection_data_get_length (data);
1864 tmp_raw = ctk_selection_data_get_data (data);
1865 receive_dropped_raw
1866 (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
,
1867 tmp_raw, length, drag_info->direct_save_uri,
1868 context, x, y);
1869 success = TRUE(!(0));
1870 break;
1871 case BAUL_ICON_DND_RESET_BACKGROUND:
1872 background = eel_get_widget_background (widget);
1873 if (background != NULL((void*)0))
1874 {
1875 eel_background_reset (background);
1876 }
1877 ctk_drag_finish (context, FALSE(0), FALSE(0), time);
1878 break;
1879 case BAUL_ICON_DND_ROOTWINDOW_DROP:
1880 /* Do nothing, everything is done by the sender */
1881 break;
1882 case BAUL_ICON_DND_XDNDDIRECTSAVE:
1883 {
1884 const guchar *selection_data;
1885 gint selection_length;
1886 gint selection_format;
1887
1888 selection_data = ctk_selection_data_get_data (drag_info->selection_data);
1889 selection_length = ctk_selection_data_get_length (drag_info->selection_data);
1890 selection_format = ctk_selection_data_get_format (drag_info->selection_data);
1891
1892 if (selection_format == 8 &&
1893 selection_length == 1 &&
1894 selection_data[0] == 'F')
1895 {
1896 ctk_drag_get_data (widget, context,
1897 cdk_atom_intern (BAUL_ICON_DND_RAW_TYPE"application/octet-stream",
1898 FALSE(0)),
1899 time);
1900 return;
1901 }
1902 else if (selection_format == 8 &&
1903 selection_length == 1 &&
1904 selection_data[0] == 'F' &&
1905 drag_info->direct_save_uri != NULL((void*)0))
This statement is never executed
1906 {
1907 CdkPoint p;
1908 GFile *location;
1909
1910 location = g_file_new_for_uri (drag_info->direct_save_uri);
1911
1912 baul_file_changes_queue_file_added (location);
1913 p.x = x;
1914 p.y = y;
1915 baul_file_changes_queue_schedule_position_set (
1916 location,
1917 p,
1918 cdk_x11_screen_get_screen_number (
1919 ctk_widget_get_screen (widget)));
1920 g_object_unref (location);
1921 baul_file_changes_consume_changes (TRUE(!(0)));
1922 success = TRUE(!(0));
1923 }
1924 break;
1925 } /* BAUL_ICON_DND_XDNDDIRECTSAVE */
1926 }
1927 ctk_drag_finish (context, success, FALSE(0), time);
1928
1929 baul_icon_container_free_drag_data (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
);
1930
1931 set_drop_target (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((widget)), (baul_icon_container_get_type())
))))
, NULL((void*)0));
1932
1933 /* reinitialise it for the next dnd */
1934 drag_info->drop_occured = FALSE(0);
1935 }
1936
1937}
1938
1939void
1940baul_icon_dnd_init (BaulIconContainer *container)
1941{
1942 CtkTargetList *targets;
1943 int n_elements;
1944
1945 g_return_if_fail (container != NULL)do { if ((container != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "container != NULL"
); return; } } while (0)
;
1946 g_return_if_fail (BAUL_IS_ICON_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (baul_icon_container_get_type()
); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning (((gchar*) 0
), ((const char*) (__func__)), "BAUL_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
1947
1948
1949 container->details->dnd_info = g_new0 (BaulIconDndInfo, 1)((BaulIconDndInfo *) g_malloc0_n ((1), sizeof (BaulIconDndInfo
)))
;
1950 baul_drag_init (&container->details->dnd_info->drag_info,
1951 drag_types, G_N_ELEMENTS (drag_types)(sizeof (drag_types) / sizeof ((drag_types)[0])), TRUE(!(0)));
1952
1953 /* Set up the widget as a drag destination.
1954 * (But not a source, as drags starting from this widget will be
1955 * implemented by dealing with events manually.)
1956 */
1957 n_elements = G_N_ELEMENTS (drop_types)(sizeof (drop_types) / sizeof ((drop_types)[0]));
1958 if (!baul_icon_container_get_is_desktop (container))
1959 {
1960 /* Don't set up rootwindow drop */
1961 n_elements -= 1;
1962 }
1963 ctk_drag_dest_set (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
,
1964 0,
1965 drop_types, n_elements,
1966 CDK_ACTION_COPY | CDK_ACTION_MOVE | CDK_ACTION_LINK | CDK_ACTION_ASK);
1967
1968 targets = ctk_drag_dest_get_target_list (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
);
1969 ctk_target_list_add_text_targets (targets, BAUL_ICON_DND_TEXT);
1970
1971
1972 /* Messages for outgoing drag. */
1973 g_signal_connect (container, "drag_begin",g_signal_connect_data ((container), ("drag_begin"), (((GCallback
) (drag_begin_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
1974 G_CALLBACK (drag_begin_callback), NULL)g_signal_connect_data ((container), ("drag_begin"), (((GCallback
) (drag_begin_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1975 g_signal_connect (container, "drag_data_get",g_signal_connect_data ((container), ("drag_data_get"), (((GCallback
) (drag_data_get_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
1976 G_CALLBACK (drag_data_get_callback), NULL)g_signal_connect_data ((container), ("drag_data_get"), (((GCallback
) (drag_data_get_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1977 g_signal_connect (container, "drag_end",g_signal_connect_data ((container), ("drag_end"), (((GCallback
) (drag_end_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
1978 G_CALLBACK (drag_end_callback), NULL)g_signal_connect_data ((container), ("drag_end"), (((GCallback
) (drag_end_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1979
1980 /* Messages for incoming drag. */
1981 g_signal_connect (container, "drag_data_received",g_signal_connect_data ((container), ("drag_data_received"), (
((GCallback) (drag_data_received_callback))), (((void*)0)), (
(void*)0), (GConnectFlags) 0)
1982 G_CALLBACK (drag_data_received_callback), NULL)g_signal_connect_data ((container), ("drag_data_received"), (
((GCallback) (drag_data_received_callback))), (((void*)0)), (
(void*)0), (GConnectFlags) 0)
;
1983 g_signal_connect (container, "drag_motion",g_signal_connect_data ((container), ("drag_motion"), (((GCallback
) (drag_motion_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
1984 G_CALLBACK (drag_motion_callback), NULL)g_signal_connect_data ((container), ("drag_motion"), (((GCallback
) (drag_motion_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1985 g_signal_connect (container, "drag_drop",g_signal_connect_data ((container), ("drag_drop"), (((GCallback
) (drag_drop_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
1986 G_CALLBACK (drag_drop_callback), NULL)g_signal_connect_data ((container), ("drag_drop"), (((GCallback
) (drag_drop_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1987 g_signal_connect (container, "drag_leave",g_signal_connect_data ((container), ("drag_leave"), (((GCallback
) (drag_leave_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
1988 G_CALLBACK (drag_leave_callback), NULL)g_signal_connect_data ((container), ("drag_leave"), (((GCallback
) (drag_leave_callback))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1989}
1990
1991void
1992baul_icon_dnd_fini (BaulIconContainer *container)
1993{
1994 g_return_if_fail (BAUL_IS_ICON_CONTAINER (container))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((container)); GType __t = (baul_icon_container_get_type()
); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning (((gchar*) 0
), ((const char*) (__func__)), "BAUL_IS_ICON_CONTAINER (container)"
); return; } } while (0)
;
1995
1996 if (container->details->dnd_info != NULL((void*)0))
1997 {
1998 stop_auto_scroll (container);
1999
2000 baul_drag_finalize (&container->details->dnd_info->drag_info);
2001 container->details->dnd_info = NULL((void*)0);
2002 }
2003}