Commit ac97cb95 authored by Christian Neumair's avatar Christian Neumair Committed by Christian Neumair

Add complete session management, remember maximization state and type of

2006-06-21  Christian Neumair  <chris@gnome-de.org>

	Add complete session management, remember maximization state and type
	of open windows, save history on quit.

	* libnautilus-private/nautilus-global-preferences.c
	* libnautilus-private/nautilus-global-preferences.h:
	Add NAUTILUS_PREFERENCES_NAVIGATION_WINDOW_MAXIMIZED setting.

	* libnautilus-private/nautilus-metadata.h:
	Add NAUTILUS_METADATA_KEY_WINDOW_MAXIMIZED key.

	* src/nautilus-application.c:
	* src/nautilus-application.h:
	Save session on session save request, add
	nautilus_application_load_session(), move
	initial navigational geometry handling to
	nautilus_application_create_navigation_window,
	maximize window if
	NAUTILUS_PREFERENCES_NAVIGATION_WINDOW_MAXIMIZED
	is set.

	* src/nautilus-main.c:
	Add "--load-session" parameter.

	* src/nautilus-shell-interface.idl:
	* src/nautilus-shell.c:
	Add load_session CORBA method.

	* src/nautilus-navigation-window.c:
	* src/nautilus-spatial-window.c:
	Save maximized state when appropriate.

	* src/nautilus-window-manage-views.c:
	Load maximized state for spatial windows,
	remove navigation window geometry handling.

	* src/nautilus-window.c:
	* src/nautilus-window-private.h:
	Add nautilus_add_to_history_list_no_notify.
