nautilus-3.6.3/src/nautilus-desktop-canvas-view.c

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 }