1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
6 * Copyright (C) 1999, 2000 Red Hat, Inc.
7 * Copyright (C) 2000, 2001 Eazel, Inc.
9 * Nautilus is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version.
14 * Nautilus is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Authors: Elliot Lee <sopwith@redhat.com>,
24 * Darin Adler <darin@bentspoon.com>
29 #include "nautilus-application.h"
32 #include "file-manager/fm-ditem-page.h"
33 #include "file-manager/fm-desktop-icon-view.h"
34 #include "file-manager/fm-icon-view.h"
35 #include "file-manager/fm-list-view.h"
36 #include "file-manager/fm-tree-view.h"
38 #include "file-manager/fm-empty-view.h"
39 #endif /* ENABLE_EMPTY_VIEW */
40 #include "nautilus-information-panel.h"
41 #include "nautilus-history-sidebar.h"
42 #include "nautilus-places-sidebar.h"
43 #include "nautilus-notes-viewer.h"
44 #include "nautilus-emblem-sidebar.h"
45 #include "nautilus-image-properties-page.h"
46 #include <sys/types.h>
50 #include "nautilus-desktop-window.h"
51 #include "nautilus-main.h"
52 #include "nautilus-spatial-window.h"
53 #include "nautilus-navigation-window.h"
54 #include "nautilus-shell-interface.h"
55 #include "nautilus-shell.h"
56 #include "nautilus-window-bookmarks.h"
57 #include "libnautilus-private/nautilus-file-operations.h"
58 #include "nautilus-window-private.h"
59 #include "nautilus-window-manage-views.h"
60 #include <libxml/xmlsave.h>
61 #include <glib/gstdio.h>
62 #include <glib/gi18n.h>
64 #include <bonobo/bonobo-main.h>
65 #include <bonobo/bonobo-object.h>
66 #include <eel/eel-gtk-extensions.h>
67 #include <eel/eel-gtk-macros.h>
68 #include <eel/eel-stock-dialogs.h>
70 #include <gtk/gtkwindow.h>
71 #include <libgnome/gnome-config.h>
72 #include <libgnomeui/gnome-authentication-manager.h>
73 #include <libgnomeui/gnome-client.h>
74 #include <libnautilus-private/nautilus-debug-log.h>
75 #include <libnautilus-private/nautilus-file-utilities.h>
76 #include <libnautilus-private/nautilus-global-preferences.h>
77 #include <libnautilus-private/nautilus-module.h>
78 #include <libnautilus-private/nautilus-undo-manager.h>
79 #include <libnautilus-private/nautilus-desktop-link-monitor.h>
80 #include <libnautilus-private/nautilus-directory-private.h>
81 #include <libnautilus-private/nautilus-signaller.h>
82 #include <libnautilus-extension/nautilus-menu-provider.h>
83 #include <bonobo-activation/bonobo-activation.h>
84 #include <libnautilus-private/nautilus-autorun.h>
86 #ifdef HAVE_STARTUP_NOTIFICATION
87 #define SN_API_NOT_YET_FROZEN Yes_i_know_DO_IT
88 #include <libsn/sn-launchee.h>
91 /* Needed for the is_kdesktop_present check */
95 #define FACTORY_IID "OAFIID:Nautilus_Factory"
96 #define SEARCH_LIST_VIEW_IID "OAFIID:Nautilus_File_Manager_Search_List_View"
97 #define SHELL_IID "OAFIID:Nautilus_Shell"
98 #define TREE_VIEW_IID "OAFIID:Nautilus_File_Manager_Tree_View"
100 /* Keeps track of all the desktop windows. */
101 static GList
*nautilus_application_desktop_windows
;
103 /* Keeps track of all the nautilus windows. */
104 static GList
*nautilus_application_window_list
;
106 /* Keeps track of all the object windows */
107 static GList
*nautilus_application_spatial_window_list
;
109 static void desktop_changed_callback (gpointer user_data
);
110 static void desktop_location_changed_callback (gpointer user_data
);
111 static void mount_removed_callback (GVolumeMonitor
*monitor
,
113 NautilusApplication
*application
);
114 static void mount_added_callback (GVolumeMonitor
*monitor
,
116 NautilusApplication
*application
);
117 static void volume_added_callback (GVolumeMonitor
*monitor
,
119 NautilusApplication
*application
);
120 static void drive_connected_callback (GVolumeMonitor
*monitor
,
122 NautilusApplication
*application
);
123 static void drive_listen_for_eject_button (GDrive
*drive
,
124 NautilusApplication
*application
);
125 static void update_session (gpointer callback_data
);
126 static void init_session (void);
127 static gboolean
is_kdesktop_present (void);
129 BONOBO_CLASS_BOILERPLATE (NautilusApplication
, nautilus_application
,
130 BonoboGenericFactory
, BONOBO_TYPE_GENERIC_FACTORY
)
133 create_object (PortableServer_Servant servant
,
134 const CORBA_char
*iid
,
135 CORBA_Environment
*ev
)
137 BonoboObject
*object
;
138 NautilusApplication
*application
;
140 if (strcmp (iid
, SHELL_IID
) == 0) {
141 application
= NAUTILUS_APPLICATION (bonobo_object_from_servant (servant
));
142 object
= BONOBO_OBJECT (nautilus_shell_new (application
));
144 object
= CORBA_OBJECT_NIL
;
147 return CORBA_Object_duplicate (BONOBO_OBJREF (object
), ev
);
151 nautilus_application_get_window_list (void)
153 return nautilus_application_window_list
;
157 nautilus_application_get_spatial_window_list (void)
159 return nautilus_application_spatial_window_list
;
163 nautilus_application_get_n_windows (void)
165 return g_list_length (nautilus_application_window_list
) +
166 g_list_length (nautilus_application_desktop_windows
);
170 startup_volume_mount_cb (GObject
*source_object
,
174 g_volume_mount_finish (G_VOLUME (source_object
), res
, NULL
);
178 automount_all_volumes (NautilusApplication
*application
)
184 if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_MEDIA_AUTOMOUNT
)) {
185 /* automount all mountable volumes at start-up */
186 volumes
= g_volume_monitor_get_volumes (application
->volume_monitor
);
187 for (l
= volumes
; l
!= NULL
; l
= l
->next
) {
190 if (!g_volume_should_automount (volume
) ||
191 !g_volume_can_mount (volume
)) {
195 mount
= g_volume_get_mount (volume
);
197 g_object_unref (mount
);
201 /* pass NULL as GMountOperation to avoid user interaction */
202 g_volume_mount (volume
, 0, NULL
, NULL
, startup_volume_mount_cb
, NULL
);
204 eel_g_object_list_free (volumes
);
210 nautilus_application_instance_init (NautilusApplication
*application
)
212 /* Create an undo manager */
213 application
->undo_manager
= nautilus_undo_manager_new ();
215 application
->shell
= nautilus_shell_new (application
);
218 fm_icon_view_register ();
219 fm_desktop_icon_view_register ();
220 fm_list_view_register ();
221 #if ENABLE_EMPTY_VIEW
222 fm_empty_view_register ();
223 #endif /* ENABLE_EMPTY_VIEW */
225 /* register sidebars */
226 nautilus_places_sidebar_register ();
227 nautilus_information_panel_register ();
228 fm_tree_view_register ();
229 nautilus_history_sidebar_register ();
230 nautilus_notes_viewer_register (); /* also property page */
231 nautilus_emblem_sidebar_register ();
233 /* register property pages */
234 nautilus_image_properties_page_register ();
237 NautilusApplication
*
238 nautilus_application_new (void)
240 NautilusApplication
*application
;
242 application
= g_object_new (NAUTILUS_TYPE_APPLICATION
, NULL
);
244 bonobo_generic_factory_construct_noreg (BONOBO_GENERIC_FACTORY (application
),
252 nautilus_application_destroy (BonoboObject
*object
)
254 NautilusApplication
*application
;
256 application
= NAUTILUS_APPLICATION (object
);
258 nautilus_bookmarks_exiting ();
260 g_object_unref (application
->undo_manager
);
262 if (application
->volume_monitor
) {
263 g_object_unref (application
->volume_monitor
);
264 application
->volume_monitor
= NULL
;
267 if (application
->shell_registered
) {
268 bonobo_activation_unregister_active_server (SHELL_IID
, BONOBO_OBJREF (application
->shell
));
270 bonobo_object_unref (application
->shell
);
272 if (application
->automount_idle_id
!= 0) {
273 g_source_remove (application
->automount_idle_id
);
274 application
->automount_idle_id
= 0;
277 EEL_CALL_PARENT (BONOBO_OBJECT_CLASS
, destroy
, (object
));
281 check_required_directories (NautilusApplication
*application
)
283 char *user_directory
;
284 char *desktop_directory
;
288 g_assert (NAUTILUS_IS_APPLICATION (application
));
292 user_directory
= nautilus_get_user_directory ();
293 desktop_directory
= nautilus_get_desktop_directory ();
297 if (!g_file_test (user_directory
, G_FILE_TEST_IS_DIR
)) {
298 directories
= g_slist_prepend (directories
, user_directory
);
301 if (!g_file_test (desktop_directory
, G_FILE_TEST_IS_DIR
)) {
302 directories
= g_slist_prepend (directories
, desktop_directory
);
305 if (directories
!= NULL
) {
307 GString
*directories_as_string
;
310 const char *detail_string
;
315 failed_count
= g_slist_length (directories
);
317 directories_as_string
= g_string_new ((const char *)directories
->data
);
318 for (l
= directories
->next
; l
!= NULL
; l
= l
->next
) {
319 g_string_append_printf (directories_as_string
, ", %s", (const char *)l
->data
);
322 if (failed_count
== 1) {
323 error_string
= g_strdup_printf (_("Nautilus could not create the required folder \"%s\"."),
324 directories_as_string
->str
);
325 detail_string
= _("Before running Nautilus, please create the following folder, or "
326 "set permissions such that Nautilus can create it.");
328 error_string
= g_strdup_printf (_("Nautilus could not create the following required folders: "
329 "%s."), directories_as_string
->str
);
330 detail_string
= _("Before running Nautilus, please create these folders, or "
331 "set permissions such that Nautilus can create them.");
334 dialog
= eel_show_error_dialog (error_string
, detail_string
, NULL
);
335 /* We need the main event loop so the user has a chance to see the dialog. */
336 nautilus_main_event_loop_register (GTK_OBJECT (dialog
));
338 g_string_free (directories_as_string
, TRUE
);
339 g_free (error_string
);
342 g_slist_free (directories
);
343 g_free (user_directory
);
344 g_free (desktop_directory
);
349 static Nautilus_URIList
*
350 nautilus_make_uri_list_from_shell_strv (const char * const *strv
)
353 Nautilus_URIList
*uri_list
;
355 char *translated_uri
;
357 length
= g_strv_length ((char **) strv
);
359 uri_list
= Nautilus_URIList__alloc ();
360 uri_list
->_maximum
= length
;
361 uri_list
->_length
= length
;
362 uri_list
->_buffer
= CORBA_sequence_Nautilus_URI_allocbuf (length
);
363 for (i
= 0; i
< length
; i
++) {
364 file
= g_file_new_for_commandline_arg (strv
[i
]);
365 translated_uri
= g_file_get_uri (file
);
366 g_object_unref (file
);
367 uri_list
->_buffer
[i
] = CORBA_string_dup (translated_uri
);
368 g_free (translated_uri
);
369 translated_uri
= NULL
;
371 CORBA_sequence_set_release (uri_list
, CORBA_TRUE
);
377 menu_provider_items_updated_handler (NautilusMenuProvider
*provider
, GtkWidget
* parent_window
, gpointer data
)
380 g_signal_emit_by_name (nautilus_signaller_get_current (),
381 "popup_menu_changed");
385 menu_provider_init_callback (void)
391 providers
= nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_MENU_PROVIDER
);
394 for (l
= providers
; l
!= NULL
; l
= l
->next
) {
395 NautilusMenuProvider
*provider
= NAUTILUS_MENU_PROVIDER (l
->data
);
397 g_signal_connect_after (G_OBJECT (provider
), "items_updated",
398 (GCallback
)menu_provider_items_updated_handler
,
402 nautilus_module_extension_list_free (providers
);
406 automount_all_volumes_idle_cb (gpointer data
)
408 NautilusApplication
*application
= NAUTILUS_APPLICATION (data
);
410 automount_all_volumes (application
);
412 application
->automount_idle_id
= 0;
417 finish_startup (NautilusApplication
*application
)
421 /* initialize nautilus modules */
422 nautilus_module_init ();
424 nautilus_module_add_type (FM_TYPE_DITEM_PAGE
);
426 /* attach menu-provider module callback */
427 menu_provider_init_callback ();
429 /* Initialize the desktop link monitor singleton */
430 nautilus_desktop_link_monitor_get ();
432 /* Watch for mounts so we can restore open windows This used
433 * to be for showing new window on mount, but is not used
436 /* Watch for unmounts so we can close open windows */
437 /* TODO-gio: This should be using the UNMOUNTED feature of GFileMonitor instead */
438 application
->volume_monitor
= g_volume_monitor_get ();
439 g_signal_connect_object (application
->volume_monitor
, "mount_removed",
440 G_CALLBACK (mount_removed_callback
), application
, 0);
441 g_signal_connect_object (application
->volume_monitor
, "mount_pre_unmount",
442 G_CALLBACK (mount_removed_callback
), application
, 0);
443 g_signal_connect_object (application
->volume_monitor
, "mount_added",
444 G_CALLBACK (mount_added_callback
), application
, 0);
445 g_signal_connect_object (application
->volume_monitor
, "volume_added",
446 G_CALLBACK (volume_added_callback
), application
, 0);
447 g_signal_connect_object (application
->volume_monitor
, "drive_connected",
448 G_CALLBACK (drive_connected_callback
), application
, 0);
450 /* listen for eject button presses */
451 drives
= g_volume_monitor_get_connected_drives (application
->volume_monitor
);
452 g_list_foreach (drives
, (GFunc
) drive_listen_for_eject_button
, application
);
453 g_list_foreach (drives
, (GFunc
) g_object_unref
, NULL
);
454 g_list_free (drives
);
456 application
->automount_idle_id
=
457 g_idle_add_full (G_PRIORITY_LOW
,
458 automount_all_volumes_idle_cb
,
463 initialize_kde_trash_hack (void)
466 char *desktop_dir
, *desktop_uri
, *kde_trash_dir
;
467 char *dir
, *basename
;
474 desktop_uri
= nautilus_get_desktop_directory_uri_no_create ();
475 desktop_dir
= g_filename_from_uri (desktop_uri
, NULL
, NULL
);
476 g_free (desktop_uri
);
478 if (g_file_test (desktop_dir
, G_FILE_TEST_EXISTS
)) {
479 /* Look for trash directory */
480 kde_conf_file
= g_build_filename (g_get_home_dir(), ".kde/share/config/kdeglobals", NULL
);
481 key
= g_strconcat ("=", kde_conf_file
, "=/Paths/Trash", NULL
);
482 kde_trash_dir
= gnome_config_get_string_with_default (key
, &def
);
483 gnome_config_drop_file (kde_conf_file
);
484 g_free (kde_conf_file
);
487 if (kde_trash_dir
== NULL
) {
488 kde_conf_file
= "/usr/share/config/kdeglobals";
489 key
= g_strconcat ("=", kde_conf_file
, "=/Paths/Trash", NULL
);
490 kde_trash_dir
= gnome_config_get_string_with_default (key
, &def
);
491 gnome_config_drop_file (kde_conf_file
);
495 if (kde_trash_dir
!= NULL
) {
496 basename
= g_path_get_basename (kde_trash_dir
);
497 g_free (kde_trash_dir
);
499 dir
= g_build_filename (desktop_dir
, basename
, NULL
);
501 if (g_file_test (dir
, G_FILE_TEST_IS_DIR
)) {
502 trash_dir
= g_strdup (basename
);
508 if (trash_dir
!= NULL
) {
509 nautilus_set_kde_trash_name (trash_dir
);
514 g_free (desktop_dir
);
518 static Bonobo_RegistrationResult
519 nautilus_bonobo_activation_register_for_display (const char *iid
,
522 const char *display_name
;
524 Bonobo_RegistrationResult result
;
526 display_name
= gdk_display_get_name (gdk_display_get_default());
527 reg_env
= bonobo_activation_registration_env_set (NULL
,
528 "DISPLAY", display_name
);
529 result
= bonobo_activation_register_active_server (iid
, ref
, reg_env
);
530 bonobo_activation_registration_env_free (reg_env
);
535 nautilus_application_startup (NautilusApplication
*application
,
537 gboolean restart_shell
,
538 gboolean no_default_window
,
540 gboolean browser_window
,
541 const char *startup_id
,
542 const char *geometry
,
543 const char *session_to_load
,
546 CORBA_Environment ev
;
547 Nautilus_Shell shell
;
548 Bonobo_RegistrationResult result
;
549 const char *message
, *detailed_message
;
551 Nautilus_URIList
*url_list
;
552 const CORBA_char
*corba_startup_id
;
553 const CORBA_char
*corba_geometry
;
558 /* Check the user's ~/.nautilus directories and post warnings
559 * if there are problems.
561 if (!kill_shell
&& !check_required_directories (application
)) {
565 initialize_kde_trash_hack ();
567 CORBA_exception_init (&ev
);
569 /* Start up the factory. */
571 /* Try to register the file manager view factory. */
572 result
= nautilus_bonobo_activation_register_for_display
573 (SHELL_IID
, BONOBO_OBJREF (application
->shell
));
576 case Bonobo_ACTIVATION_REG_SUCCESS
:
577 /* We are registered and all is right with the world. */
578 application
->shell_registered
= TRUE
;
579 finish_startup (application
);
581 detailed_message
= NULL
;
583 case Bonobo_ACTIVATION_REG_ALREADY_ACTIVE
:
584 /* Another copy of nautilus already is running and registered. */
586 detailed_message
= NULL
;
588 case Bonobo_ACTIVATION_REG_NOT_LISTED
:
589 /* Can't register myself due to trouble locating the
590 * Nautilus_Shell.server file. This has happened when you
591 * launch Nautilus with an LD_LIBRARY_PATH that
592 * doesn't include the directory containing the oaf
593 * library. It could also happen if the
594 * Nautilus_Shell.server file was not present for some
595 * reason. Sometimes killing oafd and gconfd fixes
596 * this problem but we don't exactly understand why,
597 * since neither of the above causes explain it.
599 message
= _("Nautilus cannot be used now. "
600 "Running the command \"bonobo-slay\""
601 " from the console may fix the problem. If not,"
602 " you can try rebooting the computer or"
603 " installing Nautilus again.");
604 /* FIXME bugzilla.gnome.org 42536: The guesses and stuff here are lame. */
605 detailed_message
= _("Nautilus cannot be used now. "
606 "Running the command \"bonobo-slay\" "
607 "from the console may fix the problem. If not, "
608 "you can try rebooting the computer or "
609 "installing Nautilus again.\n\n"
610 "Bonobo could not locate the Nautilus_shell.server file. "
611 "One cause of this seems to be an LD_LIBRARY_PATH "
612 "that does not include the bonobo-activation library's directory. "
613 "Another possible cause would be bad install "
614 "with a missing Nautilus_Shell.server file.\n\n"
615 "Running \"bonobo-slay\" will kill all "
616 "Bonobo Activation and GConf processes, which may be needed by "
617 "other applications.\n\n"
618 "Sometimes killing bonobo-activation-server and gconfd fixes "
619 "the problem, but we do not know why.\n\n"
620 "We have also seen this error when a faulty "
621 "version of bonobo-activation was installed.");
624 /* This should never happen. */
625 g_warning ("bad error code from bonobo_activation_active_server_register");
626 case Bonobo_ACTIVATION_REG_ERROR
:
627 /* Some misc. error (can never happen with current
628 * version of bonobo-activation). Show dialog and terminate the
631 /* FIXME bugzilla.gnome.org 42537: Looks like this does happen with the
632 * current OAF. I guess I read the code wrong. Need to figure out when and make a
635 message
= _("Nautilus cannot be used now, due to an unexpected error.");
636 detailed_message
= _("Nautilus cannot be used now, due to an unexpected error "
637 "from Bonobo when attempting to register the file manager view server.");
641 /* Get the shell object. */
642 if (message
== NULL
) {
643 shell
= bonobo_activation_activate_from_id (SHELL_IID
, Bonobo_ACTIVATION_FLAG_EXISTING_ONLY
, NULL
, NULL
);
644 if (!CORBA_Object_is_nil (shell
, &ev
)) {
648 /* If we couldn't find ourselves it's a bad problem so
649 * we better stop looping.
651 if (result
== Bonobo_ACTIVATION_REG_SUCCESS
) {
652 /* FIXME bugzilla.gnome.org 42538: When can this happen? */
653 message
= _("Nautilus cannot be used now, due to an unexpected error.");
654 detailed_message
= _("Nautilus cannot be used now, due to an unexpected error "
655 "from Bonobo when attempting to locate the factory. "
656 "Killing bonobo-activation-server and restarting Nautilus may help fix the problem.");
659 if (num_failures
> 20) {
660 message
= _("Nautilus cannot be used now, due to an unexpected error.");
661 detailed_message
= _("Nautilus cannot be used now, due to an unexpected error "
662 "from Bonobo when attempting to locate the shell object. "
663 "Killing bonobo-activation-server and restarting Nautilus may help fix the problem.");
669 if (message
!= NULL
) {
670 dialog
= eel_show_error_dialog_with_details (message
, NULL
, detailed_message
, NULL
);
671 /* We need the main event loop so the user has a chance to see the dialog. */
672 nautilus_main_event_loop_register (GTK_OBJECT (dialog
));
678 Nautilus_Shell_quit (shell
, &ev
);
679 } else if (restart_shell
) {
680 Nautilus_Shell_restart (shell
, &ev
);
682 /* If KDE desktop is running, then force no_desktop */
683 if (is_kdesktop_present ()) {
687 if (!no_desktop
&& eel_preferences_get_boolean (NAUTILUS_PREFERENCES_SHOW_DESKTOP
)) {
688 Nautilus_Shell_start_desktop (shell
, &ev
);
691 /* Monitor the preference to show or hide the desktop */
692 eel_preferences_add_callback_while_alive (NAUTILUS_PREFERENCES_SHOW_DESKTOP
,
693 desktop_changed_callback
,
695 G_OBJECT (application
));
697 /* Monitor the preference to have the desktop */
698 /* point to the Unix home folder */
699 eel_preferences_add_callback_while_alive (NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR
,
700 desktop_location_changed_callback
,
702 G_OBJECT (application
));
704 /* CORBA C mapping doesn't allow NULL to be passed
705 for string parameters */
706 corba_geometry
= (geometry
!= NULL
) ? geometry
: "";
707 corba_startup_id
= (startup_id
!= NULL
) ? startup_id
: "";
709 /* Create the other windows. */
711 url_list
= nautilus_make_uri_list_from_shell_strv (urls
);
712 Nautilus_Shell_open_windows (shell
, url_list
, corba_startup_id
, corba_geometry
, browser_window
, &ev
);
713 CORBA_free (url_list
);
714 } else if (!no_default_window
) {
715 g_assert (session_to_load
== NULL
);
716 Nautilus_Shell_open_default_window (shell
, corba_startup_id
, corba_geometry
, browser_window
, &ev
);
719 if (session_to_load
!= NULL
) {
720 Nautilus_Shell_load_session (shell
, session_to_load
, &ev
);
723 /* Add ourselves to the session */
728 CORBA_exception_free (&ev
);
733 selection_get_cb (GtkWidget
*widget
,
734 GtkSelectionData
*selection_data
,
738 /* No extra targets atm */
742 get_desktop_manager_selection (GdkDisplay
*display
, int screen
)
744 char selection_name
[32];
745 GdkAtom selection_atom
;
746 Window selection_owner
;
747 GtkWidget
*selection_widget
;
749 g_snprintf (selection_name
, sizeof (selection_name
), "_NET_DESKTOP_MANAGER_S%d", screen
);
750 selection_atom
= gdk_atom_intern (selection_name
, FALSE
);
752 selection_owner
= XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display
),
753 gdk_x11_atom_to_xatom_for_display (display
,
755 if (selection_owner
!= None
) {
759 selection_widget
= gtk_invisible_new_for_screen (gdk_display_get_screen (display
, screen
));
760 /* We need this for gdk_x11_get_server_time() */
761 gtk_widget_add_events (selection_widget
, GDK_PROPERTY_CHANGE_MASK
);
763 if (gtk_selection_owner_set_for_display (display
,
766 gdk_x11_get_server_time (selection_widget
->window
))) {
768 g_signal_connect (selection_widget
, "selection_get",
769 G_CALLBACK (selection_get_cb
), NULL
);
770 return selection_widget
;
773 gtk_widget_destroy (selection_widget
);
779 desktop_unrealize_cb (GtkWidget
*widget
,
780 GtkWidget
*selection_widget
)
782 gtk_widget_destroy (selection_widget
);
786 selection_clear_event_cb (GtkWidget
*widget
,
787 GdkEventSelection
*event
,
788 NautilusDesktopWindow
*window
)
790 gtk_widget_destroy (GTK_WIDGET (window
));
792 nautilus_application_desktop_windows
=
793 g_list_remove (nautilus_application_desktop_windows
, window
);
799 nautilus_application_create_desktop_windows (NautilusApplication
*application
)
801 static gboolean create_in_progress
= FALSE
;
803 NautilusDesktopWindow
*window
;
804 GtkWidget
*selection_widget
;
807 g_return_if_fail (nautilus_application_desktop_windows
== NULL
);
808 g_return_if_fail (NAUTILUS_IS_APPLICATION (application
));
810 if (create_in_progress
) {
814 create_in_progress
= TRUE
;
816 display
= gdk_display_get_default ();
817 screens
= gdk_display_get_n_screens (display
);
819 for (i
= 0; i
< screens
; i
++) {
820 selection_widget
= get_desktop_manager_selection (display
, i
);
821 if (selection_widget
!= NULL
) {
822 window
= nautilus_desktop_window_new (application
,
823 gdk_display_get_screen (display
, i
));
825 g_signal_connect (selection_widget
, "selection_clear_event",
826 G_CALLBACK (selection_clear_event_cb
), window
);
828 g_signal_connect (window
, "unrealize",
829 G_CALLBACK (desktop_unrealize_cb
), selection_widget
);
831 /* We realize it immediately so that the NAUTILUS_DESKTOP_WINDOW_ID
832 property is set so gnome-settings-daemon doesn't try to set the
833 background. And we do a gdk_flush() to be sure X gets it. */
834 gtk_widget_realize (GTK_WIDGET (window
));
838 nautilus_application_desktop_windows
=
839 g_list_prepend (nautilus_application_desktop_windows
, window
);
843 create_in_progress
= FALSE
;
847 nautilus_application_open_desktop (NautilusApplication
*application
)
849 if (nautilus_application_desktop_windows
== NULL
) {
850 nautilus_application_create_desktop_windows (application
);
852 /* Make sure we update the session when the desktop is created */
853 update_session (gnome_master_client ());
858 nautilus_application_close_desktop (void)
860 if (nautilus_application_desktop_windows
!= NULL
) {
861 g_list_foreach (nautilus_application_desktop_windows
,
862 (GFunc
) gtk_widget_destroy
, NULL
);
863 g_list_free (nautilus_application_desktop_windows
);
864 nautilus_application_desktop_windows
= NULL
;
866 /* Make sure we update the session when the desktop goes away */
867 update_session (gnome_master_client ());
872 nautilus_application_close_all_navigation_windows (void)
877 list_copy
= g_list_copy (nautilus_application_window_list
);
878 for (l
= list_copy
; l
!= NULL
; l
= l
->next
) {
879 NautilusWindow
*window
;
881 window
= NAUTILUS_WINDOW (l
->data
);
883 if (NAUTILUS_IS_NAVIGATION_WINDOW (window
)) {
884 nautilus_window_close (window
);
887 g_list_free (list_copy
);
890 static NautilusSpatialWindow
*
891 nautilus_application_get_existing_spatial_window (GFile
*location
)
895 for (l
= nautilus_application_get_spatial_window_list ();
896 l
!= NULL
; l
= l
->next
) {
897 GFile
*window_location
;
899 window_location
= nautilus_window_get_location (NAUTILUS_WINDOW (l
->data
));
900 if (window_location
!= NULL
) {
901 if (g_file_equal (location
, window_location
)) {
902 g_object_unref (window_location
);
903 return NAUTILUS_SPATIAL_WINDOW (l
->data
);
905 g_object_unref (window_location
);
911 static NautilusSpatialWindow
*
912 find_parent_spatial_window (NautilusSpatialWindow
*window
)
915 NautilusFile
*parent_file
;
918 location
= nautilus_window_get_location (NAUTILUS_WINDOW (window
));
919 if (location
== NULL
) {
922 file
= nautilus_file_get (location
);
923 g_object_unref (location
);
929 parent_file
= nautilus_file_get_parent (file
);
930 nautilus_file_unref (file
);
931 while (parent_file
) {
932 NautilusSpatialWindow
*parent_window
;
934 location
= nautilus_file_get_location (parent_file
);
935 parent_window
= nautilus_application_get_existing_spatial_window (location
);
936 g_object_unref (location
);
938 /* Stop at the desktop directory if it's not explicitely opened
939 * in a spatial window of its own.
941 if (nautilus_file_is_desktop_directory (parent_file
) && !parent_window
) {
942 nautilus_file_unref (parent_file
);
947 nautilus_file_unref (parent_file
);
948 return parent_window
;
951 parent_file
= nautilus_file_get_parent (file
);
952 nautilus_file_unref (file
);
959 nautilus_application_close_parent_windows (NautilusSpatialWindow
*window
)
961 NautilusSpatialWindow
*parent_window
;
962 NautilusSpatialWindow
*new_parent_window
;
964 g_return_if_fail (NAUTILUS_IS_SPATIAL_WINDOW (window
));
966 parent_window
= find_parent_spatial_window (window
);
968 while (parent_window
) {
970 new_parent_window
= find_parent_spatial_window (parent_window
);
971 nautilus_window_close (NAUTILUS_WINDOW (parent_window
));
972 parent_window
= new_parent_window
;
977 nautilus_application_close_all_spatial_windows (void)
982 list_copy
= g_list_copy (nautilus_application_spatial_window_list
);
983 for (l
= list_copy
; l
!= NULL
; l
= l
->next
) {
984 NautilusWindow
*window
;
986 window
= NAUTILUS_WINDOW (l
->data
);
988 if (NAUTILUS_IS_SPATIAL_WINDOW (window
)) {
989 nautilus_window_close (window
);
992 g_list_free (list_copy
);
996 nautilus_application_destroyed_window (GtkObject
*object
, NautilusApplication
*application
)
998 nautilus_application_window_list
= g_list_remove (nautilus_application_window_list
, object
);
1002 nautilus_window_delete_event_callback (GtkWidget
*widget
,
1006 NautilusWindow
*window
;
1008 window
= NAUTILUS_WINDOW (widget
);
1009 nautilus_window_close (window
);
1015 static NautilusWindow
*
1016 create_window (NautilusApplication
*application
,
1018 const char *startup_id
,
1021 NautilusWindow
*window
;
1023 g_return_val_if_fail (NAUTILUS_IS_APPLICATION (application
), NULL
);
1025 window
= NAUTILUS_WINDOW (gtk_widget_new (window_type
,
1029 /* Must be called after construction finished */
1030 nautilus_window_constructed (window
);
1032 g_signal_connect_data (window
, "delete_event",
1033 G_CALLBACK (nautilus_window_delete_event_callback
), NULL
, NULL
,
1036 g_signal_connect_object (window
, "destroy",
1037 G_CALLBACK (nautilus_application_destroyed_window
), application
, 0);
1039 nautilus_application_window_list
= g_list_prepend (nautilus_application_window_list
, window
);
1041 /* Do not yet show the window. It will be shown later on if it can
1042 * successfully display its initial URI. Otherwise it will be destroyed
1043 * without ever having seen the light of day.
1050 spatial_window_destroyed_callback (void *user_data
, GObject
*window
)
1052 nautilus_application_spatial_window_list
= g_list_remove (nautilus_application_spatial_window_list
, window
);
1057 nautilus_application_present_spatial_window (NautilusApplication
*application
,
1058 NautilusWindow
*requesting_window
,
1059 const char *startup_id
,
1063 return nautilus_application_present_spatial_window_with_selection (application
,
1071 #ifdef HAVE_STARTUP_NOTIFICATION
1074 sn_error_trap_push (SnDisplay
*display
,
1077 gdk_error_trap_push ();
1081 sn_error_trap_pop (SnDisplay
*display
,
1084 gdk_error_trap_pop ();
1088 end_startup_notification (GtkWidget
*widget
,
1089 const char *startup_id
)
1091 SnDisplay
*sn_display
;
1092 SnLauncheeContext
*context
;
1093 GdkDisplay
*display
;
1096 if (startup_id
== NULL
) {
1100 if (!GTK_WIDGET_REALIZED (widget
)) {
1101 gtk_widget_realize (widget
);
1107 /* Set up window for launch notification */
1108 /* FIXME In principle all transient children of this
1109 * window should get the same startup_id
1112 screen
= gtk_widget_get_screen (widget
);
1113 display
= gdk_screen_get_display (screen
);
1115 sn_display
= sn_display_new (gdk_x11_display_get_xdisplay (display
),
1119 context
= sn_launchee_context_new (sn_display
,
1120 gdk_screen_get_number (screen
),
1123 /* Handle the setup for the window if the startup_id is valid;
1124 * I don't think it can hurt to do this even if it was
1125 * invalid, but why do the extra work...
1127 if (strncmp (sn_launchee_context_get_startup_id (context
), "_TIME", 5) != 0) {
1128 sn_launchee_context_setup_window (context
,
1129 GDK_WINDOW_XWINDOW (widget
->window
));
1132 /* Now, set the _NET_WM_USER_TIME for the new window to the timestamp
1133 * that caused the window to be launched.
1135 if (sn_launchee_context_get_id_has_timestamp (context
)) {
1136 gulong startup_id_timestamp
;
1137 startup_id_timestamp
= sn_launchee_context_get_timestamp (context
);
1138 gdk_x11_window_set_user_time (widget
->window
, startup_id_timestamp
);
1141 sn_launchee_context_complete (context
);
1142 sn_launchee_context_unref (context
);
1143 sn_display_unref (sn_display
);
1149 nautilus_application_present_spatial_window_with_selection (NautilusApplication
*application
,
1150 NautilusWindow
*requesting_window
,
1151 const char *startup_id
,
1153 GList
*new_selection
,
1156 NautilusWindow
*window
;
1160 g_return_val_if_fail (NAUTILUS_IS_APPLICATION (application
), NULL
);
1162 for (l
= nautilus_application_get_spatial_window_list ();
1163 l
!= NULL
; l
= l
->next
) {
1164 NautilusWindow
*existing_window
;
1165 GFile
*existing_location
;
1167 existing_window
= NAUTILUS_WINDOW (l
->data
);
1168 existing_location
= existing_window
->details
->pending_location
;
1170 if (existing_location
== NULL
) {
1171 existing_location
= existing_window
->details
->location
;
1174 if (g_file_equal (existing_location
, location
)) {
1175 #ifdef HAVE_STARTUP_NOTIFICATION
1176 end_startup_notification (GTK_WIDGET (existing_window
),
1180 gtk_window_present (GTK_WINDOW (existing_window
));
1181 if (new_selection
&&
1182 existing_window
->content_view
!= NULL
) {
1183 nautilus_view_set_selection (existing_window
->content_view
, new_selection
);
1186 uri
= g_file_get_uri (location
);
1187 nautilus_debug_log (FALSE
, NAUTILUS_DEBUG_LOG_DOMAIN_USER
,
1188 "present EXISTING spatial window=%p: %s",
1189 existing_window
, uri
);
1191 return existing_window
;
1195 window
= create_window (application
, NAUTILUS_TYPE_SPATIAL_WINDOW
, startup_id
, screen
);
1196 #ifdef HAVE_STARTUP_NOTIFICATION
1197 end_startup_notification (GTK_WIDGET (window
),
1200 if (requesting_window
) {
1201 /* Center the window over the requesting window by default */
1202 int orig_x
, orig_y
, orig_width
, orig_height
;
1203 int new_x
, new_y
, new_width
, new_height
;
1205 gtk_window_get_position (GTK_WINDOW (requesting_window
),
1207 gtk_window_get_size (GTK_WINDOW (requesting_window
),
1208 &orig_width
, &orig_height
);
1209 gtk_window_get_default_size (GTK_WINDOW (window
),
1210 &new_width
, &new_height
);
1212 new_x
= orig_x
+ (orig_width
- new_width
) / 2;
1213 new_y
= orig_y
+ (orig_height
- new_height
) / 2;
1215 if (orig_width
- new_width
< 10) {
1220 gtk_window_move (GTK_WINDOW (window
), new_x
, new_y
);
1223 nautilus_application_spatial_window_list
= g_list_prepend (nautilus_application_spatial_window_list
, window
);
1224 g_object_weak_ref (G_OBJECT (window
),
1225 spatial_window_destroyed_callback
, NULL
);
1227 nautilus_window_go_to_with_selection (window
, location
, new_selection
);
1229 uri
= g_file_get_uri (location
);
1230 nautilus_debug_log (FALSE
, NAUTILUS_DEBUG_LOG_DOMAIN_USER
,
1231 "present NEW spatial window=%p: %s",
1239 another_navigation_window_already_showing (NautilusWindow
*the_window
)
1243 list
= nautilus_application_get_window_list ();
1244 for (item
= list
; item
!= NULL
; item
= item
->next
) {
1245 if (item
->data
!= the_window
&&
1246 NAUTILUS_IS_NAVIGATION_WINDOW (item
->data
)) {
1255 nautilus_application_create_navigation_window (NautilusApplication
*application
,
1256 const char *startup_id
,
1259 NautilusWindow
*window
;
1260 char *geometry_string
;
1263 g_return_val_if_fail (NAUTILUS_IS_APPLICATION (application
), NULL
);
1265 window
= create_window (application
, NAUTILUS_TYPE_NAVIGATION_WINDOW
, startup_id
, screen
);
1266 #ifdef HAVE_STARTUP_NOTIFICATION
1267 end_startup_notification (GTK_WIDGET (window
),
1271 maximized
= eel_preferences_get_boolean
1272 (NAUTILUS_PREFERENCES_NAVIGATION_WINDOW_MAXIMIZED
);
1274 gtk_window_maximize (GTK_WINDOW (window
));
1276 gtk_window_unmaximize (GTK_WINDOW (window
));
1279 geometry_string
= eel_preferences_get
1280 (NAUTILUS_PREFERENCES_NAVIGATION_WINDOW_SAVED_GEOMETRY
);
1281 if (geometry_string
!= NULL
&&
1282 geometry_string
[0] != 0) {
1283 /* Ignore saved window position if a window with the same
1284 * location is already showing. That way the two windows
1285 * wont appear at the exact same location on the screen.
1287 eel_gtk_window_set_initial_geometry_from_string
1288 (GTK_WINDOW (window
),
1290 NAUTILUS_WINDOW_MIN_WIDTH
,
1291 NAUTILUS_WINDOW_MIN_HEIGHT
,
1292 another_navigation_window_already_showing (window
));
1294 g_free (geometry_string
);
1296 nautilus_debug_log (FALSE
, NAUTILUS_DEBUG_LOG_DOMAIN_USER
,
1297 "create new navigation window=%p",
1303 /* callback for changing the directory the desktop points to */
1305 desktop_location_changed_callback (gpointer user_data
)
1307 if (nautilus_application_desktop_windows
!= NULL
) {
1308 g_list_foreach (nautilus_application_desktop_windows
,
1309 (GFunc
) nautilus_desktop_window_update_directory
, NULL
);
1313 /* callback for showing or hiding the desktop based on the user's preference */
1315 desktop_changed_callback (gpointer user_data
)
1317 NautilusApplication
*application
;
1319 application
= NAUTILUS_APPLICATION (user_data
);
1320 if ( eel_preferences_get_boolean (NAUTILUS_PREFERENCES_SHOW_DESKTOP
)) {
1321 nautilus_application_open_desktop (application
);
1323 nautilus_application_close_desktop ();
1328 window_can_be_closed (NautilusWindow
*window
)
1330 if (!NAUTILUS_IS_DESKTOP_WINDOW (window
)) {
1338 volume_added_callback (GVolumeMonitor
*monitor
,
1340 NautilusApplication
*application
)
1342 if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_MEDIA_AUTOMOUNT
) &&
1343 g_volume_should_automount (volume
) &&
1344 g_volume_can_mount (volume
)) {
1345 nautilus_file_operations_mount_volume (NULL
, volume
, TRUE
);
1350 drive_eject_cb (GObject
*source_object
,
1358 if (!g_drive_eject_finish (G_DRIVE (source_object
), res
, &error
)) {
1359 if (error
->code
!= G_IO_ERROR_FAILED_HANDLED
) {
1360 name
= g_drive_get_name (G_DRIVE (source_object
));
1361 primary
= g_strdup_printf (_("Unable to eject %s"), name
);
1363 eel_show_error_dialog (primary
,
1368 g_error_free (error
);
1373 drive_eject_button_pressed (GDrive
*drive
,
1374 NautilusApplication
*application
)
1376 g_drive_eject (drive
, 0, NULL
, drive_eject_cb
, NULL
);
1380 drive_listen_for_eject_button (GDrive
*drive
, NautilusApplication
*application
)
1382 g_signal_connect (drive
,
1384 G_CALLBACK (drive_eject_button_pressed
),
1389 drive_connected_callback (GVolumeMonitor
*monitor
,
1391 NautilusApplication
*application
)
1393 drive_listen_for_eject_button (drive
, application
);
1397 autorun_show_window (GMount
*mount
, gpointer user_data
)
1400 NautilusApplication
*application
= user_data
;
1402 location
= g_mount_get_root (mount
);
1404 /* Ther should probably be an easier way to do this */
1405 if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_ALWAYS_USE_BROWSER
)) {
1406 NautilusWindow
*window
;
1407 window
= nautilus_application_create_navigation_window (application
,
1409 gdk_screen_get_default ());
1410 nautilus_window_go_to (window
, location
);
1413 nautilus_application_present_spatial_window (application
,
1417 gdk_screen_get_default ());
1419 g_object_unref (location
);
1423 mount_added_callback (GVolumeMonitor
*monitor
,
1425 NautilusApplication
*application
)
1427 NautilusDirectory
*directory
;
1430 root
= g_mount_get_root (mount
);
1431 directory
= nautilus_directory_get_existing (root
);
1432 g_object_unref (root
);
1433 if (directory
!= NULL
) {
1434 nautilus_directory_force_reload (directory
);
1435 nautilus_directory_unref (directory
);
1438 nautilus_autorun (mount
, autorun_show_window
, application
);
1441 /* Called whenever a mount is unmounted. Check and see if there are
1442 * any windows open displaying contents on the mount. If there are,
1443 * close them. It would also be cool to save open window and position
1446 * This is also called on pre_unmount.
1449 mount_removed_callback (GVolumeMonitor
*monitor
,
1451 NautilusApplication
*application
)
1453 GList
*window_list
, *node
, *close_list
;
1454 NautilusWindow
*window
;
1459 /* Check and see if any of the open windows are displaying contents from the unmounted mount */
1460 window_list
= nautilus_application_get_window_list ();
1462 root
= g_mount_get_root (mount
);
1463 /* Construct a list of windows to be closed. Do not add the non-closable windows to the list. */
1464 for (node
= window_list
; node
!= NULL
; node
= node
->next
) {
1465 window
= NAUTILUS_WINDOW (node
->data
);
1466 if (window
!= NULL
&& window_can_be_closed (window
)) {
1469 location
= nautilus_window_get_location (window
);
1471 if (g_file_has_prefix (location
, root
)) {
1472 close_list
= g_list_prepend (close_list
, window
);
1474 g_object_unref (location
);
1478 /* Handle the windows in the close list. */
1479 for (node
= close_list
; node
!= NULL
; node
= node
->next
) {
1480 window
= NAUTILUS_WINDOW (node
->data
);
1481 if (NAUTILUS_IS_SPATIAL_WINDOW (window
)) {
1482 nautilus_window_close (window
);
1484 nautilus_window_go_home (window
);
1488 g_list_free (close_list
);
1492 removed_from_session (GnomeClient
*client
, gpointer data
)
1494 nautilus_main_event_loop_quit (FALSE
);
1498 icon_to_string (GIcon
*icon
)
1500 const char * const *names
;
1505 } else if (G_IS_THEMED_ICON (icon
)) {
1506 names
= g_themed_icon_get_names (G_THEMED_ICON (icon
));
1507 return g_strjoinv (":", (char **)names
);
1508 } else if (G_IS_FILE_ICON (icon
)) {
1509 file
= g_file_icon_get_file (G_FILE_ICON (icon
));
1510 return g_file_get_path (file
);
1516 icon_from_string (const char *string
)
1522 if (g_path_is_absolute (string
)) {
1523 file
= g_file_new_for_path (string
);
1524 icon
= g_file_icon_new (file
);
1525 g_object_unref (file
);
1528 names
= g_strsplit (string
, ":", 0);
1529 icon
= g_themed_icon_new_from_names (names
, -1);
1537 nautilus_application_save_session_to_file (void)
1540 xmlNodePtr root_node
, history_node
;
1542 char *dir
, *filename
;
1543 unsigned n_processed
;
1547 doc
= xmlNewDoc ("1.0");
1549 root_node
= xmlNewNode (NULL
, "session");
1550 xmlDocSetRootElement (doc
, root_node
);
1552 history_node
= xmlNewChild (root_node
, NULL
, "history", NULL
);
1555 for (l
= nautilus_get_history_list (); l
!= NULL
; l
= l
->next
) {
1556 NautilusBookmark
*bookmark
;
1557 xmlNodePtr bookmark_node
;
1563 bookmark_node
= xmlNewChild (history_node
, NULL
, "bookmark", NULL
);
1565 tmp
= nautilus_bookmark_get_name (bookmark
);
1566 xmlNewProp (bookmark_node
, "name", tmp
);
1569 icon
= nautilus_bookmark_get_icon (bookmark
);
1570 tmp
= icon_to_string (icon
);
1571 g_object_unref (icon
);
1573 xmlNewProp (bookmark_node
, "icon", tmp
);
1577 tmp
= nautilus_bookmark_get_uri (bookmark
);
1578 xmlNewProp (bookmark_node
, "uri", tmp
);
1581 if (nautilus_bookmark_get_has_custom_name (bookmark
)) {
1582 xmlNewProp (bookmark_node
, "has_custom_name", "TRUE");
1585 if (++n_processed
> 50) { /* prevent history list from growing arbitrarily large. */
1590 for (l
= nautilus_application_window_list
; l
!= NULL
; l
= l
->next
) {
1591 xmlNodePtr win_node
;
1592 NautilusWindow
*window
;
1597 win_node
= xmlNewChild (root_node
, NULL
, "window", NULL
);
1599 xmlNewProp (win_node
, "type", NAUTILUS_IS_NAVIGATION_WINDOW (window
) ? "navigation" : "spatial");
1601 if (NAUTILUS_IS_NAVIGATION_WINDOW (window
)) { /* spatial windows store their state as file metadata */
1602 tmp
= eel_gtk_window_get_geometry_string (GTK_WINDOW (window
));
1603 xmlNewProp (win_node
, "geometry", tmp
);
1606 if (GTK_WIDGET (window
)->window
&&
1607 gdk_window_get_state (GTK_WIDGET (window
)->window
) & GDK_WINDOW_STATE_MAXIMIZED
) {
1608 xmlNewProp (win_node
, "maximized", "TRUE");
1611 if (GTK_WIDGET (window
)->window
&&
1612 gdk_window_get_state (GTK_WIDGET (window
)->window
) & GDK_WINDOW_STATE_STICKY
) {
1613 xmlNewProp (win_node
, "sticky", "TRUE");
1616 if (GTK_WIDGET (window
)->window
&&
1617 gdk_window_get_state (GTK_WIDGET (window
)->window
) & GDK_WINDOW_STATE_ABOVE
) {
1618 xmlNewProp (win_node
, "keep-above", "TRUE");
1622 tmp
= nautilus_window_get_location_uri (window
);
1623 xmlNewProp (win_node
, "location", tmp
);
1627 dir
= nautilus_get_user_directory ();
1628 filename
= g_build_filename (dir
, "saved-session-XXXXXX", NULL
);
1631 fd
= g_mkstemp (filename
);
1633 g_message ("failed to open session file %s", filename
);
1639 xmlIndentTreeOutput
= 1;
1640 ctx
= xmlSaveToFd (fd
, NULL
, XML_SAVE_FORMAT
);
1641 if (xmlSaveDoc (ctx
, doc
) < 0 ||
1642 xmlSaveFlush (ctx
) < 0) {
1643 g_message ("failed to save session to %s", filename
);
1658 nautilus_application_load_session (NautilusApplication
*application
,
1659 const char *filename
)
1664 g_assert (filename
!= NULL
);
1668 if (g_file_test (filename
, G_FILE_TEST_EXISTS
)) {
1669 xmlNodePtr root_node
;
1671 doc
= xmlReadFile (filename
, NULL
, 0);
1672 if (doc
!= NULL
&& (root_node
= xmlDocGetRootElement (doc
)) != NULL
) {
1677 for (node
= root_node
->children
; node
!= NULL
; node
= node
->next
) {
1679 if (!strcmp (node
->name
, "text")) {
1681 } else if (!strcmp (node
->name
, "history")) {
1682 xmlNodePtr bookmark_node
;
1683 gboolean emit_change
;
1685 emit_change
= FALSE
;
1687 for (bookmark_node
= node
->children
; bookmark_node
!= NULL
; bookmark_node
= bookmark_node
->next
) {
1688 if (!strcmp (bookmark_node
->name
, "text")) {
1690 } else if (!strcmp (bookmark_node
->name
, "bookmark")) {
1691 xmlChar
*name
, *icon_str
, *uri
;
1692 gboolean has_custom_name
;
1696 uri
= xmlGetProp (bookmark_node
, "uri");
1697 name
= xmlGetProp (bookmark_node
, "name");
1698 has_custom_name
= xmlHasProp (bookmark_node
, "has_custom_name") ? TRUE
: FALSE
;
1699 icon_str
= xmlGetProp (bookmark_node
, "icon");
1702 icon
= icon_from_string (icon_str
);
1704 location
= g_file_new_for_uri (uri
);
1706 emit_change
|= nautilus_add_to_history_list_no_notify (location
, name
, has_custom_name
, icon
);
1708 g_object_unref (location
);
1711 g_object_unref (icon
);
1717 g_message ("unexpected bookmark node %s while parsing %s", bookmark_node
->name
, filename
);
1724 nautilus_send_history_list_changed ();
1726 } else if (!strcmp (node
->name
, "window")) {
1727 NautilusWindow
*window
;
1728 xmlChar
*type
, *location_uri
;
1731 type
= xmlGetProp (node
, "type");
1733 g_message ("empty type node while parsing %s", filename
);
1738 location_uri
= xmlGetProp (node
, "location");
1739 if (location_uri
== NULL
) {
1740 g_message ("empty location node while parsing %s", filename
);
1746 if (!strcmp (type
, "navigation")) {
1749 window
= nautilus_application_create_navigation_window (application
, NULL
, gdk_screen_get_default ());
1751 geometry
= xmlGetProp (node
, "geometry");
1752 if (geometry
!= NULL
) {
1753 eel_gtk_window_set_initial_geometry_from_string
1754 (GTK_WINDOW (window
),
1756 NAUTILUS_WINDOW_MIN_WIDTH
,
1757 NAUTILUS_WINDOW_MIN_HEIGHT
,
1762 if (xmlHasProp (node
, "maximized")) {
1763 gtk_window_maximize (GTK_WINDOW (window
));
1765 gtk_window_unmaximize (GTK_WINDOW (window
));
1768 if (xmlHasProp (node
, "sticky")) {
1769 gtk_window_stick (GTK_WINDOW (window
));
1771 gtk_window_unstick (GTK_WINDOW (window
));
1774 if (xmlHasProp (node
, "keep-above")) {
1775 gtk_window_set_keep_above (GTK_WINDOW (window
), TRUE
);
1777 gtk_window_set_keep_above (GTK_WINDOW (window
), FALSE
);
1780 location
= g_file_new_for_uri (location_uri
);
1781 nautilus_window_open_location (window
, location
, FALSE
);
1782 g_object_unref (location
);
1783 } else if (!strcmp (type
, "spatial")) {
1784 location
= g_file_new_for_uri (location_uri
);
1785 window
= nautilus_application_present_spatial_window (application
, NULL
, NULL
, location
, gdk_screen_get_default ());
1786 g_object_unref (location
);
1788 g_message ("unknown window type \"%s\" while parsing %s", type
, filename
);
1793 xmlFree (location_uri
);
1795 g_message ("unexpected node %s while parsing %s", node
->name
, filename
);
1808 g_message ("failed to load session from %s", filename
);
1812 /* only remove file if it is regular, user-owned and the user has write access. */
1814 if (g_stat (filename
, &buf
) == 0 &&
1815 S_ISREG (buf
.st_mode
) &&
1816 (buf
.st_mode
& S_IWUSR
) &&
1817 buf
.st_uid
== geteuid()) {
1818 g_remove (filename
);
1824 save_session (GnomeClient
*client
, gint phase
, GnomeSaveStyle save_style
, gint shutdown
,
1825 GnomeInteractStyle interact_style
, gint fast
, gpointer data
)
1827 char *argv
[3] = { NULL
};
1829 argv
[0] = "nautilus";
1831 argv
[2] = nautilus_application_save_session_to_file ();
1832 if (argv
[2] != NULL
) {
1833 argv
[1] = "--load-session";
1836 gnome_client_set_restart_command (client
,
1837 G_N_ELEMENTS (argv
),
1840 if (argv
[2] != NULL
) {
1848 set_session_restart (GnomeClient
*client
, gboolean restart
)
1850 gnome_client_set_priority (client
, 40);
1852 if (restart
&& g_getenv ("NAUTILUS_DEBUG") == NULL
) {
1853 /* Don't respawn in debug mode */
1854 gnome_client_set_restart_style (client
, GNOME_RESTART_IMMEDIATELY
);
1856 gnome_client_set_restart_style (client
, GNOME_RESTART_IF_RUNNING
);
1861 update_session (gpointer callback_data
)
1863 set_session_restart (callback_data
,
1864 /* Only ever add ourselves to the session
1865 * if we have a desktop window. Prevents the
1866 * session thrashing that's seen otherwise
1868 nautilus_application_desktop_windows
!= NULL
);
1874 GnomeClient
*client
;
1876 client
= gnome_master_client ();
1878 g_signal_connect (client
, "save_yourself",
1879 G_CALLBACK (save_session
), NULL
);
1881 g_signal_connect (client
, "die",
1882 G_CALLBACK (removed_from_session
), NULL
);
1884 update_session (client
);
1887 #ifdef UGLY_HACK_TO_DETECT_KDE
1890 get_self_typed_prop (Window xwindow
,
1901 gdk_error_trap_push ();
1903 XGetWindowProperty (gdk_display
,
1907 False
, atom
, &type
, &format
, &nitems
,
1908 &bytes_after
, (guchar
**)&num
);
1910 err
= gdk_error_trap_pop ();
1911 if (err
!= Success
) {
1928 has_wm_state (Window xwindow
)
1930 return get_self_typed_prop (xwindow
,
1931 XInternAtom (gdk_display
, "WM_STATE", False
),
1936 look_for_kdesktop_recursive (Window xwindow
)
1939 Window ignored1
, ignored2
;
1941 unsigned int n_children
;
1945 /* If WM_STATE is set, this is a managed client, so look
1946 * for the class hint and end recursion. Otherwise,
1947 * this is probably just a WM frame, so keep recursing.
1949 if (has_wm_state (xwindow
)) {
1952 gdk_error_trap_push ();
1954 ch
.res_class
= NULL
;
1956 XGetClassHint (gdk_display
, xwindow
, &ch
);
1958 gdk_error_trap_pop ();
1961 XFree (ch
.res_name
);
1964 if (strcmp (ch
.res_class
, "kdesktop") == 0) {
1965 XFree (ch
.res_class
);
1969 XFree (ch
.res_class
);
1977 gdk_error_trap_push ();
1979 XQueryTree (gdk_display
,
1981 &ignored1
, &ignored2
, &children
, &n_children
);
1983 if (gdk_error_trap_pop ()) {
1988 while (i
< n_children
) {
1989 if (look_for_kdesktop_recursive (children
[i
])) {
2002 #endif /* UGLY_HACK_TO_DETECT_KDE */
2005 is_kdesktop_present (void)
2007 #ifdef UGLY_HACK_TO_DETECT_KDE
2008 /* FIXME this is a pretty lame hack, should be replaced
2009 * eventually with e.g. a requirement that desktop managers
2010 * support a manager selection, ICCCM sec 2.8
2012 return look_for_kdesktop_recursive (GDK_ROOT_WINDOW ());
2019 nautilus_application_class_init (NautilusApplicationClass
*class)
2021 BONOBO_OBJECT_CLASS (class)->destroy
= nautilus_application_destroy
;
2022 BONOBO_GENERIC_FACTORY_CLASS (class)->epv
.createObject
= create_object
;