File: | libbaul-private/baul-icon-dnd.c |
Warning: | line 1903, column 22 This statement is never executed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
65 | static 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 | |
71 | static 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 | }; |
86 | static void stop_dnd_highlight (CtkWidget *widget); |
87 | static void dnd_highlight_queue_redraw (CtkWidget *widget); |
88 | |
89 | static CtkTargetList *drop_types_list = NULL((void*)0); |
90 | static CtkTargetList *drop_types_list_root = NULL((void*)0); |
91 | |
92 | static 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 | |
97 | static EelCanvasItem * |
98 | create_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 | */ |
177 | static void |
178 | set_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 */ |
190 | typedef struct |
191 | { |
192 | gpointer iterator_context; |
193 | BaulDragEachSelectedItemDataGet iteratee; |
194 | gpointer iteratee_data; |
195 | } IconGetDataBinderContext; |
196 | |
197 | static void |
198 | canvas_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 | |
220 | static void |
221 | canvas_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 | |
231 | static gboolean |
232 | icon_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 | */ |
280 | static void |
281 | baul_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 | */ |
305 | static void |
306 | each_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 */ |
322 | static void |
323 | drag_data_get_callback (CtkWidget *widget, |
324 | CdkDragContext *context, |
325 | CtkSelectionData *selection_data, |
326 | guint info, |
327 | guint32 time, |
328 | gpointer data) |
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 | |
345 | static void |
346 | baul_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 | |
365 | static void |
366 | baul_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 | |
394 | static char * |
395 | get_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 | |
424 | static void |
425 | set_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 */ |
471 | static void |
472 | get_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 | |
533 | static void |
534 | baul_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 | |
548 | static void |
549 | drag_end_callback (CtkWidget *widget, |
550 | CdkDragContext *context, |
551 | gpointer data) |
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 | |
563 | static BaulIcon * |
564 | baul_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 | |
606 | static char * |
607 | get_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 | |
617 | static gboolean |
618 | baul_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 | |
645 | static CdkDragAction |
646 | get_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 | |
668 | static void |
669 | receive_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 */ |
692 | static void |
693 | receive_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 */ |
714 | static void |
715 | receive_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 */ |
756 | static void |
757 | receive_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 */ |
778 | static void |
779 | receive_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 */ |
800 | static void |
801 | receive_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 */ |
822 | static void |
823 | receive_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 | |
845 | static int |
846 | auto_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 | |
933 | static void |
934 | set_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 | |
942 | static void |
943 | stop_auto_scroll (BaulIconContainer *container) |
944 | { |
945 | baul_drag_autoscroll_stop (&container->details->dnd_info->drag_info); |
946 | } |
947 | |
948 | static void |
949 | handle_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 | |
1016 | static void |
1017 | handle_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 | |
1099 | static char * |
1100 | baul_icon_container_find_drop_target (BaulIconContainer *container, |
1101 | CdkDragContext *context, |
1102 | int x, int y, |
1103 | gboolean *icon_hit, |
1104 | gboolean rewrite_desktop) |
1105 | { |
1106 | BaulIcon *drop_target_icon; |
1107 | double world_x, world_y; |
1108 | |
1109 | if (icon_hit) |
1110 | { |
1111 | *icon_hit = FALSE(0); |
1112 | } |
1113 | |
1114 | if (!container->details->dnd_info->drag_info.got_drop_data_type) |
1115 | { |
1116 | return NULL((void*)0); |
1117 | } |
1118 | |
1119 | 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); |
1120 | |
1121 | /* FIXME bugzilla.gnome.org 42485: |
1122 | * These "can_accept_items" tests need to be done by |
1123 | * the icon view, not here. This file is not supposed to know |
1124 | * that the target is a file. |
1125 | */ |
1126 | |
1127 | /* Find the item we hit with our drop, if any */ |
1128 | drop_target_icon = baul_icon_container_item_at (container, world_x, world_y); |
1129 | if (drop_target_icon != NULL((void*)0)) |
1130 | { |
1131 | char *icon_uri; |
1132 | |
1133 | icon_uri = baul_icon_container_get_icon_uri (container, drop_target_icon); |
1134 | if (icon_uri != NULL((void*)0)) |
1135 | { |
1136 | BaulFile *file; |
1137 | |
1138 | file = baul_file_get_by_uri (icon_uri); |
1139 | |
1140 | if (!baul_drag_can_accept_info (file, |
1141 | container->details->dnd_info->drag_info.data_type, |
1142 | container->details->dnd_info->drag_info.selection_list)) |
1143 | { |
1144 | /* the item we dropped our selection on cannot accept the items, |
1145 | * do the same thing as if we just dropped the items on the canvas |
1146 | */ |
1147 | drop_target_icon = NULL((void*)0); |
1148 | } |
1149 | |
1150 | g_free (icon_uri); |
1151 | baul_file_unref (file); |
1152 | } |
1153 | } |
1154 | |
1155 | if (drop_target_icon == NULL((void*)0)) |
1156 | { |
1157 | char *container_uri; |
1158 | |
1159 | if (icon_hit) |
1160 | { |
1161 | *icon_hit = FALSE(0); |
1162 | } |
1163 | |
1164 | container_uri = get_container_uri (container); |
1165 | |
1166 | if (rewrite_desktop && |
1167 | container_uri != NULL((void*)0) && |
1168 | eel_uri_is_desktop (container_uri)) |
1169 | { |
1170 | g_free (container_uri); |
1171 | container_uri = baul_get_desktop_directory_uri (); |
1172 | } |
1173 | |
1174 | return container_uri; |
1175 | } |
1176 | |
1177 | if (icon_hit) |
1178 | { |
1179 | *icon_hit = TRUE(!(0)); |
1180 | } |
1181 | return baul_icon_container_get_icon_drop_target_uri (container, drop_target_icon); |
1182 | } |
1183 | |
1184 | static gboolean |
1185 | selection_is_image_file (GList *selection_list) |
1186 | { |
1187 | const char *mime_type; |
1188 | BaulDragSelectionItem *selected_item; |
1189 | gboolean result; |
1190 | GFile *location; |
1191 | GFileInfo *info; |
1192 | |
1193 | /* Make sure only one item is selected */ |
1194 | if (selection_list == NULL((void*)0) || |
1195 | selection_list->next != NULL((void*)0)) |
1196 | { |
1197 | return FALSE(0); |
1198 | } |
1199 | |
1200 | selected_item = selection_list->data; |
1201 | |
1202 | mime_type = NULL((void*)0); |
1203 | |
1204 | location = g_file_new_for_uri (selected_item->uri); |
1205 | info = g_file_query_info (location, |
1206 | G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE"standard::content-type", |
1207 | 0, NULL((void*)0), NULL((void*)0)); |
1208 | if (info) |
1209 | { |
1210 | mime_type = g_file_info_get_content_type (info); |
1211 | } |
1212 | |
1213 | result = eel_istr_has_prefix (mime_type, "image/"); |
1214 | |
1215 | if (info) |
1216 | { |
1217 | g_object_unref (info); |
1218 | } |
1219 | g_object_unref (location); |
1220 | |
1221 | return result; |
1222 | } |
1223 | |
1224 | |
1225 | static void |
1226 | baul_icon_container_receive_dropped_icons (BaulIconContainer *container, |
1227 | CdkDragContext *context, |
1228 | int x, int y) |
1229 | { |
1230 | char *drop_target; |
1231 | gboolean local_move_only; |
1232 | double world_x, world_y; |
1233 | gboolean icon_hit; |
1234 | CdkDragAction action, real_action; |
1235 | |
1236 | drop_target = NULL((void*)0); |
1237 | |
1238 | if (container->details->dnd_info->drag_info.selection_list == NULL((void*)0)) |
1239 | { |
1240 | return; |
1241 | } |
1242 | |
1243 | real_action = cdk_drag_context_get_selected_action (context); |
1244 | |
1245 | if (real_action == CDK_ACTION_ASK) |
1246 | { |
1247 | /* FIXME bugzilla.gnome.org 42485: This belongs in FMDirectoryView, not here. */ |
1248 | /* Check for special case items in selection list */ |
1249 | if (baul_drag_selection_includes_special_link (container->details->dnd_info->drag_info.selection_list)) |
1250 | { |
1251 | /* We only want to move the trash */ |
1252 | action = CDK_ACTION_MOVE; |
1253 | } |
1254 | else |
1255 | { |
1256 | action = CDK_ACTION_MOVE | CDK_ACTION_COPY | CDK_ACTION_LINK; |
1257 | |
1258 | if (selection_is_image_file (container->details->dnd_info->drag_info.selection_list)) |
1259 | { |
1260 | action |= BAUL_DND_ACTION_SET_AS_BACKGROUND; |
1261 | } |
1262 | } |
1263 | real_action = baul_drag_drop_action_ask (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((container)), ((ctk_widget_get_type ())))))), action); |
1264 | } |
1265 | |
1266 | if (real_action == (CdkDragAction) BAUL_DND_ACTION_SET_AS_BACKGROUND) |
1267 | { |
1268 | BaulDragSelectionItem *selected_item; |
1269 | |
1270 | selected_item = container->details->dnd_info->drag_info.selection_list->data; |
1271 | 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 ()))))))), |
1272 | real_action, selected_item->uri); |
1273 | return; |
1274 | } |
1275 | |
1276 | if (real_action > 0) |
1277 | { |
1278 | eel_canvas_window_to_world (EEL_CANVAS (container)((((EelCanvas*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((container)), ((eel_canvas_get_type ())))))), |
1279 | 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 ())))))))), |
1280 | 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 ())))))))), |
1281 | &world_x, &world_y); |
1282 | |
1283 | drop_target = baul_icon_container_find_drop_target (container, |
1284 | context, x, y, &icon_hit, FALSE(0)); |
1285 | |
1286 | local_move_only = FALSE(0); |
1287 | if (!icon_hit && real_action == CDK_ACTION_MOVE) |
1288 | { |
1289 | /* we can just move the icon positions if the move ended up in |
1290 | * the item's parent container |
1291 | */ |
1292 | local_move_only = baul_icon_container_selection_items_local |
1293 | (container, container->details->dnd_info->drag_info.selection_list); |
1294 | } |
1295 | |
1296 | if (local_move_only) |
1297 | { |
1298 | handle_local_move (container, world_x, world_y); |
1299 | } |
1300 | else |
1301 | { |
1302 | handle_nonlocal_move (container, real_action, world_x, world_y, drop_target, icon_hit); |
1303 | } |
1304 | } |
1305 | |
1306 | g_free (drop_target); |
1307 | baul_drag_destroy_selection_list (container->details->dnd_info->drag_info.selection_list); |
1308 | container->details->dnd_info->drag_info.selection_list = NULL((void*)0); |
1309 | } |
1310 | |
1311 | static void |
1312 | baul_icon_container_get_drop_action (BaulIconContainer *container, |
1313 | CdkDragContext *context, |
1314 | int x, int y, |
1315 | int *action) |
1316 | { |
1317 | char *drop_target; |
1318 | gboolean icon_hit; |
1319 | BaulIcon *icon; |
1320 | double world_x, world_y; |
1321 | |
1322 | icon_hit = FALSE(0); |
1323 | if (!container->details->dnd_info->drag_info.got_drop_data_type) |
1324 | { |
1325 | /* drag_data_received_callback didn't get called yet */ |
1326 | return; |
1327 | } |
1328 | |
1329 | /* find out if we're over an icon */ |
1330 | 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); |
1331 | |
1332 | icon = baul_icon_container_item_at (container, world_x, world_y); |
1333 | |
1334 | *action = 0; |
1335 | |
1336 | /* case out on the type of object being dragged */ |
1337 | switch (container->details->dnd_info->drag_info.data_type) |
1338 | { |
1339 | case BAUL_ICON_DND_CAFE_ICON_LIST: |
1340 | if (container->details->dnd_info->drag_info.selection_list == NULL((void*)0)) |
1341 | { |
1342 | return; |
1343 | } |
1344 | drop_target = baul_icon_container_find_drop_target (container, |
1345 | context, x, y, &icon_hit, FALSE(0)); |
1346 | if (!drop_target) |
1347 | { |
1348 | return; |
1349 | } |
1350 | baul_drag_default_drop_action_for_icons (context, drop_target, |
1351 | container->details->dnd_info->drag_info.selection_list, |
1352 | action); |
1353 | g_free (drop_target); |
1354 | break; |
1355 | case BAUL_ICON_DND_URI_LIST: |
1356 | drop_target = baul_icon_container_find_drop_target (container, |
1357 | context, x, y, &icon_hit, FALSE(0)); |
1358 | *action = baul_drag_default_drop_action_for_uri_list (context, drop_target); |
1359 | |
1360 | g_free (drop_target); |
1361 | break; |
1362 | |
1363 | /* handle emblems by setting the action if we're over an object */ |
1364 | case BAUL_ICON_DND_KEYWORD: |
1365 | if (icon != NULL((void*)0)) |
1366 | { |
1367 | *action = cdk_drag_context_get_suggested_action (context); |
1368 | } |
1369 | break; |
1370 | |
1371 | case BAUL_ICON_DND_NETSCAPE_URL: |
1372 | *action = baul_drag_default_drop_action_for_netscape_url (context); |
1373 | break; |
1374 | |
1375 | case BAUL_ICON_DND_COLOR: |
1376 | case BAUL_ICON_DND_BGIMAGE: |
1377 | case BAUL_ICON_DND_RESET_BACKGROUND: |
1378 | case BAUL_ICON_DND_ROOTWINDOW_DROP: |
1379 | *action = cdk_drag_context_get_suggested_action (context); |
1380 | break; |
1381 | |
1382 | case BAUL_ICON_DND_TEXT: |
1383 | case BAUL_ICON_DND_XDNDDIRECTSAVE: |
1384 | case BAUL_ICON_DND_RAW: |
1385 | *action = CDK_ACTION_COPY; |
1386 | break; |
1387 | } |
1388 | } |
1389 | |
1390 | static void |
1391 | set_drop_target (BaulIconContainer *container, |
1392 | BaulIcon *icon) |
1393 | { |
1394 | BaulIcon *old_icon; |
1395 | |
1396 | /* Check if current drop target changed, update icon drop |
1397 | * higlight if needed. |
1398 | */ |
1399 | old_icon = container->details->drop_target; |
1400 | if (icon == old_icon) |
1401 | { |
1402 | return; |
1403 | } |
1404 | |
1405 | /* Remember the new drop target for the next round. */ |
1406 | container->details->drop_target = icon; |
1407 | baul_icon_container_update_icon (container, old_icon); |
1408 | baul_icon_container_update_icon (container, icon); |
1409 | } |
1410 | |
1411 | static void |
1412 | baul_icon_dnd_update_drop_target (BaulIconContainer *container, |
1413 | CdkDragContext *context, |
1414 | int x, int y) |
1415 | { |
1416 | BaulIcon *icon; |
1417 | double world_x, world_y; |
1418 | |
1419 | 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" , 1419, ((const char*) (__func__)), "BAUL_IS_ICON_CONTAINER (container)" ); } while (0); |
1420 | |
1421 | 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); |
1422 | |
1423 | /* Find the item we hit with our drop, if any. */ |
1424 | icon = baul_icon_container_item_at (container, world_x, world_y); |
1425 | |
1426 | /* FIXME bugzilla.gnome.org 42485: |
1427 | * These "can_accept_items" tests need to be done by |
1428 | * the icon view, not here. This file is not supposed to know |
1429 | * that the target is a file. |
1430 | */ |
1431 | |
1432 | /* Find if target icon accepts our drop. */ |
1433 | if (icon != NULL((void*)0) && (container->details->dnd_info->drag_info.data_type != BAUL_ICON_DND_KEYWORD)) |
1434 | { |
1435 | BaulFile *file; |
1436 | char *uri; |
1437 | |
1438 | uri = baul_icon_container_get_icon_uri (container, icon); |
1439 | file = baul_file_get_by_uri (uri); |
1440 | g_free (uri); |
1441 | |
1442 | if (!baul_drag_can_accept_info (file, |
1443 | container->details->dnd_info->drag_info.data_type, |
1444 | container->details->dnd_info->drag_info.selection_list)) |
1445 | { |
1446 | icon = NULL((void*)0); |
1447 | } |
1448 | |
1449 | baul_file_unref (file); |
1450 | } |
1451 | |
1452 | set_drop_target (container, icon); |
1453 | } |
1454 | |
1455 | static void |
1456 | baul_icon_container_free_drag_data (BaulIconContainer *container) |
1457 | { |
1458 | BaulIconDndInfo *dnd_info; |
1459 | |
1460 | dnd_info = container->details->dnd_info; |
1461 | |
1462 | dnd_info->drag_info.got_drop_data_type = FALSE(0); |
1463 | |
1464 | if (dnd_info->shadow != NULL((void*)0)) |
1465 | { |
1466 | eel_canvas_item_destroy (dnd_info->shadow); |
1467 | dnd_info->shadow = NULL((void*)0); |
1468 | } |
1469 | |
1470 | if (dnd_info->drag_info.selection_data != NULL((void*)0)) |
1471 | { |
1472 | ctk_selection_data_free (dnd_info->drag_info.selection_data); |
1473 | dnd_info->drag_info.selection_data = NULL((void*)0); |
1474 | } |
1475 | |
1476 | if (dnd_info->drag_info.direct_save_uri != NULL((void*)0)) |
1477 | { |
1478 | g_free (dnd_info->drag_info.direct_save_uri); |
1479 | dnd_info->drag_info.direct_save_uri = NULL((void*)0); |
1480 | } |
1481 | } |
1482 | |
1483 | static void |
1484 | drag_leave_callback (CtkWidget *widget, |
1485 | CdkDragContext *context, |
1486 | guint32 time, |
1487 | gpointer data) |
1488 | { |
1489 | BaulIconDndInfo *dnd_info; |
1490 | |
1491 | dnd_info = BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) ))))->details->dnd_info; |
1492 | |
1493 | if (dnd_info->shadow != NULL((void*)0)) |
1494 | eel_canvas_item_hide (dnd_info->shadow); |
1495 | |
1496 | stop_dnd_highlight (widget); |
1497 | |
1498 | set_drop_target (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) )))), NULL((void*)0)); |
1499 | stop_auto_scroll (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) ))))); |
1500 | baul_icon_container_free_drag_data(BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) ))))); |
1501 | } |
1502 | |
1503 | static void |
1504 | drag_begin_callback (CtkWidget *widget, |
1505 | CdkDragContext *context, |
1506 | gpointer data) |
1507 | { |
1508 | BaulIconContainer *container; |
1509 | cairo_surface_t *surface; |
1510 | double x1, y1, x2, y2, winx, winy; |
1511 | int x_offset, y_offset; |
1512 | int start_x, start_y; |
1513 | |
1514 | container = BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) )))); |
1515 | |
1516 | start_x = container->details->dnd_info->drag_info.start_x + |
1517 | ctk_adjustment_get_value (ctk_scrollable_get_hadjustment (CTK_SCROLLABLE (container)((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((container)), ((ctk_scrollable_get_type ())))))))); |
1518 | start_y = container->details->dnd_info->drag_info.start_y + |
1519 | ctk_adjustment_get_value (ctk_scrollable_get_vadjustment (CTK_SCROLLABLE (container)((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((container)), ((ctk_scrollable_get_type ())))))))); |
1520 | |
1521 | /* create a pixmap and mask to drag with */ |
1522 | surface = baul_icon_canvas_item_get_drag_surface (container->details->drag_icon->item); |
1523 | |
1524 | /* compute the image's offset */ |
1525 | 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 ())))))), |
1526 | &x1, &y1, &x2, &y2); |
1527 | eel_canvas_world_to_window (EEL_CANVAS (container)((((EelCanvas*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((container)), ((eel_canvas_get_type ())))))), |
1528 | x1, y1, &winx, &winy); |
1529 | x_offset = start_x - winx; |
1530 | y_offset = start_y - winy; |
1531 | |
1532 | cairo_surface_set_device_offset (surface, -x_offset, -y_offset); |
1533 | ctk_drag_set_icon_surface (context, surface); |
1534 | cairo_surface_destroy (surface); |
1535 | } |
1536 | |
1537 | void |
1538 | baul_icon_dnd_begin_drag (BaulIconContainer *container, |
1539 | CdkDragAction actions, |
1540 | int button, |
1541 | CdkEventMotion *event, |
1542 | int start_x, |
1543 | int start_y) |
1544 | { |
1545 | BaulIconDndInfo *dnd_info; |
1546 | |
1547 | 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); |
1548 | 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); |
1549 | |
1550 | dnd_info = container->details->dnd_info; |
1551 | 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); |
1552 | |
1553 | /* Notice that the event is in bin_window coordinates, because of |
1554 | the way the canvas handles events. |
1555 | */ |
1556 | dnd_info->drag_info.start_x = start_x - |
1557 | ctk_adjustment_get_value (ctk_scrollable_get_hadjustment (CTK_SCROLLABLE (container)((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((container)), ((ctk_scrollable_get_type ())))))))); |
1558 | dnd_info->drag_info.start_y = start_y - |
1559 | ctk_adjustment_get_value (ctk_scrollable_get_vadjustment (CTK_SCROLLABLE (container)((((CtkScrollable*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((container)), ((ctk_scrollable_get_type ())))))))); |
1560 | |
1561 | /* start the drag */ |
1562 | ctk_drag_begin_with_coordinates (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((container)), ((ctk_widget_get_type ())))))), |
1563 | dnd_info->drag_info.target_list, |
1564 | actions, |
1565 | button, |
1566 | (CdkEvent *) event, |
1567 | dnd_info->drag_info.start_x, |
1568 | dnd_info->drag_info.start_y); |
1569 | } |
1570 | |
1571 | static gboolean |
1572 | drag_highlight_draw (CtkWidget *widget, |
1573 | cairo_t *cr, |
1574 | gpointer user_data) |
1575 | { |
1576 | gint width, height; |
1577 | CdkWindow *window; |
1578 | CtkStyleContext *style; |
1579 | |
1580 | window = ctk_widget_get_window (widget); |
1581 | width = cdk_window_get_width (window); |
1582 | height = cdk_window_get_height (window); |
1583 | |
1584 | style = ctk_widget_get_style_context (widget); |
1585 | |
1586 | ctk_style_context_save (style); |
1587 | ctk_style_context_add_class (style, CTK_STYLE_CLASS_DND"dnd"); |
1588 | ctk_style_context_set_state (style, CTK_STATE_FLAG_FOCUSED); |
1589 | |
1590 | ctk_render_frame (style, |
1591 | cr, |
1592 | 0, 0, width, height); |
1593 | |
1594 | ctk_style_context_restore (style); |
1595 | |
1596 | return FALSE(0); |
1597 | } |
1598 | |
1599 | /* Queue a redraw of the dnd highlight rect */ |
1600 | static void |
1601 | dnd_highlight_queue_redraw (CtkWidget *widget) |
1602 | { |
1603 | BaulIconDndInfo *dnd_info; |
1604 | int width, height; |
1605 | CtkAllocation allocation; |
1606 | |
1607 | dnd_info = BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) ))))->details->dnd_info; |
1608 | |
1609 | if (!dnd_info->highlighted) |
1610 | { |
1611 | return; |
1612 | } |
1613 | |
1614 | ctk_widget_get_allocation (widget, &allocation); |
1615 | width = allocation.width; |
1616 | height = allocation.height; |
1617 | |
1618 | /* we don't know how wide the shadow is exactly, |
1619 | * so we expose a 10-pixel wide border |
1620 | */ |
1621 | ctk_widget_queue_draw_area (widget, |
1622 | 0, 0, |
1623 | width, 10); |
1624 | ctk_widget_queue_draw_area (widget, |
1625 | 0, 0, |
1626 | 10, height); |
1627 | ctk_widget_queue_draw_area (widget, |
1628 | 0, height - 10, |
1629 | width, 10); |
1630 | ctk_widget_queue_draw_area (widget, |
1631 | width - 10, 0, |
1632 | 10, height); |
1633 | } |
1634 | |
1635 | static void |
1636 | start_dnd_highlight (CtkWidget *widget) |
1637 | { |
1638 | BaulIconDndInfo *dnd_info; |
1639 | CtkWidget *toplevel; |
1640 | |
1641 | dnd_info = BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) ))))->details->dnd_info; |
1642 | |
1643 | toplevel = ctk_widget_get_toplevel (widget); |
1644 | if (toplevel != NULL((void*)0) && |
1645 | g_object_get_data (G_OBJECT (toplevel)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((toplevel)), (((GType) ((20) << (2)))))))), "is_desktop_window")) |
1646 | { |
1647 | return; |
1648 | } |
1649 | |
1650 | if (!dnd_info->highlighted) |
1651 | { |
1652 | dnd_info->highlighted = TRUE(!(0)); |
1653 | g_signal_connect_after (widget, "draw",g_signal_connect_data ((widget), ("draw"), (((GCallback) (drag_highlight_draw ))), (((void*)0)), ((void*)0), G_CONNECT_AFTER) |
1654 | G_CALLBACK (drag_highlight_draw),g_signal_connect_data ((widget), ("draw"), (((GCallback) (drag_highlight_draw ))), (((void*)0)), ((void*)0), G_CONNECT_AFTER) |
1655 | NULL)g_signal_connect_data ((widget), ("draw"), (((GCallback) (drag_highlight_draw ))), (((void*)0)), ((void*)0), G_CONNECT_AFTER); |
1656 | dnd_highlight_queue_redraw (widget); |
1657 | } |
1658 | } |
1659 | |
1660 | static void |
1661 | stop_dnd_highlight (CtkWidget *widget) |
1662 | { |
1663 | BaulIconDndInfo *dnd_info; |
1664 | |
1665 | dnd_info = BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) ))))->details->dnd_info; |
1666 | |
1667 | if (dnd_info->highlighted) |
1668 | { |
1669 | 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))) |
1670 | 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))) |
1671 | 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))); |
1672 | dnd_highlight_queue_redraw (widget); |
1673 | dnd_info->highlighted = FALSE(0); |
1674 | } |
1675 | } |
1676 | |
1677 | static gboolean |
1678 | drag_motion_callback (CtkWidget *widget, |
1679 | CdkDragContext *context, |
1680 | int x, int y, |
1681 | guint32 time) |
1682 | { |
1683 | int action; |
1684 | |
1685 | 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); |
1686 | 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); |
1687 | 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); |
1688 | set_up_auto_scroll_if_needed (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) ))))); |
1689 | /* Find out what the drop actions are based on our drag selection and |
1690 | * the drop target. |
1691 | */ |
1692 | action = 0; |
1693 | 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, |
1694 | &action); |
1695 | if (action != 0) |
1696 | { |
1697 | start_dnd_highlight (widget); |
1698 | } |
1699 | |
1700 | cdk_drag_status (context, action, time); |
1701 | |
1702 | return TRUE(!(0)); |
1703 | } |
1704 | |
1705 | static gboolean |
1706 | drag_drop_callback (CtkWidget *widget, |
1707 | CdkDragContext *context, |
1708 | int x, |
1709 | int y, |
1710 | guint32 time, |
1711 | gpointer data) |
1712 | { |
1713 | BaulIconDndInfo *dnd_info; |
1714 | |
1715 | dnd_info = BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) ))))->details->dnd_info; |
1716 | |
1717 | /* tell the drag_data_received callback that |
1718 | the drop occured and that it can actually |
1719 | process the actions. |
1720 | make sure it is going to be called at least once. |
1721 | */ |
1722 | dnd_info->drag_info.drop_occured = TRUE(!(0)); |
1723 | |
1724 | get_data_on_first_target_we_support (widget, context, time, x, y); |
1725 | |
1726 | return TRUE(!(0)); |
1727 | } |
1728 | |
1729 | void |
1730 | baul_icon_dnd_end_drag (BaulIconContainer *container) |
1731 | { |
1732 | BaulIconDndInfo *dnd_info; |
1733 | |
1734 | 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); |
1735 | |
1736 | dnd_info = container->details->dnd_info; |
1737 | 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); |
1738 | stop_auto_scroll (container); |
1739 | /* Do nothing. |
1740 | * Can that possibly be right? |
1741 | */ |
1742 | } |
1743 | |
1744 | /** this callback is called in 2 cases. |
1745 | It is called upon drag_motion events to get the actual data |
1746 | In that case, it just makes sure it gets the data. |
1747 | It is called upon drop_drop events to execute the actual |
1748 | actions on the received action. In that case, it actually first makes sure |
1749 | that we have got the data then processes it. |
1750 | */ |
1751 | |
1752 | static void |
1753 | drag_data_received_callback (CtkWidget *widget, |
1754 | CdkDragContext *context, |
1755 | int x, |
1756 | int y, |
1757 | CtkSelectionData *data, |
1758 | guint info, |
1759 | guint32 time, |
1760 | gpointer user_data) |
1761 | { |
1762 | BaulDragInfo *drag_info; |
1763 | gboolean success; |
1764 | |
1765 | 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); |
1766 | |
1767 | drag_info->got_drop_data_type = TRUE(!(0)); |
1768 | drag_info->data_type = info; |
1769 | |
1770 | switch (info) |
1771 | { |
1772 | case BAUL_ICON_DND_CAFE_ICON_LIST: |
1773 | baul_icon_container_dropped_icon_feedback (widget, data, x, y); |
1774 | break; |
1775 | case BAUL_ICON_DND_COLOR: |
1776 | case BAUL_ICON_DND_BGIMAGE: |
1777 | case BAUL_ICON_DND_KEYWORD: |
1778 | case BAUL_ICON_DND_URI_LIST: |
1779 | case BAUL_ICON_DND_TEXT: |
1780 | case BAUL_ICON_DND_RESET_BACKGROUND: |
1781 | case BAUL_ICON_DND_XDNDDIRECTSAVE: |
1782 | case BAUL_ICON_DND_RAW: |
1783 | /* Save the data so we can do the actual work on drop. */ |
1784 | if (drag_info->selection_data != NULL((void*)0)) |
1785 | { |
1786 | ctk_selection_data_free (drag_info->selection_data); |
1787 | } |
1788 | drag_info->selection_data = ctk_selection_data_copy (data); |
1789 | break; |
1790 | |
1791 | /* Netscape keeps sending us the data, even though we accept the first drag */ |
1792 | case BAUL_ICON_DND_NETSCAPE_URL: |
1793 | if (drag_info->selection_data != NULL((void*)0)) |
1794 | { |
1795 | ctk_selection_data_free (drag_info->selection_data); |
1796 | drag_info->selection_data = ctk_selection_data_copy (data); |
1797 | } |
1798 | break; |
1799 | case BAUL_ICON_DND_ROOTWINDOW_DROP: |
1800 | /* Do nothing, this won't even happen, since we don't want to call get_data twice */ |
1801 | break; |
1802 | } |
1803 | |
1804 | /* this is the second use case of this callback. |
1805 | * we have to do the actual work for the drop. |
1806 | */ |
1807 | if (drag_info->drop_occured) |
1808 | { |
1809 | EelBackground *background; |
1810 | char *tmp; |
1811 | const char *tmp_raw; |
1812 | int length; |
1813 | |
1814 | success = FALSE(0); |
1815 | switch (info) |
1816 | { |
1817 | case BAUL_ICON_DND_CAFE_ICON_LIST: |
1818 | baul_icon_container_receive_dropped_icons |
1819 | (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) )))), |
1820 | context, x, y); |
1821 | break; |
1822 | case BAUL_ICON_DND_COLOR: |
1823 | receive_dropped_color (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) )))), |
1824 | x, y, |
1825 | cdk_drag_context_get_selected_action (context), |
1826 | data); |
1827 | success = TRUE(!(0)); |
1828 | break; |
1829 | case BAUL_ICON_DND_BGIMAGE: |
1830 | receive_dropped_tile_image |
1831 | (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) )))), |
1832 | cdk_drag_context_get_selected_action (context), |
1833 | data); |
1834 | break; |
1835 | case BAUL_ICON_DND_KEYWORD: |
1836 | receive_dropped_keyword |
1837 | (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) )))), |
1838 | (char *) ctk_selection_data_get_data (data), x, y); |
1839 | break; |
1840 | case BAUL_ICON_DND_NETSCAPE_URL: |
1841 | receive_dropped_netscape_url |
1842 | (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) )))), |
1843 | (char *) ctk_selection_data_get_data (data), context, x, y); |
1844 | success = TRUE(!(0)); |
1845 | break; |
1846 | case BAUL_ICON_DND_URI_LIST: |
1847 | receive_dropped_uri_list |
1848 | (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) )))), |
1849 | (char *) ctk_selection_data_get_data (data), context, x, y); |
1850 | success = TRUE(!(0)); |
1851 | break; |
1852 | case BAUL_ICON_DND_TEXT: |
1853 | tmp = ctk_selection_data_get_text (data); |
1854 | receive_dropped_text |
1855 | (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) )))), |
1856 | (char *) tmp, context, x, y); |
1857 | success = TRUE(!(0)); |
1858 | g_free (tmp); |
1859 | break; |
1860 | case BAUL_ICON_DND_RAW: |
1861 | length = ctk_selection_data_get_length (data); |
1862 | tmp_raw = ctk_selection_data_get_data (data); |
1863 | receive_dropped_raw |
1864 | (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) )))), |
1865 | tmp_raw, length, drag_info->direct_save_uri, |
1866 | context, x, y); |
1867 | success = TRUE(!(0)); |
1868 | break; |
1869 | case BAUL_ICON_DND_RESET_BACKGROUND: |
1870 | background = eel_get_widget_background (widget); |
1871 | if (background != NULL((void*)0)) |
1872 | { |
1873 | eel_background_reset (background); |
1874 | } |
1875 | ctk_drag_finish (context, FALSE(0), FALSE(0), time); |
1876 | break; |
1877 | case BAUL_ICON_DND_ROOTWINDOW_DROP: |
1878 | /* Do nothing, everything is done by the sender */ |
1879 | break; |
1880 | case BAUL_ICON_DND_XDNDDIRECTSAVE: |
1881 | { |
1882 | const guchar *selection_data; |
1883 | gint selection_length; |
1884 | gint selection_format; |
1885 | |
1886 | selection_data = ctk_selection_data_get_data (drag_info->selection_data); |
1887 | selection_length = ctk_selection_data_get_length (drag_info->selection_data); |
1888 | selection_format = ctk_selection_data_get_format (drag_info->selection_data); |
1889 | |
1890 | if (selection_format == 8 && |
1891 | selection_length == 1 && |
1892 | selection_data[0] == 'F') |
1893 | { |
1894 | ctk_drag_get_data (widget, context, |
1895 | cdk_atom_intern (BAUL_ICON_DND_RAW_TYPE"application/octet-stream", |
1896 | FALSE(0)), |
1897 | time); |
1898 | return; |
1899 | } |
1900 | else if (selection_format == 8 && |
1901 | selection_length == 1 && |
1902 | selection_data[0] == 'F' && |
1903 | drag_info->direct_save_uri != NULL((void*)0)) |
This statement is never executed | |
1904 | { |
1905 | CdkPoint p; |
1906 | GFile *location; |
1907 | |
1908 | location = g_file_new_for_uri (drag_info->direct_save_uri); |
1909 | |
1910 | baul_file_changes_queue_file_added (location); |
1911 | p.x = x; |
1912 | p.y = y; |
1913 | baul_file_changes_queue_schedule_position_set ( |
1914 | location, |
1915 | p, |
1916 | cdk_x11_screen_get_screen_number ( |
1917 | ctk_widget_get_screen (widget))); |
1918 | g_object_unref (location); |
1919 | baul_file_changes_consume_changes (TRUE(!(0))); |
1920 | success = TRUE(!(0)); |
1921 | } |
1922 | break; |
1923 | } /* BAUL_ICON_DND_XDNDDIRECTSAVE */ |
1924 | } |
1925 | ctk_drag_finish (context, success, FALSE(0), time); |
1926 | |
1927 | baul_icon_container_free_drag_data (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) ))))); |
1928 | |
1929 | set_drop_target (BAUL_ICON_CONTAINER (widget)((((BaulIconContainer*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), (baul_icon_container_get_type()) )))), NULL((void*)0)); |
1930 | |
1931 | /* reinitialise it for the next dnd */ |
1932 | drag_info->drop_occured = FALSE(0); |
1933 | } |
1934 | |
1935 | } |
1936 | |
1937 | void |
1938 | baul_icon_dnd_init (BaulIconContainer *container) |
1939 | { |
1940 | CtkTargetList *targets; |
1941 | int n_elements; |
1942 | |
1943 | 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); |
1944 | 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); |
1945 | |
1946 | |
1947 | container->details->dnd_info = g_new0 (BaulIconDndInfo, 1)((BaulIconDndInfo *) g_malloc0_n ((1), sizeof (BaulIconDndInfo ))); |
1948 | baul_drag_init (&container->details->dnd_info->drag_info, |
1949 | drag_types, G_N_ELEMENTS (drag_types)(sizeof (drag_types) / sizeof ((drag_types)[0])), TRUE(!(0))); |
1950 | |
1951 | /* Set up the widget as a drag destination. |
1952 | * (But not a source, as drags starting from this widget will be |
1953 | * implemented by dealing with events manually.) |
1954 | */ |
1955 | n_elements = G_N_ELEMENTS (drop_types)(sizeof (drop_types) / sizeof ((drop_types)[0])); |
1956 | if (!baul_icon_container_get_is_desktop (container)) |
1957 | { |
1958 | /* Don't set up rootwindow drop */ |
1959 | n_elements -= 1; |
1960 | } |
1961 | ctk_drag_dest_set (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((container)), ((ctk_widget_get_type ())))))), |
1962 | 0, |
1963 | drop_types, n_elements, |
1964 | CDK_ACTION_COPY | CDK_ACTION_MOVE | CDK_ACTION_LINK | CDK_ACTION_ASK); |
1965 | |
1966 | targets = ctk_drag_dest_get_target_list (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((container)), ((ctk_widget_get_type ()))))))); |
1967 | ctk_target_list_add_text_targets (targets, BAUL_ICON_DND_TEXT); |
1968 | |
1969 | |
1970 | /* Messages for outgoing drag. */ |
1971 | g_signal_connect (container, "drag_begin",g_signal_connect_data ((container), ("drag_begin"), (((GCallback ) (drag_begin_callback))), (((void*)0)), ((void*)0), (GConnectFlags ) 0) |
1972 | G_CALLBACK (drag_begin_callback), NULL)g_signal_connect_data ((container), ("drag_begin"), (((GCallback ) (drag_begin_callback))), (((void*)0)), ((void*)0), (GConnectFlags ) 0); |
1973 | 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) |
1974 | 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); |
1975 | g_signal_connect (container, "drag_end",g_signal_connect_data ((container), ("drag_end"), (((GCallback ) (drag_end_callback))), (((void*)0)), ((void*)0), (GConnectFlags ) 0) |
1976 | G_CALLBACK (drag_end_callback), NULL)g_signal_connect_data ((container), ("drag_end"), (((GCallback ) (drag_end_callback))), (((void*)0)), ((void*)0), (GConnectFlags ) 0); |
1977 | |
1978 | /* Messages for incoming drag. */ |
1979 | 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) |
1980 | 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); |
1981 | g_signal_connect (container, "drag_motion",g_signal_connect_data ((container), ("drag_motion"), (((GCallback ) (drag_motion_callback))), (((void*)0)), ((void*)0), (GConnectFlags ) 0) |
1982 | G_CALLBACK (drag_motion_callback), NULL)g_signal_connect_data ((container), ("drag_motion"), (((GCallback ) (drag_motion_callback))), (((void*)0)), ((void*)0), (GConnectFlags ) 0); |
1983 | g_signal_connect (container, "drag_drop",g_signal_connect_data ((container), ("drag_drop"), (((GCallback ) (drag_drop_callback))), (((void*)0)), ((void*)0), (GConnectFlags ) 0) |
1984 | G_CALLBACK (drag_drop_callback), NULL)g_signal_connect_data ((container), ("drag_drop"), (((GCallback ) (drag_drop_callback))), (((void*)0)), ((void*)0), (GConnectFlags ) 0); |
1985 | g_signal_connect (container, "drag_leave",g_signal_connect_data ((container), ("drag_leave"), (((GCallback ) (drag_leave_callback))), (((void*)0)), ((void*)0), (GConnectFlags ) 0) |
1986 | G_CALLBACK (drag_leave_callback), NULL)g_signal_connect_data ((container), ("drag_leave"), (((GCallback ) (drag_leave_callback))), (((void*)0)), ((void*)0), (GConnectFlags ) 0); |
1987 | } |
1988 | |
1989 | void |
1990 | baul_icon_dnd_fini (BaulIconContainer *container) |
1991 | { |
1992 | 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); |
1993 | |
1994 | if (container->details->dnd_info != NULL((void*)0)) |
1995 | { |
1996 | stop_auto_scroll (container); |
1997 | |
1998 | baul_drag_finalize (&container->details->dnd_info->drag_info); |
1999 | container->details->dnd_info = NULL((void*)0); |
2000 | } |
2001 | } |