parent c98d7665
2006-06-21 Christian Neumair <chris@gnome-de.org>
Add complete session management, remember maximization state and type
of open windows, save history on quit.
* libnautilus-private/nautilus-global-preferences.c
* libnautilus-private/nautilus-global-preferences.h:
Add NAUTILUS_PREFERENCES_NAVIGATION_WINDOW_MAXIMIZED setting.
* libnautilus-private/nautilus-metadata.h:
Add NAUTILUS_METADATA_KEY_WINDOW_MAXIMIZED key.
* src/nautilus-application.c:
* src/nautilus-application.h:
Save session on session save request, add
nautilus_application_load_session(), move
initial navigational geometry handling to
nautilus_application_create_navigation_window,
maximize window if
NAUTILUS_PREFERENCES_NAVIGATION_WINDOW_MAXIMIZED
is set.
* src/nautilus-main.c:
Add "--load-session" parameter.
* src/nautilus-shell-interface.idl:
* src/nautilus-shell.c:
Add load_session CORBA method.
* src/nautilus-navigation-window.c:
* src/nautilus-spatial-window.c:
Save maximized state when appropriate.
* src/nautilus-window-manage-views.c:
Load maximized state for spatial windows,
remove navigation window geometry handling.
* src/nautilus-window.c:
* src/nautilus-window-private.h:
Add nautilus_add_to_history_list_no_notify.
2006-06-16 Alexander Larsson <alexl@redhat.com>
* libnautilus-extension/nautilus-menu-provider.[ch]:
......
......@@ -384,6 +384,10 @@ static const PreferenceDefault preference_defaults[] = {
PREFERENCE_STRING,
""
},
{ NAUTILUS_PREFERENCES_NAVIGATION_WINDOW_MAXIMIZED,
PREFERENCE_BOOLEAN,
GINT_TO_POINTER (FALSE)
},
{ NAUTILUS_PREFERENCES_TREE_SHOW_ONLY_DIRECTORIES,
PREFERENCE_BOOLEAN,
GINT_TO_POINTER (TRUE)
......
......@@ -88,6 +88,7 @@ typedef enum
#define NAUTILUS_PREFERENCES_START_WITH_TOOLBAR "preferences/start_with_toolbar"
#define NAUTILUS_PREFERENCES_SIDE_PANE_VIEW "preferences/side_pane_view"
#define NAUTILUS_PREFERENCES_NAVIGATION_WINDOW_SAVED_GEOMETRY "preferences/navigation_window_saved_geometry"
#define NAUTILUS_PREFERENCES_NAVIGATION_WINDOW_MAXIMIZED "preferences/navigation_window_saved_maximized"
/* Sorting order */
#define NAUTILUS_PREFERENCES_SORT_DIRECTORIES_FIRST "preferences/sort_directories_first"
......
......@@ -55,6 +55,7 @@
#define NAUTILUS_METADATA_KEY_WINDOW_GEOMETRY "window_geometry"
#define NAUTILUS_METADATA_KEY_WINDOW_SCROLL_POSITION "window_scroll_position"
#define NAUTILUS_METADATA_KEY_WINDOW_SHOW_HIDDEN_FILES "window_show_hidden_files"
#define NAUTILUS_METADATA_KEY_WINDOW_MAXIMIZED "window_maximized"
#define NAUTILUS_METADATA_KEY_SIDEBAR_BACKGROUND_COLOR "sidebar_background_color"
#define NAUTILUS_METADATA_KEY_SIDEBAR_BACKGROUND_IMAGE "sidebar_background_tile_image"
......
......@@ -52,8 +52,11 @@
#include "nautilus-shell.h"
#include "nautilus-window-bookmarks.h"
#include "nautilus-window-private.h"
#include "nautilus-window-manage-views.h"
#include <glib/gstdio.h>
#include <bonobo/bonobo-main.h>
#include <bonobo/bonobo-object.h>
#include <eel/eel-gtk-extensions.h>
#include <eel/eel-gtk-macros.h>
#include <eel/eel-stock-dialogs.h>
#include <eel/eel-string-list.h>
......@@ -119,6 +122,8 @@ static void update_session (gpointer cal
static void init_session (void);
static gboolean is_kdesktop_present (void);
static char *save_session_to_file (void);
BONOBO_CLASS_BOILERPLATE (NautilusApplication, nautilus_application,
BonoboGenericFactory, BONOBO_TYPE_GENERIC_FACTORY)
......@@ -482,6 +487,7 @@ nautilus_application_startup (NautilusApplication *application,
gboolean browser_window,
const char *startup_id,
const char *geometry,
const char *session_to_load,
const char *urls[])
{
CORBA_Environment ev;
......@@ -649,8 +655,13 @@ nautilus_application_startup (NautilusApplication *application,
Nautilus_Shell_open_windows (shell, url_list, corba_startup_id, corba_geometry, browser_window, &ev);
CORBA_free (url_list);
} else if (!no_default_window) {
g_assert (session_to_load == NULL);
Nautilus_Shell_open_default_window (shell, corba_startup_id, corba_geometry, browser_window, &ev);
}
if (session_to_load != NULL) {
Nautilus_Shell_load_session (shell, session_to_load, &ev);
}
/* Add ourselves to the session */
init_session ();
......@@ -1163,12 +1174,30 @@ nautilus_application_present_spatial_window_with_selection (NautilusApplication
return window;
}
static gboolean
another_navigation_window_already_showing (NautilusWindow *the_window)
{
GList *list, *item;
list = nautilus_application_get_window_list ();
for (item = list; item != NULL; item = item->next) {
if (item->data != the_window &&
NAUTILUS_IS_NAVIGATION_WINDOW (item->data)) {
return TRUE;
}
}
return FALSE;
}
NautilusWindow *
nautilus_application_create_navigation_window (NautilusApplication *application,
const char *startup_id,
GdkScreen *screen)
{
NautilusWindow *window;
char *geometry_string;
gboolean maximized;
g_return_val_if_fail (NAUTILUS_IS_APPLICATION (application), NULL);
......@@ -1178,6 +1207,31 @@ nautilus_application_create_navigation_window (NautilusApplication *application,
startup_id);
#endif
maximized = eel_preferences_get_boolean
(NAUTILUS_PREFERENCES_NAVIGATION_WINDOW_MAXIMIZED);
if (maximized) {
gtk_window_maximize (GTK_WINDOW (window));
} else {
gtk_window_unmaximize (GTK_WINDOW (window));
}
geometry_string = eel_preferences_get
(NAUTILUS_PREFERENCES_NAVIGATION_WINDOW_SAVED_GEOMETRY);
if (geometry_string != NULL &&
geometry_string[0] != 0) {
/* Ignore saved window position if a window with the same
* location is already showing. That way the two windows
* wont appear at the exact same location on the screen.
*/
eel_gtk_window_set_initial_geometry_from_string
(GTK_WINDOW (window),
geometry_string,
NAUTILUS_WINDOW_MIN_WIDTH,
NAUTILUS_WINDOW_MIN_HEIGHT,
another_navigation_window_already_showing (window));
}
g_free (geometry_string);
return window;
}
......@@ -1307,41 +1361,263 @@ removed_from_session (GnomeClient *client, gpointer data)
nautilus_main_event_loop_quit ();
}
static gint
save_session (GnomeClient *client, gint phase, GnomeSaveStyle save_style, gint shutdown,
GnomeInteractStyle interact_style, gint fast, gpointer data)
static char *
save_session_to_file (void)
{
NautilusWindow *window;
xmlDocPtr doc;
xmlNodePtr root_node, history_node;
GList *l;
static char *clone_argv[] = { "nautilus", "--no-default-window" };
char **restart_argv;
int argc;
int i;
int num_windows;
num_windows = g_list_length (nautilus_application_window_list);
if (num_windows > 0) {
argc = 1 + num_windows;
i = 0;
restart_argv = g_new (char *, argc);
restart_argv[i++] = g_strdup ("nautilus");
for (l = nautilus_application_window_list; l != NULL; l = l->next) {
window = NAUTILUS_WINDOW (l->data);
restart_argv[i++] = nautilus_window_get_location (window);
char *dir, *filename;
unsigned n_processed;
doc = xmlNewDoc ("1.0");
root_node = xmlNewNode (NULL, "session");
xmlDocSetRootElement (doc, root_node);
history_node = xmlNewChild (root_node, NULL, "history", NULL);
n_processed = 0;
for (l = nautilus_get_history_list (); l != NULL; l = l->next) {
NautilusBookmark *bookmark;
xmlNodePtr bookmark_node;
char *tmp;
bookmark = l->data;
bookmark_node = xmlNewChild (history_node, NULL, "bookmark", NULL);
tmp = nautilus_bookmark_get_name (bookmark);
xmlNewProp (bookmark_node, "name", tmp);
g_free (tmp);
tmp = nautilus_bookmark_get_icon (bookmark);
xmlNewProp (bookmark_node, "icon", tmp);
g_free (tmp);
tmp = nautilus_bookmark_get_uri (bookmark);
xmlNewProp (bookmark_node, "uri", tmp);
g_free (tmp);
if (nautilus_bookmark_get_has_custom_name (bookmark)) {
xmlNewProp (bookmark_node, "has_custom_name", "TRUE");
}
gnome_client_set_restart_command (client, argc, restart_argv);
for (i = 0; i < argc; i++) {
g_free (restart_argv[i]);
if (++n_processed > 50) { /* prevent history list from growing arbitrarily large. */
break;
}
}
for (l = nautilus_application_window_list; l != NULL; l = l->next) {
xmlNodePtr win_node;
NautilusWindow *window;
char *tmp;
window = l->data;
win_node = xmlNewChild (root_node, NULL, "window", NULL);
xmlNewProp (win_node, "type", NAUTILUS_IS_NAVIGATION_WINDOW (window) ? "navigation" : "spatial");
if (NAUTILUS_IS_NAVIGATION_WINDOW (window)) { /* spatial windows store their state as file metadata */
tmp = eel_gtk_window_get_geometry_string (GTK_WINDOW (window));
xmlNewProp (win_node, "geometry", tmp);
g_free (tmp);
if (GTK_WIDGET (window)->window &&
gdk_window_get_state (GTK_WIDGET (window)->window) & GDK_WINDOW_STATE_MAXIMIZED) {
xmlNewProp (win_node, "maximized", "TRUE");
}
}
g_free (restart_argv);
tmp = nautilus_window_get_location (window);
xmlNewProp (win_node, "location", tmp);
g_free (tmp);
}
dir = nautilus_get_user_directory ();
filename = tempnam (dir, "saved-session-");
g_free (dir);
xmlIndentTreeOutput = 1;
if (filename == NULL || xmlSaveFormatFile (filename, doc, 1) < 0) {
g_message ("failed to save session to %s", filename);
g_free (filename);
filename = NULL;
}
xmlFreeDoc (doc);
return filename;
}
void
nautilus_application_load_session (NautilusApplication *application,
const char *filename)
{
xmlDocPtr doc;
gboolean bail;
g_assert (filename != NULL);
bail = TRUE;
if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
xmlNodePtr root_node;
doc = xmlReadFile (filename, NULL, 0);
if (doc != NULL && (root_node = xmlDocGetRootElement (doc)) != NULL) {
xmlNodePtr node;
bail = FALSE;
for (node = root_node->children; node != NULL; node = node->next) {
if (!strcmp (node->name, "text")) {
continue;
} else if (!strcmp (node->name, "history")) {
xmlNodePtr bookmark_node;
gboolean emit_change;
emit_change = FALSE;
for (bookmark_node = node->children; bookmark_node != NULL; bookmark_node = bookmark_node->next) {
if (!strcmp (bookmark_node->name, "text")) {
continue;
} else if (!strcmp (bookmark_node->name, "bookmark")) {
xmlChar *name, *icon, *uri;
gboolean has_custom_name;
uri = xmlGetProp (bookmark_node, "uri");
name = xmlGetProp (bookmark_node, "name");
has_custom_name = xmlHasProp (bookmark_node, "has_custom_name") ? TRUE : FALSE;
icon = xmlGetProp (bookmark_node, "icon");
emit_change |= nautilus_add_to_history_list_no_notify (uri, name, has_custom_name, icon);
xmlFree (name);
xmlFree (uri);
xmlFree (icon);
} else {
g_message ("unexpected bookmark node %s while parsing %s", bookmark_node->name, filename);
bail = TRUE;
continue;
}
}
if (emit_change) {
nautilus_send_history_list_changed ();
}
} else if (!strcmp (node->name, "window")) {
NautilusWindow *window;
xmlChar *type, *location;
type = xmlGetProp (node, "type");
if (type == NULL) {
g_message ("empty type node while parsing %s", filename);
bail = TRUE;
continue;
}
location = xmlGetProp (node, "location");
if (location == NULL) {
g_message ("empty location node while parsing %s", filename);
bail = TRUE;
xmlFree (type);
continue;
}
if (!strcmp (type, "navigation")) {
xmlChar *geometry;
window = nautilus_application_create_navigation_window (application, NULL, gdk_screen_get_default ());
geometry = xmlGetProp (node, "geometry");
if (geometry != NULL) {
eel_gtk_window_set_initial_geometry_from_string
(GTK_WINDOW (window),
geometry,
NAUTILUS_WINDOW_MIN_WIDTH,
NAUTILUS_WINDOW_MIN_HEIGHT,
FALSE);
}
xmlFree (geometry);
if (xmlHasProp (node, "maximized")) {
gtk_window_maximize (GTK_WINDOW (window));
} else {
gtk_window_unmaximize (GTK_WINDOW (window));
}
nautilus_window_open_location (window, location, FALSE);
} else if (!strcmp (type, "spatial")) {
window = nautilus_application_present_spatial_window (application, NULL, NULL, location, gdk_screen_get_default ());
} else {
g_message ("unknown window type \"%s\" while parsing %s", type, filename);
bail = TRUE;
}
xmlFree (type);
xmlFree (location);
} else {
g_message ("unexpected node %s while parsing %s", node->name, filename);
bail = TRUE;
continue;
}
}
}
if (doc != NULL) {
xmlFreeDoc (doc);
}
}
if (bail) {
g_message ("failed to load session from %s", filename);
} else {
gnome_client_set_restart_command (client,
G_N_ELEMENTS (clone_argv),
clone_argv);
char *uri;
GnomeVFSFileInfo *info;
/* only remove file if it is regular, user-owned and the user has write access. */
uri = gnome_vfs_get_uri_from_local_path (filename);
info = gnome_vfs_file_info_new ();
if (uri != NULL &&
gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_DEFAULT) == GNOME_VFS_OK &&
(info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) &&
(info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS) &&
(info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_IDS) &&
info->type == GNOME_VFS_FILE_TYPE_REGULAR &&
(info->permissions & (GNOME_VFS_PERM_USER_WRITE |
GNOME_VFS_PERM_USER_WRITE)) &&
info->uid == geteuid ()) {
g_remove (filename);
}
gnome_vfs_file_info_unref (info);
g_free (uri);
}
}
static gint
save_session (GnomeClient *client, gint phase, GnomeSaveStyle save_style, gint shutdown,
GnomeInteractStyle interact_style, gint fast, gpointer data)
{
char *argv[3] = { NULL };
argv[0] = "nautilus";
argv[2] = save_session_to_file ();
if (argv[2] != NULL) {
argv[1] = "--load-session";
}
gnome_client_set_restart_command (client,
G_N_ELEMENTS (argv),
argv);
if (argv[2] != NULL) {
g_free (argv[2]);
}
return TRUE;
}
......
......@@ -69,6 +69,7 @@ void nautilus_application_startup (NautilusApplication
gboolean browser_window,
const char *startup_id,
const char *default_geometry,
const char *session_to_load,
const char *urls[]);
GList * nautilus_application_get_window_list (void);
GList * nautilus_application_get_spatial_window_list (void);
......@@ -95,5 +96,6 @@ void nautilus_application_close_parent_windows (NautilusSpat
void nautilus_application_close_all_spatial_windows (void);
void nautilus_application_open_desktop (NautilusApplication *application);
void nautilus_application_close_desktop (void);
void nautilus_application_load_session (NautilusApplication *application,
const char *filename);
#endif /* NAUTILUS_APPLICATION_H */
......@@ -190,6 +190,7 @@ main (int argc, char *argv[])
gboolean no_desktop;
const char *startup_id;
char *startup_id_copy;
char *session_to_load;
gchar *geometry;
const gchar **remaining;
gboolean perform_self_check;
......@@ -216,6 +217,9 @@ main (int argc, char *argv[])
{ "restart", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &restart_shell,
N_("Restart Nautilus."), NULL },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &remaining, NULL, N_("[URI...]") },
{ "load-session", 'l', 0, G_OPTION_ARG_STRING, &session_to_load,
/* Translators: --no-default-window is a nautilus command line parameter, don't modify it. */
N_("Load a saved session from the specified file. Implies \"--no-default-window\"."), N_("FILENAME") },
{ NULL }
};
......@@ -243,6 +247,7 @@ main (int argc, char *argv[])
/* Get parameters. */
remaining = NULL;
geometry = NULL;
session_to_load = NULL;
kill_shell = FALSE;
no_default_window = FALSE;
no_desktop = FALSE;
......@@ -262,6 +267,10 @@ main (int argc, char *argv[])
GNOME_PARAM_HUMAN_READABLE_NAME, _("Nautilus"),
NULL);
if (session_to_load != NULL) {
no_default_window = TRUE;
}
/* Do this here so that gdk_display is initialized */
if (startup_id_copy == NULL) {
/* Create a fake one containing a timestamp that we can use */
......@@ -349,6 +358,7 @@ main (int argc, char *argv[])
browser_window,
startup_id_copy,
geometry,
session_to_load,
remaining);
g_free (startup_id_copy);
......
......@@ -560,6 +560,22 @@ nautilus_navigation_window_unrealize (GtkWidget *widget)
GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
}
static gboolean
nautilus_navigation_window_state_event (GtkWidget *widget,
GdkEventWindowState *event)
{
if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) {
eel_preferences_set_boolean (NAUTILUS_PREFERENCES_NAVIGATION_WINDOW_MAXIMIZED,
event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED);
}
if (GTK_WIDGET_CLASS (parent_class)->window_state_event != NULL) {
return GTK_WIDGET_CLASS (parent_class)->window_state_event (widget, event);
}
return FALSE;
}
static void
nautilus_navigation_window_destroy (GtkObject *object)
{
......@@ -1418,8 +1434,7 @@ nautilus_navigation_window_save_geometry (NautilusNavigationWindow *window)
g_assert (NAUTILUS_IS_WINDOW (window));
if (GTK_WIDGET(window)->window &&
!(gdk_window_get_state (GTK_WIDGET(window)->window) & GDK_WINDOW_STATE_MAXIMIZED)) {
if (GTK_WIDGET(window)->window) {
geometry_string = eel_gtk_window_get_geometry_string (GTK_WINDOW (window));
if (eel_preferences_key_is_writable (NAUTILUS_PREFERENCES_NAVIGATION_WINDOW_SAVED_GEOMETRY)) {
......@@ -1428,6 +1443,12 @@ nautilus_navigation_window_save_geometry (NautilusNavigationWindow *window)
geometry_string);
}
g_free (geometry_string);
if (eel_preferences_key_is_writable (NAUTILUS_PREFERENCES_NAVIGATION_WINDOW_MAXIMIZED)) {
eel_preferences_set_boolean
(NAUTILUS_PREFERENCES_NAVIGATION_WINDOW_MAXIMIZED,
gdk_window_get_state (GTK_WIDGET (window)->window) & GDK_WINDOW_STATE_MAXIMIZED);
}
}
}
......@@ -1462,6 +1483,7 @@ nautilus_navigation_window_class_init (NautilusNavigationWindowClass *class)
GTK_OBJECT_CLASS (class)->destroy = nautilus_navigation_window_destroy;
GTK_WIDGET_CLASS (class)->show = nautilus_navigation_window_show;
GTK_WIDGET_CLASS (class)->unrealize = nautilus_navigation_window_unrealize;
GTK_WIDGET_CLASS (class)->window_state_event = nautilus_navigation_window_state_event;
NAUTILUS_WINDOW_CLASS (class)->load_view_as_menu = real_load_view_as_menu;
NAUTILUS_WINDOW_CLASS (class)->set_content_view_widget = real_set_content_view_widget;
NAUTILUS_WINDOW_CLASS (class)->set_throbber_active = real_set_throbber_active;
......
......@@ -17,6 +17,7 @@ module Nautilus {
void stop_desktop ();
void quit ();
void restart ();
void load_session (in string filename);
};
};
......
......@@ -72,6 +72,9 @@ static void corba_open_default_window (PortableServer_Servant servant
const CORBA_char *geometry,
CORBA_boolean browser_window,
CORBA_Environment *ev);
static void corba_load_session (PortableServer_Servant servant,
const CORBA_char *filename,
CORBA_Environment *ev);
static void corba_start_desktop (PortableServer_Servant servant,
CORBA_Environment *ev);
static void corba_stop_desktop (PortableServer_Servant servant,
......@@ -93,6 +96,7 @@ nautilus_shell_class_init (NautilusShellClass *klass)
klass->epv.open_windows = corba_open_windows;
klass->epv.open_default_window = corba_open_default_window;
klass->epv.load_session = corba_load_session;
klass->epv.start_desktop = corba_start_desktop;
klass->epv.stop_desktop = corba_stop_desktop;
klass->epv.quit = corba_quit;
......@@ -204,6 +208,20 @@ corba_open_default_window (PortableServer_Servant servant,
}
}
static void
corba_load_session (PortableServer_Servant servant,
const CORBA_char *filename,