No issues found
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3 /* nautilus-desktop-canvas-view.c - implementation of canvas view for managing the desktop.
4
5 Copyright (C) 2000, 2001 Eazel, Inc.mou
6
7 The Gnome Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The Gnome Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the Gnome Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
21
22 Authors: Mike Engber <engber@eazel.com>
23 Gene Z. Ragan <gzr@eazel.com>
24 Miguel de Icaza <miguel@ximian.com>
25 */
26
27 #include <config.h>
28
29 #include "nautilus-desktop-canvas-view.h"
30
31 #include "nautilus-actions.h"
32 #include "nautilus-canvas-view-container.h"
33 #include "nautilus-view-factory.h"
34 #include "nautilus-view.h"
35
36 #include <X11/Xatom.h>
37 #include <gtk/gtk.h>
38 #include <eel/eel-glib-extensions.h>
39 #include <eel/eel-gtk-extensions.h>
40 #include <eel/eel-vfs-extensions.h>
41 #include <fcntl.h>
42 #include <gdk/gdkx.h>
43 #include <glib/gi18n.h>
44 #include <libnautilus-private/nautilus-desktop-background.h>
45 #include <libnautilus-private/nautilus-desktop-icon-file.h>
46 #include <libnautilus-private/nautilus-directory-notify.h>
47 #include <libnautilus-private/nautilus-file-changes-queue.h>
48 #include <libnautilus-private/nautilus-file-operations.h>
49 #include <libnautilus-private/nautilus-file-utilities.h>
50 #include <libnautilus-private/nautilus-ui-utilities.h>
51 #include <libnautilus-private/nautilus-global-preferences.h>
52 #include <libnautilus-private/nautilus-link.h>
53 #include <libnautilus-private/nautilus-metadata.h>
54 #include <libnautilus-private/nautilus-monitor.h>
55 #include <libnautilus-private/nautilus-program-choosing.h>
56 #include <libnautilus-private/nautilus-trash-monitor.h>
57 #include <limits.h>
58 #include <stddef.h>
59 #include <stdio.h>
60 #include <string.h>
61 #include <sys/stat.h>
62 #include <sys/types.h>
63 #include <unistd.h>
64
65 /* Timeout to check the desktop directory for updates */
66 #define RESCAN_TIMEOUT 4
67
68 struct NautilusDesktopCanvasViewDetails
69 {
70 GdkWindow *root_window;
71 GtkActionGroup *desktop_action_group;
72 guint desktop_merge_id;
73
74 /* For the desktop rescanning
75 */
76 gulong delayed_init_signal;
77 guint reload_desktop_timeout;
78 gboolean pending_rescan;
79
80 NautilusDesktopBackground *background;
81 };
82
83 static void default_zoom_level_changed (gpointer user_data);
84 static void real_merge_menus (NautilusView *view);
85 static void real_update_menus (NautilusView *view);
86 static void nautilus_desktop_canvas_view_update_canvas_container_fonts (NautilusDesktopCanvasView *view);
87 static void font_changed_callback (gpointer callback_data);
88
89 G_DEFINE_TYPE (NautilusDesktopCanvasView, nautilus_desktop_canvas_view, NAUTILUS_TYPE_CANVAS_VIEW)
90
91 static char *desktop_directory;
92 static time_t desktop_dir_modify_time;
93
94 #define get_canvas_container(w) nautilus_canvas_view_get_canvas_container(NAUTILUS_CANVAS_VIEW (w))
95
96 #define POPUP_PATH_CANVAS_APPEARANCE "/selection/Canvas Appearance Items"
97
98 static void
99 canvas_container_set_workarea (NautilusCanvasContainer *canvas_container,
100 GdkScreen *screen,
101 long *workareas,
102 int n_items)
103 {
104 int left, right, top, bottom;
105 int i;
106 GdkRectangle geometry;
107
108 left = right = top = bottom = 0;
109 gdk_screen_get_monitor_geometry (screen, gdk_screen_get_primary_monitor (screen), &geometry);
110
111 for (i = 0; i < n_items; i += 4) {
112 GdkRectangle workarea;
113
114 workarea.x = workareas[i];
115 workarea.y = workareas[i + 1];
116 workarea.width = workareas[i + 2];
117 workarea.height = workareas[i + 3];
118
119 if (!gdk_rectangle_intersect (&geometry, &workarea, &workarea))
120 continue;
121
122 left = MAX (left, workarea.x);
123 right = MAX (right, (geometry.x + geometry.width) - (workarea.x + workarea.width));
124 top = MAX (top, workarea.y);
125 bottom = MAX (bottom, (geometry.y + geometry.height) - (workarea.y + workarea.height));
126 }
127
128 nautilus_canvas_container_set_margins (canvas_container,
129 left, right, top, bottom);
130 }
131
132 static void
133 net_workarea_changed (NautilusDesktopCanvasView *canvas_view,
134 GdkWindow *window)
135 {
136 long *nworkareas = NULL;
137 long *workareas = NULL;
138 GdkAtom type_returned;
139 int format_returned;
140 int length_returned;
141 NautilusCanvasContainer *canvas_container;
142 GdkScreen *screen;
143
144 g_return_if_fail (NAUTILUS_IS_DESKTOP_CANVAS_VIEW (canvas_view));
145
146 canvas_container = get_canvas_container (canvas_view);
147
148 /* Find the number of desktops so we know how long the
149 * workareas array is going to be (each desktop will have four
150 * elements in the workareas array describing
151 * x,y,width,height) */
152 gdk_error_trap_push ();
153 if (!gdk_property_get (window,
154 gdk_atom_intern ("_NET_NUMBER_OF_DESKTOPS", FALSE),
155 gdk_x11_xatom_to_atom (XA_CARDINAL),
156 0, 4, FALSE,
157 &type_returned,
158 &format_returned,
159 &length_returned,
160 (guchar **) &nworkareas)) {
161 g_warning("Can not calculate _NET_NUMBER_OF_DESKTOPS");
162 }
163 if (gdk_error_trap_pop()
164 || nworkareas == NULL
165 || type_returned != gdk_x11_xatom_to_atom (XA_CARDINAL)
166 || format_returned != 32)
167 g_warning("Can not calculate _NET_NUMBER_OF_DESKTOPS");
168
169 /* Note : gdk_property_get() is broken (API documents admit
170 * this). As a length argument, it expects the number of
171 * _bytes_ of data you require. Internally, gdk_property_get
172 * converts that value to a count of 32 bit (4 byte) elements.
173 * However, the length returned is in bytes, but is calculated
174 * via the count of returned elements * sizeof(long). This
175 * means on a 64 bit system, the number of bytes you have to
176 * request does not correspond to the number of bytes you get
177 * back, and is the reason for the workaround below.
178 */
179 gdk_error_trap_push ();
180 if (nworkareas == NULL || (*nworkareas < 1)
181 || !gdk_property_get (window,
182 gdk_atom_intern ("_NET_WORKAREA", FALSE),
183 gdk_x11_xatom_to_atom (XA_CARDINAL),
184 0, ((*nworkareas) * 4 * 4), FALSE,
185 &type_returned,
186 &format_returned,
187 &length_returned,
188 (guchar **) &workareas)) {
189 g_warning("Can not get _NET_WORKAREA");
190 workareas = NULL;
191 }
192
193 if (gdk_error_trap_pop ()
194 || workareas == NULL
195 || type_returned != gdk_x11_xatom_to_atom (XA_CARDINAL)
196 || ((*nworkareas) * 4 * sizeof(long)) != length_returned
197 || format_returned != 32) {
198 g_warning("Can not determine workarea, guessing at layout");
199 nautilus_canvas_container_set_margins (canvas_container,
200 0, 0, 0, 0);
201 } else {
202 screen = gdk_window_get_screen (window);
203
204 canvas_container_set_workarea
205 (canvas_container, screen, workareas, length_returned / sizeof (long));
206 }
207
208 if (nworkareas != NULL)
209 g_free (nworkareas);
210
211 if (workareas != NULL)
212 g_free (workareas);
213 }
214
215 static GdkFilterReturn
216 desktop_canvas_view_property_filter (GdkXEvent *gdk_xevent,
217 GdkEvent *event,
218 gpointer data)
219 {
220 XEvent *xevent = gdk_xevent;
221 NautilusDesktopCanvasView *canvas_view;
222
223 canvas_view = NAUTILUS_DESKTOP_CANVAS_VIEW (data);
224
225 switch (xevent->type) {
226 case PropertyNotify:
227 if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name ("_NET_WORKAREA"))
228 net_workarea_changed (canvas_view, event->any.window);
229 break;
230 default:
231 break;
232 }
233
234 return GDK_FILTER_CONTINUE;
235 }
236
237 static void
238 real_begin_loading (NautilusView *object)
239 {
240 NautilusCanvasContainer *canvas_container;
241 NautilusDesktopCanvasView *view;
242
243 view = NAUTILUS_DESKTOP_CANVAS_VIEW (object);
244
245 canvas_container = get_canvas_container (view);
246 if (view->details->background == NULL) {
247 view->details->background = nautilus_desktop_background_new (canvas_container);
248 }
249
250 NAUTILUS_VIEW_CLASS (nautilus_desktop_canvas_view_parent_class)->begin_loading (object);
251 }
252
253 static const char *
254 real_get_id (NautilusView *view)
255 {
256 return NAUTILUS_DESKTOP_CANVAS_VIEW_ID;
257 }
258
259 static void
260 nautilus_desktop_canvas_view_dispose (GObject *object)
261 {
262 NautilusDesktopCanvasView *canvas_view;
263 GtkUIManager *ui_manager;
264
265 canvas_view = NAUTILUS_DESKTOP_CANVAS_VIEW (object);
266
267 /* Remove desktop rescan timeout. */
268 if (canvas_view->details->reload_desktop_timeout != 0) {
269 g_source_remove (canvas_view->details->reload_desktop_timeout);
270 canvas_view->details->reload_desktop_timeout = 0;
271 }
272
273 ui_manager = nautilus_view_get_ui_manager (NAUTILUS_VIEW (canvas_view));
274 if (ui_manager != NULL) {
275 nautilus_ui_unmerge_ui (ui_manager,
276 &canvas_view->details->desktop_merge_id,
277 &canvas_view->details->desktop_action_group);
278 }
279
280 g_signal_handlers_disconnect_by_func (nautilus_icon_view_preferences,
281 default_zoom_level_changed,
282 canvas_view);
283 g_signal_handlers_disconnect_by_func (nautilus_preferences,
284 font_changed_callback,
285 canvas_view);
286 g_signal_handlers_disconnect_by_func (gnome_lockdown_preferences,
287 nautilus_view_update_menus,
288 canvas_view);
289
290 if (canvas_view->details->background != NULL) {
291 g_object_unref (canvas_view->details->background);
292 canvas_view->details->background = NULL;
293 }
294
295 G_OBJECT_CLASS (nautilus_desktop_canvas_view_parent_class)->dispose (object);
296 }
297
298 static void
299 nautilus_desktop_canvas_view_class_init (NautilusDesktopCanvasViewClass *class)
300 {
301 NautilusViewClass *vclass;
302
303 vclass = NAUTILUS_VIEW_CLASS (class);
304
305 G_OBJECT_CLASS (class)->dispose = nautilus_desktop_canvas_view_dispose;
306
307 vclass->begin_loading = real_begin_loading;
308 vclass->merge_menus = real_merge_menus;
309 vclass->update_menus = real_update_menus;
310 vclass->get_view_id = real_get_id;
311
312 g_type_class_add_private (class, sizeof (NautilusDesktopCanvasViewDetails));
313 }
314
315 static void
316 nautilus_desktop_canvas_view_handle_middle_click (NautilusCanvasContainer *canvas_container,
317 GdkEventButton *event,
318 NautilusDesktopCanvasView *desktop_canvas_view)
319 {
320 XButtonEvent x_event;
321 GdkDevice *keyboard = NULL, *pointer = NULL, *cur;
322 GdkDeviceManager *manager;
323 GList *list, *l;
324
325 manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (canvas_container)));
326 list = gdk_device_manager_list_devices (manager, GDK_DEVICE_TYPE_MASTER);
327
328 for (l = list; l != NULL; l = l->next) {
329 cur = l->data;
330
331 if (pointer == NULL && (gdk_device_get_source (cur) == GDK_SOURCE_MOUSE)) {
332 pointer = cur;
333 }
334
335 if (keyboard == NULL && (gdk_device_get_source (cur) == GDK_SOURCE_KEYBOARD)) {
336 keyboard = cur;
337 }
338
339 if (pointer != NULL && keyboard != NULL) {
340 break;
341 }
342 }
343
344 g_list_free (list);
345
346 /* During a mouse click we have the pointer and keyboard grab.
347 * We will send a fake event to the root window which will cause it
348 * to try to get the grab so we need to let go ourselves.
349 */
350
351 if (pointer != NULL) {
352 gdk_device_ungrab (pointer, GDK_CURRENT_TIME);
353 }
354
355
356 if (keyboard != NULL) {
357 gdk_device_ungrab (keyboard, GDK_CURRENT_TIME);
358 }
359
360 /* Stop the event because we don't want anyone else dealing with it. */
361 gdk_flush ();
362 g_signal_stop_emission_by_name (canvas_container, "middle_click");
363
364 /* build an X event to represent the middle click. */
365 x_event.type = ButtonPress;
366 x_event.send_event = True;
367 x_event.display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
368 x_event.window = GDK_ROOT_WINDOW ();
369 x_event.root = GDK_ROOT_WINDOW ();
370 x_event.subwindow = 0;
371 x_event.time = event->time;
372 x_event.x = event->x;
373 x_event.y = event->y;
374 x_event.x_root = event->x_root;
375 x_event.y_root = event->y_root;
376 x_event.state = event->state;
377 x_event.button = event->button;
378 x_event.same_screen = True;
379
380 /* Send it to the root window, the window manager will handle it. */
381 XSendEvent (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), GDK_ROOT_WINDOW (), True,
382 ButtonPressMask, (XEvent *) &x_event);
383 }
384
385 static void
386 unrealized_callback (GtkWidget *widget, NautilusDesktopCanvasView *desktop_canvas_view)
387 {
388 g_return_if_fail (desktop_canvas_view->details->root_window != NULL);
389
390 /* Remove the property filter */
391 gdk_window_remove_filter (desktop_canvas_view->details->root_window,
392 desktop_canvas_view_property_filter,
393 desktop_canvas_view);
394 desktop_canvas_view->details->root_window = NULL;
395 }
396
397 static void
398 realized_callback (GtkWidget *widget, NautilusDesktopCanvasView *desktop_canvas_view)
399 {
400 GdkWindow *root_window;
401 GdkScreen *screen;
402 GtkAllocation allocation;
403
404 g_return_if_fail (desktop_canvas_view->details->root_window == NULL);
405
406 screen = gtk_widget_get_screen (widget);
407
408 /* Ugly HACK for the problem that the views realize at the
409 * wrong size and then get resized. (This is a problem with
410 * BonoboPlug.) This was leading to problems where initial
411 * layout was done at 60x60 stacking all desktop icons in
412 * the top left corner.
413 */
414 allocation.x = 0;
415 allocation.y = 0;
416 allocation.width = gdk_screen_get_width (screen);
417 allocation.height = gdk_screen_get_height (screen);
418 gtk_widget_size_allocate (GTK_WIDGET(get_canvas_container(desktop_canvas_view)),
419 &allocation);
420
421 root_window = gdk_screen_get_root_window (screen);
422
423 desktop_canvas_view->details->root_window = root_window;
424
425 /* Read out the workarea geometry and update the icon container accordingly */
426 net_workarea_changed (desktop_canvas_view, root_window);
427
428 /* Setup the property filter */
429 gdk_window_set_events (root_window, GDK_PROPERTY_CHANGE_MASK);
430 gdk_window_add_filter (root_window,
431 desktop_canvas_view_property_filter,
432 desktop_canvas_view);
433 }
434
435 static NautilusZoomLevel
436 get_default_zoom_level (void)
437 {
438 NautilusZoomLevel default_zoom_level;
439
440 default_zoom_level = g_settings_get_enum (nautilus_icon_view_preferences,
441 NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL);
442
443 return CLAMP (default_zoom_level, NAUTILUS_ZOOM_LEVEL_SMALLEST, NAUTILUS_ZOOM_LEVEL_LARGEST);
444 }
445
446 static void
447 default_zoom_level_changed (gpointer user_data)
448 {
449 NautilusZoomLevel new_level;
450 NautilusDesktopCanvasView *desktop_canvas_view;
451
452 desktop_canvas_view = NAUTILUS_DESKTOP_CANVAS_VIEW (user_data);
453 new_level = get_default_zoom_level ();
454
455 nautilus_canvas_container_set_zoom_level (get_canvas_container (desktop_canvas_view),
456 new_level);
457 }
458
459 static gboolean
460 do_desktop_rescan (gpointer data)
461 {
462 NautilusDesktopCanvasView *desktop_canvas_view;
463 struct stat buf;
464
465 desktop_canvas_view = NAUTILUS_DESKTOP_CANVAS_VIEW (data);
466 if (desktop_canvas_view->details->pending_rescan) {
467 return TRUE;
468 }
469
470 if (stat (desktop_directory, &buf) == -1) {
471 return TRUE;
472 }
473
474 if (buf.st_ctime == desktop_dir_modify_time) {
475 return TRUE;
476 }
477
478 desktop_canvas_view->details->pending_rescan = TRUE;
479
480 nautilus_directory_force_reload
481 (nautilus_view_get_model (NAUTILUS_VIEW (desktop_canvas_view)));
482
483 return TRUE;
484 }
485
486 static void
487 done_loading (NautilusDirectory *model,
488 NautilusDesktopCanvasView *desktop_canvas_view)
489 {
490 struct stat buf;
491
492 desktop_canvas_view->details->pending_rescan = FALSE;
493 if (stat (desktop_directory, &buf) == -1) {
494 return;
495 }
496
497 desktop_dir_modify_time = buf.st_ctime;
498 }
499
500 /* This function is used because the NautilusDirectory model does not
501 * exist always in the desktop_canvas_view, so we wait until it has been
502 * instantiated.
503 */
504 static void
505 delayed_init (NautilusDesktopCanvasView *desktop_canvas_view)
506 {
507 /* Keep track of the load time. */
508 g_signal_connect_object (nautilus_view_get_model (NAUTILUS_VIEW (desktop_canvas_view)),
509 "done_loading",
510 G_CALLBACK (done_loading), desktop_canvas_view, 0);
511
512 /* Monitor desktop directory. */
513 desktop_canvas_view->details->reload_desktop_timeout =
514 g_timeout_add_seconds (RESCAN_TIMEOUT, do_desktop_rescan, desktop_canvas_view);
515
516 g_signal_handler_disconnect (desktop_canvas_view,
517 desktop_canvas_view->details->delayed_init_signal);
518
519 desktop_canvas_view->details->delayed_init_signal = 0;
520 }
521
522 static void
523 font_changed_callback (gpointer callback_data)
524 {
525 g_return_if_fail (NAUTILUS_IS_DESKTOP_CANVAS_VIEW (callback_data));
526
527 nautilus_desktop_canvas_view_update_canvas_container_fonts (NAUTILUS_DESKTOP_CANVAS_VIEW (callback_data));
528 }
529
530 static void
531 nautilus_desktop_canvas_view_update_canvas_container_fonts (NautilusDesktopCanvasView *canvas_view)
532 {
533 NautilusCanvasContainer *canvas_container;
534 char *font;
535
536 canvas_container = get_canvas_container (canvas_view);
537 g_assert (canvas_container != NULL);
538
539 font = g_settings_get_string (nautilus_desktop_preferences,
540 NAUTILUS_PREFERENCES_DESKTOP_FONT);
541
542 nautilus_canvas_container_set_font (canvas_container, font);
543
544 g_free (font);
545 }
546
547 static void
548 nautilus_desktop_canvas_view_init (NautilusDesktopCanvasView *desktop_canvas_view)
549 {
550 NautilusCanvasContainer *canvas_container;
551 GtkAllocation allocation;
552 GtkAdjustment *hadj, *vadj;
553
554 desktop_canvas_view->details = G_TYPE_INSTANCE_GET_PRIVATE (desktop_canvas_view,
555 NAUTILUS_TYPE_DESKTOP_CANVAS_VIEW,
556 NautilusDesktopCanvasViewDetails);
557
558 if (desktop_directory == NULL) {
559 desktop_directory = nautilus_get_desktop_directory ();
560 }
561
562 nautilus_canvas_view_filter_by_screen (NAUTILUS_CANVAS_VIEW (desktop_canvas_view), TRUE);
563 canvas_container = get_canvas_container (desktop_canvas_view);
564 nautilus_canvas_container_set_use_drop_shadows (canvas_container, TRUE);
565 nautilus_canvas_view_container_set_sort_desktop (NAUTILUS_CANVAS_VIEW_CONTAINER (canvas_container), TRUE);
566
567 /* Do a reload on the desktop if we don't have FAM, a smarter
568 * way to keep track of the items on the desktop.
569 */
570 if (!nautilus_monitor_active ()) {
571 desktop_canvas_view->details->delayed_init_signal = g_signal_connect_object
572 (desktop_canvas_view, "begin_loading",
573 G_CALLBACK (delayed_init), desktop_canvas_view, 0);
574 }
575
576 nautilus_canvas_container_set_is_fixed_size (canvas_container, TRUE);
577 nautilus_canvas_container_set_is_desktop (canvas_container, TRUE);
578 nautilus_canvas_container_set_store_layout_timestamps (canvas_container, TRUE);
579
580 /* Set allocation to be at 0, 0 */
581 gtk_widget_get_allocation (GTK_WIDGET (canvas_container), &allocation);
582 allocation.x = 0;
583 allocation.y = 0;
584 gtk_widget_set_allocation (GTK_WIDGET (canvas_container), &allocation);
585
586 gtk_widget_queue_resize (GTK_WIDGET (canvas_container));
587
588 hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas_container));
589 vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas_container));
590
591 gtk_adjustment_set_value (hadj, 0);
592 gtk_adjustment_set_value (vadj, 0);
593
594 nautilus_view_ignore_hidden_file_preferences
595 (NAUTILUS_VIEW (desktop_canvas_view));
596
597 nautilus_view_set_show_foreign (NAUTILUS_VIEW (desktop_canvas_view),
598 FALSE);
599
600 /* Set our default layout mode */
601 nautilus_canvas_container_set_layout_mode (canvas_container,
602 gtk_widget_get_direction (GTK_WIDGET(canvas_container)) == GTK_TEXT_DIR_RTL ?
603 NAUTILUS_CANVAS_LAYOUT_T_B_R_L :
604 NAUTILUS_CANVAS_LAYOUT_T_B_L_R);
605
606 g_signal_connect_object (canvas_container, "middle_click",
607 G_CALLBACK (nautilus_desktop_canvas_view_handle_middle_click), desktop_canvas_view, 0);
608 g_signal_connect_object (desktop_canvas_view, "realize",
609 G_CALLBACK (realized_callback), desktop_canvas_view, 0);
610 g_signal_connect_object (desktop_canvas_view, "unrealize",
611 G_CALLBACK (unrealized_callback), desktop_canvas_view, 0);
612
613 g_signal_connect_swapped (nautilus_icon_view_preferences,
614 "changed::" NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL,
615 G_CALLBACK (default_zoom_level_changed),
616 desktop_canvas_view);
617
618 g_signal_connect_swapped (nautilus_desktop_preferences,
619 "changed::" NAUTILUS_PREFERENCES_DESKTOP_FONT,
620 G_CALLBACK (font_changed_callback),
621 desktop_canvas_view);
622
623 default_zoom_level_changed (desktop_canvas_view);
624 nautilus_desktop_canvas_view_update_canvas_container_fonts (desktop_canvas_view);
625
626 g_signal_connect_swapped (gnome_lockdown_preferences,
627 "changed::" NAUTILUS_PREFERENCES_LOCKDOWN_COMMAND_LINE,
628 G_CALLBACK (nautilus_view_update_menus),
629 desktop_canvas_view);
630 }
631
632 static void
633 action_change_background_callback (GtkAction *action,
634 gpointer data)
635 {
636 g_assert (NAUTILUS_VIEW (data));
637
638 nautilus_launch_application_from_command (gtk_widget_get_screen (GTK_WIDGET (data)),
639 "gnome-control-center",
640 FALSE,
641 "background", NULL);
642 }
643
644 static void
645 action_empty_trash_conditional_callback (GtkAction *action,
646 gpointer data)
647 {
648 g_assert (NAUTILUS_IS_VIEW (data));
649
650 nautilus_file_operations_empty_trash (GTK_WIDGET (data));
651 }
652
653 static void
654 action_stretch_callback (GtkAction *action,
655 gpointer callback_data)
656 {
657 nautilus_canvas_container_show_stretch_handles
658 (get_canvas_container (callback_data));
659 }
660
661 static void
662 action_unstretch_callback (GtkAction *action,
663 gpointer callback_data)
664 {
665 nautilus_canvas_container_unstretch (get_canvas_container (callback_data));
666 }
667
668 static void
669 action_clean_up_callback (GtkAction *action,
670 gpointer callback_data)
671 {
672 nautilus_canvas_view_clean_up_by_name (NAUTILUS_CANVAS_VIEW (callback_data));
673 }
674
675 static gboolean
676 trash_link_is_selection (NautilusView *view)
677 {
678 GList *selection;
679 NautilusDesktopLink *link;
680 gboolean result;
681
682 result = FALSE;
683
684 selection = nautilus_view_get_selection (view);
685
686 if ((g_list_length (selection) == 1) &&
687 NAUTILUS_IS_DESKTOP_ICON_FILE (selection->data)) {
688 link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (selection->data));
689 /* link may be NULL if the link was recently removed (unmounted) */
690 if (link != NULL &&
691 nautilus_desktop_link_get_link_type (link) == NAUTILUS_DESKTOP_LINK_TRASH) {
692 result = TRUE;
693 }
694 if (link) {
695 g_object_unref (link);
696 }
697 }
698
699 nautilus_file_list_free (selection);
700
701 return result;
702 }
703
704 static void
705 real_update_menus (NautilusView *view)
706 {
707 NautilusDesktopCanvasView *desktop_view;
708 NautilusCanvasContainer *canvas_container;
709 gboolean include_empty_trash;
710 char *label;
711 GtkAction *action;
712 int selection_count;
713
714 g_assert (NAUTILUS_IS_DESKTOP_CANVAS_VIEW (view));
715
716 NAUTILUS_VIEW_CLASS (nautilus_desktop_canvas_view_parent_class)->update_menus (view);
717
718 desktop_view = NAUTILUS_DESKTOP_CANVAS_VIEW (view);
719
720 /* Empty Trash */
721 include_empty_trash = trash_link_is_selection (view);
722 action = gtk_action_group_get_action (desktop_view->details->desktop_action_group,
723 NAUTILUS_ACTION_EMPTY_TRASH_CONDITIONAL);
724 gtk_action_set_visible (action,
725 include_empty_trash);
726 if (include_empty_trash) {
727 label = g_strdup (_("E_mpty Trash"));
728 g_object_set (action , "label", label, NULL);
729 gtk_action_set_sensitive (action,
730 !nautilus_trash_monitor_is_empty ());
731 g_free (label);
732 }
733
734 /* Stretch */
735 selection_count = nautilus_view_get_selection_count (view);
736 canvas_container = get_canvas_container (desktop_view);
737
738 action = gtk_action_group_get_action (desktop_view->details->desktop_action_group,
739 NAUTILUS_ACTION_STRETCH);
740 gtk_action_set_sensitive (action,
741 selection_count == 1
742 && canvas_container != NULL
743 && !nautilus_canvas_container_has_stretch_handles (canvas_container));
744 gtk_action_set_visible (action, TRUE);
745
746 /* Unstretch */
747 action = gtk_action_group_get_action (desktop_view->details->desktop_action_group,
748 NAUTILUS_ACTION_UNSTRETCH);
749 g_object_set (action, "label",
750 (selection_count > 1)
751 ? _("Restore Icons' Original Si_zes")
752 : _("Restore Icon's Original Si_ze"),
753 NULL);
754 gtk_action_set_sensitive (action,
755 canvas_container != NULL
756 && nautilus_canvas_container_is_stretched (canvas_container));
757 gtk_action_set_visible (action, TRUE);
758 }
759
760 static const GtkActionEntry desktop_view_entries[] = {
761 /* name, stock id */
762 { "Change Background", NULL,
763 /* label, accelerator */
764 N_("Change Desktop _Background"), NULL,
765 /* tooltip */
766 N_("Show a window that lets you set your desktop background's pattern or color"),
767 G_CALLBACK (action_change_background_callback) },
768 /* name, stock id */
769 { "Empty Trash Conditional", NULL,
770 /* label, accelerator */
771 N_("Empty Trash"), NULL,
772 /* tooltip */
773 N_("Delete all items in the Trash"),
774 G_CALLBACK (action_empty_trash_conditional_callback) },
775 /* name, stock id */
776 { NAUTILUS_ACTION_CLEAN_UP, NULL,
777 /* label, accelerator */
778 N_("_Organize Desktop by Name"), NULL,
779 /* tooltip */
780 N_("Reposition icons to better fit in the window and avoid overlapping"),
781 G_CALLBACK (action_clean_up_callback) },
782 /* name, stock id */
783 { "Stretch", NULL,
784 /* label, accelerator */
785 N_("Resize Icon..."), NULL,
786 /* tooltip */
787 N_("Make the selected icons resizable"),
788 G_CALLBACK (action_stretch_callback) },
789 /* name, stock id */
790 { "Unstretch", NULL,
791 /* label, accelerator */
792 N_("Restore Icons' Original Si_zes"), NULL,
793 /* tooltip */
794 N_("Restore each selected icons to its original size"),
795 G_CALLBACK (action_unstretch_callback) },
796 };
797
798 static void
799 real_merge_menus (NautilusView *view)
800 {
801 NautilusDesktopCanvasView *desktop_view;
802 GtkUIManager *ui_manager;
803 GtkActionGroup *action_group;
804
805 NAUTILUS_VIEW_CLASS (nautilus_desktop_canvas_view_parent_class)->merge_menus (view);
806
807 desktop_view = NAUTILUS_DESKTOP_CANVAS_VIEW (view);
808
809 ui_manager = nautilus_view_get_ui_manager (view);
810
811 action_group = gtk_action_group_new ("DesktopViewActions");
812 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
813 desktop_view->details->desktop_action_group = action_group;
814 gtk_action_group_add_actions (action_group,
815 desktop_view_entries, G_N_ELEMENTS (desktop_view_entries),
816 view);
817
818 gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
819 g_object_unref (action_group); /* owned by ui manager */
820
821 desktop_view->details->desktop_merge_id =
822 gtk_ui_manager_add_ui_from_resource (ui_manager, "/org/gnome/nautilus/nautilus-desktop-canvas-view-ui.xml", NULL);
823
824 gtk_ui_manager_add_ui (ui_manager,
825 desktop_view->details->desktop_merge_id,
826 POPUP_PATH_CANVAS_APPEARANCE,
827 NAUTILUS_ACTION_STRETCH,
828 NAUTILUS_ACTION_STRETCH,
829 GTK_UI_MANAGER_MENUITEM,
830 FALSE);
831 gtk_ui_manager_add_ui (ui_manager,
832 desktop_view->details->desktop_merge_id,
833 POPUP_PATH_CANVAS_APPEARANCE,
834 NAUTILUS_ACTION_UNSTRETCH,
835 NAUTILUS_ACTION_UNSTRETCH,
836 GTK_UI_MANAGER_MENUITEM,
837 FALSE);
838 }
839
840 static NautilusView *
841 nautilus_desktop_canvas_view_create (NautilusWindowSlot *slot)
842 {
843 NautilusCanvasView *view;
844
845 view = g_object_new (NAUTILUS_TYPE_DESKTOP_CANVAS_VIEW,
846 "window-slot", slot,
847 "supports-zooming", FALSE,
848 "supports-auto-layout", FALSE,
849 "supports-manual-layout", TRUE,
850 "supports-scaling", TRUE,
851 "supports-keep-aligned", TRUE,
852 NULL);
853 return NAUTILUS_VIEW (view);
854 }
855
856 static gboolean
857 nautilus_desktop_canvas_view_supports_uri (const char *uri,
858 GFileType file_type,
859 const char *mime_type)
860 {
861 if (g_str_has_prefix (uri, EEL_DESKTOP_URI)) {
862 return TRUE;
863 }
864
865 return FALSE;
866 }
867
868 static NautilusViewInfo nautilus_desktop_canvas_view = {
869 NAUTILUS_DESKTOP_CANVAS_VIEW_ID,
870 "Desktop View",
871 "_Desktop",
872 N_("The desktop view encountered an error."),
873 N_("The desktop view encountered an error while starting up."),
874 "Display this location with the desktop view.",
875 nautilus_desktop_canvas_view_create,
876 nautilus_desktop_canvas_view_supports_uri
877 };
878
879 void
880 nautilus_desktop_canvas_view_register (void)
881 {
882 nautilus_desktop_canvas_view.error_label = _(nautilus_desktop_canvas_view.error_label);
883 nautilus_desktop_canvas_view.startup_error_label = _(nautilus_desktop_canvas_view.startup_error_label);
884
885 nautilus_view_factory_register (&nautilus_desktop_canvas_view);
886 }