1
0
mirror of https://gitlab.gnome.org/GNOME/nautilus synced 2024-07-04 17:30:47 +00:00

Renamed nautilus.desktop to nautilus-browser.desktop (this is what it

2008-10-02  Alexander Larsson  <alexl@redhat.com>

        * Makefile.am:
        * nautilus-browser.desktop.in.in:
        * nautilus.desktop.in.in:
	Renamed nautilus.desktop to nautilus-browser.desktop
	(this is what it does, launch a browser window with no desktop)
	Created new NoDisplay nautilus.desktop file that is used
	for autostarting nautilus from gnome-session.
	
        * configure.in:
	Pull in the right cflags/libs for libegg
	Add nautilus-browser.desktop.in to output
	
        * cut-n-paste-code/libegg/Makefile.am:
        * cut-n-paste-code/libegg/eggdesktopfile.[ch]: Added.
        * cut-n-paste-code/libegg/eggsmclient-private.h: Added.
        * cut-n-paste-code/libegg/eggsmclient-xsmp.c: Added.
        * cut-n-paste-code/libegg/eggsmclient.[ch]: Added.
	Import eggsmclient from libegg.
	Save data in desktop file instead of a separate file as per the
	new gnome-session.
	
        * cut-n-paste-code/libegg/eggtreemultidnd.c:
	Minor update from libegg
	
        * src/nautilus-application.[ch]:
	Use eggsmclient for session handling instead of gnome-client.
	
        * src/nautilus-main.c:
	Don't use gnome_program, instead use eggsmsession and
	g_option_context_parse directly.
	This removes support for some internal commandline arguments
	that are not used anymore.


svn path=/trunk/; revision=14680
This commit is contained in:
Alexander Larsson 2008-10-02 14:31:52 +00:00 committed by Alexander Larsson
parent 31d3fc91d8
commit 9c068ad3e6
16 changed files with 4088 additions and 437 deletions

View File

@ -1,3 +1,38 @@
2008-10-02 Alexander Larsson <alexl@redhat.com>
* Makefile.am:
* nautilus-browser.desktop.in.in:
* nautilus.desktop.in.in:
Renamed nautilus.desktop to nautilus-browser.desktop
(this is what it does, launch a browser window with no desktop)
Created new NoDisplay nautilus.desktop file that is used
for autostarting nautilus from gnome-session.
* configure.in:
Pull in the right cflags/libs for libegg
Add nautilus-browser.desktop.in to output
* cut-n-paste-code/libegg/Makefile.am:
* cut-n-paste-code/libegg/eggdesktopfile.[ch]: Added.
* cut-n-paste-code/libegg/eggsmclient-private.h: Added.
* cut-n-paste-code/libegg/eggsmclient-xsmp.c: Added.
* cut-n-paste-code/libegg/eggsmclient.[ch]: Added.
Import eggsmclient from libegg.
Save data in desktop file instead of a separate file as per the
new gnome-session.
* cut-n-paste-code/libegg/eggtreemultidnd.c:
Minor update from libegg
* src/nautilus-application.[ch]:
Use eggsmclient for session handling instead of gnome-client.
* src/nautilus-main.c:
Don't use gnome_program, instead use eggsmsession and
g_option_context_parse directly.
This removes support for some internal commandline arguments
that are not used anymore.
2008-10-02 Cosimo Cecchi <cosimoc@gnome.org>
* libnautilus-extension/libnautilus-extension-uninstalled.pc.in:

View File

@ -10,6 +10,7 @@ desktop_in_files = \
nautilus-computer.desktop.in \
nautilus-folder-handler.desktop.in \
nautilus-file-management-properties.desktop.in \
nautilus-browser.desktop.in \
nautilus-autorun-software.desktop.in
SUBDIRS = \

View File

@ -370,9 +370,10 @@ fi
dnl ==========================================================================
dnl libegg
LIBEGG_MODULES="gtk+-2.0 libgnome-2.0"
LIBEGG_MODULES="gtk+-2.0 gthread-2.0"
LIBEGG_CFLAGS="`$PKG_CONFIG --cflags $LIBEGG_MODULES`"
AC_SUBST(LIBEGG_CFLAGS)
AC_SUBST(LIBEGG_LIBS)
dnl libnautilus-extension
LIBNAUTILUS_EXTENSION_MODULES="glib-2.0 gtk+-2.0"
@ -461,6 +462,7 @@ nautilus-file-management-properties.desktop.in
nautilus-home.desktop.in
nautilus.desktop.in
nautilus-folder-handler.desktop.in
nautilus-browser.desktop.in
nautilus-autorun-software.desktop.in
po/Makefile.in
src/Makefile

View File

@ -9,15 +9,38 @@ EGG_TREE_DND_FILES = \
eggtreemultidnd.h \
$(NULL)
EGG_SMCLIENT_FILES = \
eggdesktopfile.c \
eggdesktopfile.h \
eggsmclient.c \
eggsmclient.h \
eggsmclient-private.h \
eggsmclient-xsmp.c \
$(NULL)
libegg_la_SOURCES = \
$(EGG_TREE_DND_FILES) \
$(EGG_SMCLIENT_FILES) \
$(NULL)
libegg_la_CFLAGS = \
-DEGG_SM_CLIENT_BACKEND_XSMP \
-DG_LOG_DOMAIN=\""EggSMClient"\" \
$(LIBEGG_CFLAGS) \
$(WARNING_CFLAGS) \
$(DISABLE_DEPRECATED)
libegg_la_LIBADD = \
$(LIBEGG_LIBS) \
-lSM -lICE
EXTRA_DIST = \
update-from-egg.sh \
$(NULL)
EGG_TREE_DND_DIR = $(srcdir)/../../../libegg/libegg/treeviewutils
EGG_SMCLIENT_DIR = $(srcdir)/../../../libegg/libegg/smclient
regenerate-built-sources:
EGGFILES="$(EGG_TREE_DND_FILES)" EGGDIR="$(EGG_TREE_DND_DIR)" $(srcdir)/update-from-egg.sh
EGGFILES="$(EGG_SMCLIENT_FILES)" EGGDIR="$(EGG_SMCLIENT_DIR)" $(srcdir)/update-from-egg.sh

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,159 @@
/* eggdesktopfile.h - Freedesktop.Org Desktop Files
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING.LIB. If not,
* write to the Free Software Foundation, Inc., 59 Temple Place -
* Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __EGG_DESKTOP_FILE_H__
#define __EGG_DESKTOP_FILE_H__
#include <glib.h>
G_BEGIN_DECLS
typedef struct EggDesktopFile EggDesktopFile;
typedef enum {
EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED,
EGG_DESKTOP_FILE_TYPE_APPLICATION,
EGG_DESKTOP_FILE_TYPE_LINK,
EGG_DESKTOP_FILE_TYPE_DIRECTORY
} EggDesktopFileType;
EggDesktopFile *egg_desktop_file_new (const char *desktop_file_path,
GError **error);
EggDesktopFile *egg_desktop_file_new_from_data_dirs (const char *desktop_file_path,
GError **error);
EggDesktopFile *egg_desktop_file_new_from_dirs (const char *desktop_file_path,
const char **search_dirs,
GError **error);
EggDesktopFile *egg_desktop_file_new_from_key_file (GKeyFile *key_file,
const char *source,
GError **error);
void egg_desktop_file_free (EggDesktopFile *desktop_file);
const char *egg_desktop_file_get_source (EggDesktopFile *desktop_file) G_GNUC_PURE;
EggDesktopFileType egg_desktop_file_get_desktop_file_type (EggDesktopFile *desktop_file) G_GNUC_PURE;
const char *egg_desktop_file_get_name (EggDesktopFile *desktop_file) G_GNUC_PURE;
const char *egg_desktop_file_get_icon (EggDesktopFile *desktop_file) G_GNUC_PURE;
gboolean egg_desktop_file_can_launch (EggDesktopFile *desktop_file,
const char *desktop_environment);
gboolean egg_desktop_file_accepts_documents (EggDesktopFile *desktop_file);
gboolean egg_desktop_file_accepts_multiple (EggDesktopFile *desktop_file);
gboolean egg_desktop_file_accepts_uris (EggDesktopFile *desktop_file);
char *egg_desktop_file_parse_exec (EggDesktopFile *desktop_file,
GSList *documents,
GError **error);
gboolean egg_desktop_file_launch (EggDesktopFile *desktop_file,
GSList *documents,
GError **error,
...) G_GNUC_NULL_TERMINATED;
typedef enum {
EGG_DESKTOP_FILE_LAUNCH_CLEARENV = 1,
EGG_DESKTOP_FILE_LAUNCH_PUTENV,
EGG_DESKTOP_FILE_LAUNCH_SCREEN,
EGG_DESKTOP_FILE_LAUNCH_WORKSPACE,
EGG_DESKTOP_FILE_LAUNCH_DIRECTORY,
EGG_DESKTOP_FILE_LAUNCH_TIME,
EGG_DESKTOP_FILE_LAUNCH_FLAGS,
EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC,
EGG_DESKTOP_FILE_LAUNCH_RETURN_PID,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID
} EggDesktopFileLaunchOption;
/* Standard Keys */
#define EGG_DESKTOP_FILE_GROUP "Desktop Entry"
#define EGG_DESKTOP_FILE_KEY_TYPE "Type"
#define EGG_DESKTOP_FILE_KEY_VERSION "Version"
#define EGG_DESKTOP_FILE_KEY_NAME "Name"
#define EGG_DESKTOP_FILE_KEY_GENERIC_NAME "GenericName"
#define EGG_DESKTOP_FILE_KEY_NO_DISPLAY "NoDisplay"
#define EGG_DESKTOP_FILE_KEY_COMMENT "Comment"
#define EGG_DESKTOP_FILE_KEY_ICON "Icon"
#define EGG_DESKTOP_FILE_KEY_HIDDEN "Hidden"
#define EGG_DESKTOP_FILE_KEY_ONLY_SHOW_IN "OnlyShowIn"
#define EGG_DESKTOP_FILE_KEY_NOT_SHOW_IN "NotShowIn"
#define EGG_DESKTOP_FILE_KEY_TRY_EXEC "TryExec"
#define EGG_DESKTOP_FILE_KEY_EXEC "Exec"
#define EGG_DESKTOP_FILE_KEY_PATH "Path"
#define EGG_DESKTOP_FILE_KEY_TERMINAL "Terminal"
#define EGG_DESKTOP_FILE_KEY_MIME_TYPE "MimeType"
#define EGG_DESKTOP_FILE_KEY_CATEGORIES "Categories"
#define EGG_DESKTOP_FILE_KEY_STARTUP_NOTIFY "StartupNotify"
#define EGG_DESKTOP_FILE_KEY_STARTUP_WM_CLASS "StartupWMClass"
#define EGG_DESKTOP_FILE_KEY_URL "URL"
/* Accessors */
gboolean egg_desktop_file_has_key (EggDesktopFile *desktop_file,
const char *key,
GError **error);
char *egg_desktop_file_get_string (EggDesktopFile *desktop_file,
const char *key,
GError **error) G_GNUC_MALLOC;
char *egg_desktop_file_get_locale_string (EggDesktopFile *desktop_file,
const char *key,
const char *locale,
GError **error) G_GNUC_MALLOC;
gboolean egg_desktop_file_get_boolean (EggDesktopFile *desktop_file,
const char *key,
GError **error);
double egg_desktop_file_get_numeric (EggDesktopFile *desktop_file,
const char *key,
GError **error);
char **egg_desktop_file_get_string_list (EggDesktopFile *desktop_file,
const char *key,
gsize *length,
GError **error) G_GNUC_MALLOC;
char **egg_desktop_file_get_locale_string_list (EggDesktopFile *desktop_file,
const char *key,
const char *locale,
gsize *length,
GError **error) G_GNUC_MALLOC;
/* Errors */
#define EGG_DESKTOP_FILE_ERROR egg_desktop_file_error_quark()
GQuark egg_desktop_file_error_quark (void);
typedef enum {
EGG_DESKTOP_FILE_ERROR_INVALID,
EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
EGG_DESKTOP_FILE_ERROR_UNRECOGNIZED_OPTION
} EggDesktopFileError;
/* Global application desktop file */
void egg_set_desktop_file (const char *desktop_file_path);
EggDesktopFile *egg_get_desktop_file (void);
G_END_DECLS
#endif /* __EGG_DESKTOP_FILE_H__ */

View File

@ -0,0 +1,53 @@
/* eggsmclient-private.h
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __EGG_SM_CLIENT_PRIVATE_H__
#define __EGG_SM_CLIENT_PRIVATE_H__
#include <gdkconfig.h>
#include "eggsmclient.h"
G_BEGIN_DECLS
GKeyFile *egg_sm_client_save_state (EggSMClient *client);
void egg_sm_client_quit_requested (EggSMClient *client);
void egg_sm_client_quit_cancelled (EggSMClient *client);
void egg_sm_client_quit (EggSMClient *client);
#if defined (GDK_WINDOWING_X11)
# ifdef EGG_SM_CLIENT_BACKEND_XSMP
GType egg_sm_client_xsmp_get_type (void);
EggSMClient *egg_sm_client_xsmp_new (void);
# endif
# ifdef EGG_SM_CLIENT_BACKEND_DBUS
GType egg_sm_client_dbus_get_type (void);
EggSMClient *egg_sm_client_dbus_new (void);
# endif
#elif defined (GDK_WINDOWING_WIN32)
GType egg_sm_client_win32_get_type (void);
EggSMClient *egg_sm_client_win32_new (void);
#elif defined (GDK_WINDOWING_QUARTZ)
GType egg_sm_client_osx_get_type (void);
EggSMClient *egg_sm_client_osx_new (void);
#endif
G_END_DECLS
#endif /* __EGG_SM_CLIENT_PRIVATE_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,578 @@
/*
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <glib/gi18n.h>
#include "eggsmclient.h"
#include "eggsmclient-private.h"
static void egg_sm_client_debug_handler (const char *log_domain,
GLogLevelFlags log_level,
const char *message,
gpointer user_data);
enum {
SAVE_STATE,
QUIT_REQUESTED,
QUIT_CANCELLED,
QUIT,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
struct _EggSMClientPrivate {
GKeyFile *state_file;
};
#define EGG_SM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_TYPE_SM_CLIENT, EggSMClientPrivate))
G_DEFINE_TYPE (EggSMClient, egg_sm_client, G_TYPE_OBJECT)
static EggSMClient *global_client;
static EggSMClientMode global_client_mode = EGG_SM_CLIENT_MODE_NORMAL;
static void
egg_sm_client_init (EggSMClient *client)
{
;
}
static void
egg_sm_client_class_init (EggSMClientClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (klass, sizeof (EggSMClientPrivate));
/**
* EggSMClient::save_state:
* @client: the client
* @state_file: a #GKeyFile to save state information into
*
* Emitted when the session manager has requested that the
* application save information about its current state. The
* application should save its state into @state_file, and then the
* session manager may then restart the application in a future
* session and tell it to initialize itself from that state.
*
* You should not save any data into @state_file's "start group"
* (ie, the %NULL group). Instead, applications should save their
* data into groups with names that start with the application name,
* and libraries that connect to this signal should save their data
* into groups with names that start with the library name.
*
* Alternatively, rather than (or in addition to) using @state_file,
* the application can save its state by calling
* egg_sm_client_set_restart_command() during the processing of this
* signal (eg, to include a list of files to open).
**/
signals[SAVE_STATE] =
g_signal_new ("save_state",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, save_state),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE,
1, G_TYPE_POINTER);
/**
* EggSMClient::quit_requested:
* @client: the client
*
* Emitted when the session manager requests that the application
* exit (generally because the user is logging out). The application
* should decide whether or not it is willing to quit (perhaps after
* asking the user what to do with documents that have unsaved
* changes) and then call egg_sm_client_will_quit(), passing %TRUE
* or %FALSE to give its answer to the session manager. (It does not
* need to give an answer before returning from the signal handler;
* it can interact with the user asynchronously and then give its
* answer later on.) If the application does not connect to this
* signal, then #EggSMClient will automatically return %TRUE on its
* behalf.
*
* The application should not save its session state as part of
* handling this signal; if the user has requested that the session
* be saved when logging out, then ::save_state will be emitted
* separately.
*
* If the application agrees to quit, it should then wait for either
* the ::quit_cancelled or ::quit signals to be emitted.
**/
signals[QUIT_REQUESTED] =
g_signal_new ("quit_requested",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, quit_requested),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
/**
* EggSMClient::quit_cancelled:
* @client: the client
*
* Emitted when the session manager decides to cancel a logout after
* the application has already agreed to quit. After receiving this
* signal, the application can go back to what it was doing before
* receiving the ::quit_requested signal.
**/
signals[QUIT_CANCELLED] =
g_signal_new ("quit_cancelled",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, quit_cancelled),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
/**
* EggSMClient::quit:
* @client: the client
*
* Emitted when the session manager wants the application to quit
* (generally because the user is logging out). The application
* should exit as soon as possible after receiving this signal; if
* it does not, the session manager may choose to forcibly kill it.
*
* Normally a GUI application would only be sent a ::quit if it
* agreed to quit in response to a ::quit_requested signal. However,
* this is not guaranteed; in some situations the session manager
* may decide to end the session without giving applications a
* chance to object.
**/
signals[QUIT] =
g_signal_new ("quit",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, quit),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
}
static gboolean sm_client_disable = FALSE;
static char *sm_client_state_file = NULL;
static char *sm_client_id = NULL;
static GOptionEntry entries[] = {
{ "sm-client-disable", 0, 0,
G_OPTION_ARG_NONE, &sm_client_disable,
N_("Disable connection to session manager"), NULL },
{ "sm-client-state-file", 0, 0,
G_OPTION_ARG_STRING, &sm_client_state_file,
N_("Specify file containing saved configuration"), N_("FILE") },
{ "sm-client-id", 0, 0,
G_OPTION_ARG_STRING, &sm_client_id,
N_("Specify session management ID"), N_("ID") },
{ NULL }
};
static gboolean
sm_client_post_parse_func (GOptionContext *context,
GOptionGroup *group,
gpointer data,
GError **error)
{
EggSMClient *client = egg_sm_client_get ();
if (sm_client_id == NULL)
{
const gchar *desktop_autostart_id;
desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
if (desktop_autostart_id != NULL)
sm_client_id = g_strdup (desktop_autostart_id);
}
/* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to
* use the same client id. */
g_unsetenv ("DESKTOP_AUTOSTART_ID");
if (EGG_SM_CLIENT_GET_CLASS (client)->startup)
EGG_SM_CLIENT_GET_CLASS (client)->startup (client, sm_client_id);
return TRUE;
}
/**
* egg_sm_client_get_option_group:
*
* Creates a %GOptionGroup containing the session-management-related
* options. You should add this group to the application's
* %GOptionContext if you want to use #EggSMClient.
*
* Return value: the %GOptionGroup
**/
GOptionGroup *
egg_sm_client_get_option_group (void)
{
GOptionGroup *group;
/* Use our own debug handler for the "EggSMClient" domain. */
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
egg_sm_client_debug_handler, NULL);
group = g_option_group_new ("sm-client",
_("Session Management Options"),
_("Show Session Management options"),
NULL, NULL);
g_option_group_add_entries (group, entries);
g_option_group_set_parse_hooks (group, NULL, sm_client_post_parse_func);
return group;
}
/**
* egg_sm_client_set_mode:
* @mode: an #EggSMClient mode
*
* Sets the "mode" of #EggSMClient as follows:
*
* %EGG_SM_CLIENT_MODE_DISABLED: Session management is completely
* disabled. The application will not even connect to the session
* manager. (egg_sm_client_get() will still return an #EggSMClient,
* but it will just be a dummy object.)
*
* %EGG_SM_CLIENT_MODE_NO_RESTART: The application will connect to
* the session manager (and thus will receive notification when the
* user is logging out, etc), but will request to not be
* automatically restarted with saved state in future sessions.
*
* %EGG_SM_CLIENT_MODE_NORMAL: The default. #EggSMClient will
* function normally.
*
* This must be called before the application's main loop begins.
**/
void
egg_sm_client_set_mode (EggSMClientMode mode)
{
global_client_mode = mode;
}
/**
* egg_sm_client_get_mode:
*
* Gets the global #EggSMClientMode. See egg_sm_client_set_mode()
* for details.
*
* Return value: the global #EggSMClientMode
**/
EggSMClientMode
egg_sm_client_get_mode (void)
{
return global_client_mode;
}
/**
* egg_sm_client_get:
*
* Returns the master #EggSMClient for the application.
*
* On platforms that support saved sessions (ie, POSIX/X11), the
* application will only request to be restarted by the session
* manager if you call egg_set_desktop_file() to set an application
* desktop file. In particular, if the desktop file contains the key
* "X
*
* Return value: the master #EggSMClient.
**/
EggSMClient *
egg_sm_client_get (void)
{
if (!global_client)
{
if (global_client_mode != EGG_SM_CLIENT_MODE_DISABLED &&
!sm_client_disable)
{
#if defined (GDK_WINDOWING_WIN32)
global_client = egg_sm_client_win32_new ();
#elif defined (GDK_WINDOWING_QUARTZ)
global_client = egg_sm_client_osx_new ();
#else
/* If both D-Bus and XSMP are compiled in, try D-Bus first
* and fall back to XSMP if D-Bus session management isn't
* available.
*/
# ifdef EGG_SM_CLIENT_BACKEND_DBUS
global_client = egg_sm_client_dbus_new ();
# endif
# ifdef EGG_SM_CLIENT_BACKEND_XSMP
if (!global_client)
global_client = egg_sm_client_xsmp_new ();
# endif
#endif
}
/* Fallback: create a dummy client, so that callers don't have
* to worry about a %NULL return value.
*/
if (!global_client)
global_client = g_object_new (EGG_TYPE_SM_CLIENT, NULL);
}
return global_client;
}
/**
* egg_sm_client_is_resumed:
* @client: the client
*
* Checks whether or not the current session has been resumed from
* a previous saved session. If so, the application should call
* egg_sm_client_get_state_file() and restore its state from the
* returned #GKeyFile.
*
* Return value: %TRUE if the session has been resumed
**/
gboolean
egg_sm_client_is_resumed (EggSMClient *client)
{
g_return_val_if_fail (client == global_client, FALSE);
return sm_client_state_file != NULL;
}
/**
* egg_sm_client_get_state_file:
* @client: the client
*
* If the application was resumed by the session manager, this will
* return the #GKeyFile containing its state from the previous
* session.
*
* Note that other libraries and #EggSMClient itself may also store
* state in the key file, so if you call egg_sm_client_get_groups(),
* on it, the return value will likely include groups that you did not
* put there yourself. (It is also not guaranteed that the first
* group created by the application will still be the "start group"
* when it is resumed.)
*
* Return value: the #GKeyFile containing the application's earlier
* state, or %NULL on error. You should not free this key file; it
* is owned by @client.
**/
GKeyFile *
egg_sm_client_get_state_file (EggSMClient *client)
{
EggSMClientPrivate *priv = EGG_SM_CLIENT_GET_PRIVATE (client);
char *state_file_path;
GError *err = NULL;
g_return_val_if_fail (client == global_client, NULL);
if (!sm_client_state_file)
return NULL;
if (priv->state_file)
return priv->state_file;
if (!strncmp (sm_client_state_file, "file://", 7))
state_file_path = g_filename_from_uri (sm_client_state_file, NULL, NULL);
else
state_file_path = g_strdup (sm_client_state_file);
priv->state_file = g_key_file_new ();
if (!g_key_file_load_from_file (priv->state_file, state_file_path, 0, &err))
{
g_warning ("Could not load SM state file '%s': %s",
sm_client_state_file, err->message);
g_clear_error (&err);
g_key_file_free (priv->state_file);
priv->state_file = NULL;
}
g_free (state_file_path);
return priv->state_file;
}
/**
* egg_sm_client_set_restart_command:
* @client: the client
* @argc: the length of @argv
* @argv: argument vector
*
* Sets the command used to restart @client if it does not have a
* .desktop file that can be used to find its restart command.
*
* This can also be used when handling the ::save_state signal, to
* save the current state via an updated command line. (Eg, providing
* a list of filenames to open when the application is resumed.)
**/
void
egg_sm_client_set_restart_command (EggSMClient *client,
int argc,
const char **argv)
{
g_return_if_fail (EGG_IS_SM_CLIENT (client));
if (EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command)
EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command (client, argc, argv);
}
/**
* egg_sm_client_will_quit:
* @client: the client
* @will_quit: whether or not the application is willing to quit
*
* This MUST be called in response to the ::quit_requested signal, to
* indicate whether or not the application is willing to quit. The
* application may call it either directly from the signal handler, or
* at some later point (eg, after asynchronously interacting with the
* user).
*
* If the application does not connect to ::quit_requested,
* #EggSMClient will call this method on its behalf (passing %TRUE
* for @will_quit).
*
* After calling this method, the application should wait to receive
* either ::quit_cancelled or ::quit.
**/
void
egg_sm_client_will_quit (EggSMClient *client,
gboolean will_quit)
{
g_return_if_fail (EGG_IS_SM_CLIENT (client));
if (EGG_SM_CLIENT_GET_CLASS (client)->will_quit)
EGG_SM_CLIENT_GET_CLASS (client)->will_quit (client, will_quit);
}
/**
* egg_sm_client_end_session:
* @style: a hint at how to end the session
* @request_confirmation: whether or not the user should get a chance
* to confirm the action
*
* Requests that the session manager end the current session. @style
* indicates how the session should be ended, and
* @request_confirmation indicates whether or not the user should be
* given a chance to confirm the logout/reboot/shutdown. Both of these
* flags are merely hints though; the session manager may choose to
* ignore them.
*
* Return value: %TRUE if the request was sent; %FALSE if it could not
* be (eg, because it could not connect to the session manager).
**/
gboolean
egg_sm_client_end_session (EggSMClientEndStyle style,
gboolean request_confirmation)
{
EggSMClient *client = egg_sm_client_get ();
g_return_val_if_fail (EGG_IS_SM_CLIENT (client), FALSE);
if (EGG_SM_CLIENT_GET_CLASS (client)->end_session)
{
return EGG_SM_CLIENT_GET_CLASS (client)->end_session (client, style,
request_confirmation);
}
else
return FALSE;
}
/* Signal-emitting callbacks from platform-specific code */
GKeyFile *
egg_sm_client_save_state (EggSMClient *client)
{
GKeyFile *state_file;
char *group;
g_return_val_if_fail (client == global_client, NULL);
state_file = g_key_file_new ();
g_debug ("Emitting save_state");
g_signal_emit (client, signals[SAVE_STATE], 0, state_file);
g_debug ("Done emitting save_state");
group = g_key_file_get_start_group (state_file);
if (group)
{
g_free (group);
return state_file;
}
else
{
g_key_file_free (state_file);
return NULL;
}
}
void
egg_sm_client_quit_requested (EggSMClient *client)
{
g_return_if_fail (client == global_client);
if (!g_signal_has_handler_pending (client, signals[QUIT_REQUESTED], 0, FALSE))
{
g_debug ("Not emitting quit_requested because no one is listening");
egg_sm_client_will_quit (client, TRUE);
return;
}
g_debug ("Emitting quit_requested");
g_signal_emit (client, signals[QUIT_REQUESTED], 0);
g_debug ("Done emitting quit_requested");
}
void
egg_sm_client_quit_cancelled (EggSMClient *client)
{
g_return_if_fail (client == global_client);
g_debug ("Emitting quit_cancelled");
g_signal_emit (client, signals[QUIT_CANCELLED], 0);
g_debug ("Done emitting quit_cancelled");
}
void
egg_sm_client_quit (EggSMClient *client)
{
g_return_if_fail (client == global_client);
g_debug ("Emitting quit");
g_signal_emit (client, signals[QUIT], 0);
g_debug ("Done emitting quit");
/* FIXME: should we just call gtk_main_quit() here? */
}
static void
egg_sm_client_debug_handler (const char *log_domain,
GLogLevelFlags log_level,
const char *message,
gpointer user_data)
{
static int debug = -1;
if (debug < 0)
debug = (g_getenv ("EGG_SM_CLIENT_DEBUG") != NULL);
if (debug)
g_log_default_handler (log_domain, log_level, message, NULL);
}

View File

@ -0,0 +1,117 @@
/* eggsmclient.h
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __EGG_SM_CLIENT_H__
#define __EGG_SM_CLIENT_H__
#include <glib-object.h>
G_BEGIN_DECLS
#define EGG_TYPE_SM_CLIENT (egg_sm_client_get_type ())
#define EGG_SM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT, EggSMClient))
#define EGG_SM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT, EggSMClientClass))
#define EGG_IS_SM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT))
#define EGG_IS_SM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT))
#define EGG_SM_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT, EggSMClientClass))
typedef struct _EggSMClient EggSMClient;
typedef struct _EggSMClientClass EggSMClientClass;
typedef struct _EggSMClientPrivate EggSMClientPrivate;
typedef enum {
EGG_SM_CLIENT_END_SESSION_DEFAULT,
EGG_SM_CLIENT_LOGOUT,
EGG_SM_CLIENT_REBOOT,
EGG_SM_CLIENT_SHUTDOWN
} EggSMClientEndStyle;
typedef enum {
EGG_SM_CLIENT_MODE_DISABLED,
EGG_SM_CLIENT_MODE_NO_RESTART,
EGG_SM_CLIENT_MODE_NORMAL
} EggSMClientMode;
struct _EggSMClient
{
GObject parent;
};
struct _EggSMClientClass
{
GObjectClass parent_class;
/* signals */
void (*save_state) (EggSMClient *client,
GKeyFile *state_file);
void (*quit_requested) (EggSMClient *client);
void (*quit_cancelled) (EggSMClient *client);
void (*quit) (EggSMClient *client);
/* virtual methods */
void (*startup) (EggSMClient *client,
const char *client_id);
void (*set_restart_command) (EggSMClient *client,
int argc,
const char **argv);
void (*will_quit) (EggSMClient *client,
gboolean will_quit);
gboolean (*end_session) (EggSMClient *client,
EggSMClientEndStyle style,
gboolean request_confirmation);
/* Padding for future expansion */
void (*_egg_reserved1) (void);
void (*_egg_reserved2) (void);
void (*_egg_reserved3) (void);
void (*_egg_reserved4) (void);
};
GType egg_sm_client_get_type (void) G_GNUC_CONST;
GOptionGroup *egg_sm_client_get_option_group (void);
/* Initialization */
void egg_sm_client_set_mode (EggSMClientMode mode);
EggSMClientMode egg_sm_client_get_mode (void);
EggSMClient *egg_sm_client_get (void);
/* Resuming a saved session */
gboolean egg_sm_client_is_resumed (EggSMClient *client);
GKeyFile *egg_sm_client_get_state_file (EggSMClient *client);
/* Alternate means of saving state */
void egg_sm_client_set_restart_command (EggSMClient *client,
int argc,
const char **argv);
/* Handling "quit_requested" signal */
void egg_sm_client_will_quit (EggSMClient *client,
gboolean will_quit);
/* Initiate a logout/reboot/shutdown */
gboolean egg_sm_client_end_session (EggSMClientEndStyle style,
gboolean request_confirmation);
G_END_DECLS
#endif /* __EGG_SM_CLIENT_H__ */

View File

@ -59,7 +59,7 @@ egg_tree_multi_drag_source_get_type (void)
if (!our_type)
{
const GTypeInfo our_info =
static const GTypeInfo our_info =
{
sizeof (EggTreeMultiDragSourceIface), /* class_size */
NULL, /* base_init */

View File

@ -0,0 +1,16 @@
[Desktop Entry]
Encoding=UTF-8
_Name=File Browser
_Comment=Browse the file system with the file manager
TryExec=nautilus
Exec=nautilus --no-desktop --browser %U
Icon=system-file-manager
Terminal=false
StartupNotify=true
Type=Application
Categories=GNOME;GTK;System;Utility;Core;
OnlyShowIn=GNOME;
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=nautilus
X-GNOME-Bugzilla-Component=general
X-GNOME-Bugzilla-Version=@VERSION@

View File

@ -1,19 +1,17 @@
[Desktop Entry]
Encoding=UTF-8
_Name=File Browser
_Comment=Browse the file system with the file manager
TryExec=nautilus
Exec=nautilus --no-desktop --browser %U
_Name=File Manager
Exec=nautilus
Icon=system-file-manager
Terminal=false
StartupNotify=true
Type=Application
Categories=GNOME;GTK;System;Utility;Core;
StartupNotify=true
NoDisplay=true
OnlyShowIn=GNOME;
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=nautilus
X-GNOME-Bugzilla-Component=general
X-GNOME-Bugzilla-Version=@VERSION@
X-GNOME-Autostart-Phase=Desktop
X-GNOME-Provides=filemanager
X-GNOME-Autostart-Notify=true
X-GNOME-Provides=filemanager

View File

@ -82,11 +82,9 @@ enum
{
COMMAND_0, /* unused: 0 is an invalid command */
COMMAND_RESTART,
COMMAND_START_DESKTOP,
COMMAND_STOP_DESKTOP,
COMMAND_OPEN_BROWSER,
COMMAND_LOAD_SESSION
};
/* Needed for the is_kdesktop_present check */
@ -124,9 +122,9 @@ static void drive_connected_callback (GVolumeMonitor *mo
NautilusApplication *application);
static void drive_listen_for_eject_button (GDrive *drive,
NautilusApplication *application);
static void update_session (gpointer callback_data);
static void init_session (void);
static gboolean is_kdesktop_present (void);
static void nautilus_application_load_session (NautilusApplication *application);
static char * nautilus_application_get_session_data (void);
G_DEFINE_TYPE (NautilusApplication, nautilus_application, G_TYPE_OBJECT);
@ -191,31 +189,6 @@ _unique_message_data_get_geometry_and_uris (UniqueMessageData *message_data,
return result;
}
/* This is a hack, because there is no unique_message_data_get()... */
typedef struct {
guchar *data;
gint length;
/* etc... */
} UniqueMessageDataInternal;
static char *
_unique_message_data_get_filename (UniqueMessageData *message_data)
{
UniqueMessageDataInternal *internal;
internal = (UniqueMessageDataInternal *)message_data;
return g_strndup (internal->data, internal->length);
}
static void
_unique_message_data_set_filename (UniqueMessageData *message_data,
const char *filename)
{
unique_message_data_set (message_data, filename, strlen (filename));
}
GList *
nautilus_application_get_window_list (void)
{
@ -275,6 +248,30 @@ automount_all_volumes (NautilusApplication *application)
}
static void
smclient_save_state_cb (EggSMClient *client,
GKeyFile *state_file,
NautilusApplication *application)
{
char *data;
data = nautilus_application_get_session_data ();
if (data) {
g_key_file_set_string (state_file,
"Nautilus",
"documents",
data);
}
g_free (data);
}
static void
smclient_quit_cb (EggSMClient *client,
NautilusApplication *application)
{
nautilus_main_event_loop_quit (TRUE);
}
static void
nautilus_application_init (NautilusApplication *application)
{
@ -282,12 +279,20 @@ nautilus_application_init (NautilusApplication *application)
application->undo_manager = nautilus_undo_manager_new ();
application->unique_app = unique_app_new_with_commands ("org.gnome.Nautilus", NULL,
"restart", COMMAND_RESTART,
"start_desktop", COMMAND_START_DESKTOP,
"stop_desktop", COMMAND_STOP_DESKTOP,
"open_browser", COMMAND_OPEN_BROWSER,
"load_session", COMMAND_LOAD_SESSION,
NULL);
application->smclient = egg_sm_client_get ();
g_signal_connect (application->smclient, "save_state",
G_CALLBACK (smclient_save_state_cb),
application);
g_signal_connect (application->smclient, "quit",
G_CALLBACK (smclient_quit_cb),
application);
/* TODO: Should connect to quit_requested and block logout on active transfer? */
/* register views */
fm_icon_view_register ();
@ -326,6 +331,7 @@ nautilus_application_finalize (GObject *object)
nautilus_bookmarks_exiting ();
g_object_unref (application->undo_manager);
g_object_unref (application->smclient);
if (application->volume_monitor) {
g_object_unref (application->volume_monitor);
@ -627,7 +633,6 @@ message_received_cb (UniqueApp *unique_app,
{
NautilusApplication *application;
UniqueResponse res;
char *filename;
char **uris;
char *geometry;
@ -639,16 +644,6 @@ message_received_cb (UniqueApp *unique_app,
res = UNIQUE_RESPONSE_OK;
nautilus_main_event_loop_quit (TRUE);
break;
case COMMAND_RESTART:
filename = nautilus_application_save_session_to_file ();
if (filename != NULL) {
nautilus_main_event_loop_quit (TRUE);
g_setenv ("_NAUTILUS_RESTART_SESSION_FILENAME", filename, 1);
g_free (filename);
} else {
g_message ("Could not save session. Not restarting.");
}
break;
case UNIQUE_OPEN:
case COMMAND_OPEN_BROWSER:
@ -667,11 +662,6 @@ message_received_cb (UniqueApp *unique_app,
case COMMAND_STOP_DESKTOP:
nautilus_application_close_desktop ();
break;
case COMMAND_LOAD_SESSION:
filename = _unique_message_data_get_filename (message);
nautilus_application_load_session (application, filename);
g_free (filename);
break;
default:
res = UNIQUE_RESPONSE_PASSTHROUGH;
break;
@ -683,12 +673,10 @@ message_received_cb (UniqueApp *unique_app,
void
nautilus_application_startup (NautilusApplication *application,
gboolean kill_shell,
gboolean restart_shell,
gboolean no_default_window,
gboolean no_desktop,
gboolean browser_window,
const char *geometry,
const char *session_to_load,
char **urls)
{
UniqueMessageData *message;
@ -707,12 +695,6 @@ nautilus_application_startup (NautilusApplication *application,
unique_app_send_message (application->unique_app,
UNIQUE_CLOSE, NULL);
}
} else if (restart_shell) {
if (unique_app_is_running (application->unique_app)) {
unique_app_send_message (application->unique_app,
COMMAND_RESTART, NULL);
}
} else {
/* If KDE desktop is running, then force no_desktop */
@ -749,10 +731,6 @@ nautilus_application_startup (NautilusApplication *application,
/* Create the other windows. */
if (urls != NULL || !no_default_window) {
if (urls == NULL) {
g_assert (session_to_load == NULL);
}
if (unique_app_is_running (application->unique_app)) {
message = unique_message_data_new ();
_unique_message_data_set_geometry_and_uris (message, geometry, urls);
@ -772,20 +750,8 @@ nautilus_application_startup (NautilusApplication *application,
}
}
if (session_to_load != NULL) {
if (unique_app_is_running (application->unique_app)) {
message = unique_message_data_new ();
_unique_message_data_set_filename (message, session_to_load);
unique_app_send_message (application->unique_app,
COMMAND_LOAD_SESSION, message);
unique_message_data_free (message);
} else {
nautilus_application_load_session (application, session_to_load);
}
}
/* Add ourselves to the session */
init_session ();
/* Load session info if availible */
nautilus_application_load_session (application);
}
}
@ -909,9 +875,6 @@ nautilus_application_open_desktop (NautilusApplication *application)
{
if (nautilus_application_desktop_windows == NULL) {
nautilus_application_create_desktop_windows (application);
/* Make sure we update the session when the desktop is created */
update_session (gnome_master_client ());
}
}
@ -923,9 +886,6 @@ nautilus_application_close_desktop (void)
(GFunc) gtk_widget_destroy, NULL);
g_list_free (nautilus_application_desktop_windows);
nautilus_application_desktop_windows = NULL;
/* Make sure we update the session when the desktop goes away */
update_session (gnome_master_client ());
}
}
@ -1524,12 +1484,6 @@ mount_removed_callback (GVolumeMonitor *monitor,
g_list_free (close_list);
}
static void
removed_from_session (GnomeClient *client, gpointer data)
{
nautilus_main_event_loop_quit (FALSE);
}
static char *
icon_to_string (GIcon *icon)
{
@ -1569,16 +1523,16 @@ icon_from_string (const char *string)
return NULL;
}
char *
nautilus_application_save_session_to_file (void)
static char *
nautilus_application_get_session_data (void)
{
xmlDocPtr doc;
xmlNodePtr root_node, history_node;
GList *l;
char *dir, *filename;
char *data;
unsigned n_processed;
int fd;
xmlSaveCtxtPtr ctx;
xmlBufferPtr buffer;
doc = xmlNewDoc ("1.0");
@ -1683,294 +1637,221 @@ nautilus_application_save_session_to_file (void)
g_list_free (slots);
}
dir = nautilus_get_user_directory ();
filename = g_build_filename (dir, "saved-session-XXXXXX", NULL);
g_free (dir);
fd = g_mkstemp (filename);
if (fd < 0) {
g_message ("failed to open session file %s", filename);
g_free (filename);
filename = NULL;
goto out;
}
buffer = xmlBufferCreate ();
xmlIndentTreeOutput = 1;
ctx = xmlSaveToFd (fd, NULL, XML_SAVE_FORMAT);
ctx = xmlSaveToBuffer (buffer, "UTF-8", XML_SAVE_FORMAT);
if (xmlSaveDoc (ctx, doc) < 0 ||
xmlSaveFlush (ctx) < 0) {
g_message ("failed to save session to %s", filename);
g_free (filename);
filename = NULL;
g_message ("failed to save session");
}
xmlSaveClose(ctx);
close (fd);
data = g_strndup (buffer->content, buffer->use);
xmlBufferFree (buffer);
out:
xmlFreeDoc (doc);
return filename;
return data;
}
void
nautilus_application_load_session (NautilusApplication *application,
const char *filename)
nautilus_application_load_session (NautilusApplication *application)
{
xmlDocPtr doc;
gboolean bail;
xmlNodePtr root_node;
GKeyFile *state_file;
char *data;
g_assert (filename != NULL);
if (!egg_sm_client_is_resumed (application->smclient)) {
return;
}
state_file = egg_sm_client_get_state_file (application->smclient);
if (!state_file) {
return;
}
data = g_key_file_get_string (state_file,
"Nautilus",
"sessiondata",
NULL);
if (data == NULL) {
return;
}
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_str, *uri;
gboolean has_custom_name;
GIcon *icon;
GFile *location;
uri = xmlGetProp (bookmark_node, "uri");
name = xmlGetProp (bookmark_node, "name");
has_custom_name = xmlHasProp (bookmark_node, "has_custom_name") ? TRUE : FALSE;
icon_str = xmlGetProp (bookmark_node, "icon");
icon = NULL;
if (icon_str) {
icon = icon_from_string (icon_str);
}
location = g_file_new_for_uri (uri);
emit_change |= nautilus_add_to_history_list_no_notify (location, name, has_custom_name, icon);
g_object_unref (location);
if (icon) {
g_object_unref (icon);
}
xmlFree (name);
xmlFree (uri);
xmlFree (icon_str);
} 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_uri, *slot_uri;
xmlNodePtr slot_node;
GFile *location;
int i;
type = xmlGetProp (node, "type");
if (type == NULL) {
g_message ("empty type node while parsing %s", filename);
bail = TRUE;
doc = xmlReadMemory (data, strlen (data), NULL, "UTF-8", 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;
}
location_uri = xmlGetProp (node, "location");
if (location_uri == 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);
} else if (!strcmp (bookmark_node->name, "bookmark")) {
xmlChar *name, *icon_str, *uri;
gboolean has_custom_name;
GIcon *icon;
GFile *location;
uri = xmlGetProp (bookmark_node, "uri");
name = xmlGetProp (bookmark_node, "name");
has_custom_name = xmlHasProp (bookmark_node, "has_custom_name") ? TRUE : FALSE;
icon_str = xmlGetProp (bookmark_node, "icon");
icon = NULL;
if (icon_str) {
icon = icon_from_string (icon_str);
}
xmlFree (geometry);
if (xmlHasProp (node, "maximized")) {
gtk_window_maximize (GTK_WINDOW (window));
} else {
gtk_window_unmaximize (GTK_WINDOW (window));
}
if (xmlHasProp (node, "sticky")) {
gtk_window_stick (GTK_WINDOW (window));
} else {
gtk_window_unstick (GTK_WINDOW (window));
}
if (xmlHasProp (node, "keep-above")) {
gtk_window_set_keep_above (GTK_WINDOW (window), TRUE);
} else {
gtk_window_set_keep_above (GTK_WINDOW (window), FALSE);
}
for (i = 0, slot_node = node->children; slot_node != NULL; slot_node = slot_node->next) {
if (!strcmp (slot_node->name, "slot")) {
slot_uri = xmlGetProp (slot_node, "location");
if (slot_uri != NULL) {
NautilusWindowSlot *slot;
if (i == 0) {
slot = window->details->active_slot;
} else {
slot = nautilus_window_open_slot (window, NAUTILUS_WINDOW_OPEN_SLOT_APPEND);
}
location = g_file_new_for_uri (slot_uri);
nautilus_window_slot_open_location (slot, location, FALSE);
if (xmlHasProp (slot_node, "active")) {
nautilus_window_set_active_slot (window, slot);
}
i++;
}
xmlFree (slot_uri);
}
}
if (i == 0) {
/* This may be an old session file */
location = g_file_new_for_uri (location_uri);
nautilus_window_slot_open_location (window->details->active_slot, location, FALSE);
g_object_unref (location);
}
} else if (!strcmp (type, "spatial")) {
location = g_file_new_for_uri (location_uri);
window = nautilus_application_present_spatial_window (application, NULL, NULL, location, gdk_screen_get_default ());
location = g_file_new_for_uri (uri);
emit_change |= nautilus_add_to_history_list_no_notify (location, name, has_custom_name, icon);
g_object_unref (location);
if (icon) {
g_object_unref (icon);
}
xmlFree (name);
xmlFree (uri);
xmlFree (icon_str);
} else {
g_message ("unknown window type \"%s\" while parsing %s", type, filename);
g_message ("unexpected bookmark node %s while parsing session data", bookmark_node->name);
bail = TRUE;
continue;
}
xmlFree (type);
xmlFree (location_uri);
} else {
g_message ("unexpected node %s while parsing %s", node->name, filename);
}
if (emit_change) {
nautilus_send_history_list_changed ();
}
} else if (!strcmp (node->name, "window")) {
NautilusWindow *window;
xmlChar *type, *location_uri, *slot_uri;
xmlNodePtr slot_node;
GFile *location;
int i;
type = xmlGetProp (node, "type");
if (type == NULL) {
g_message ("empty type node while parsing session data");
bail = TRUE;
continue;
}
location_uri = xmlGetProp (node, "location");
if (location_uri == NULL) {
g_message ("empty location node while parsing session data");
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));
}
if (xmlHasProp (node, "sticky")) {
gtk_window_stick (GTK_WINDOW (window));
} else {
gtk_window_unstick (GTK_WINDOW (window));
}
if (xmlHasProp (node, "keep-above")) {
gtk_window_set_keep_above (GTK_WINDOW (window), TRUE);
} else {
gtk_window_set_keep_above (GTK_WINDOW (window), FALSE);
}
for (i = 0, slot_node = node->children; slot_node != NULL; slot_node = slot_node->next) {
if (!strcmp (slot_node->name, "slot")) {
slot_uri = xmlGetProp (slot_node, "location");
if (slot_uri != NULL) {
NautilusWindowSlot *slot;
if (i == 0) {
slot = window->details->active_slot;
} else {
slot = nautilus_window_open_slot (window, NAUTILUS_WINDOW_OPEN_SLOT_APPEND);
}
location = g_file_new_for_uri (slot_uri);
nautilus_window_slot_open_location (slot, location, FALSE);
if (xmlHasProp (slot_node, "active")) {
nautilus_window_set_active_slot (window, slot);
}
i++;
}
xmlFree (slot_uri);
}
}
if (i == 0) {
/* This may be an old session file */
location = g_file_new_for_uri (location_uri);
nautilus_window_slot_open_location (window->details->active_slot, location, FALSE);
g_object_unref (location);
}
} else if (!strcmp (type, "spatial")) {
location = g_file_new_for_uri (location_uri);
window = nautilus_application_present_spatial_window (application, NULL, NULL, location, gdk_screen_get_default ());
g_object_unref (location);
} else {
g_message ("unknown window type \"%s\" while parsing session data", type);
bail = TRUE;
}
xmlFree (type);
xmlFree (location_uri);
} else {
g_message ("unexpected node %s while parsing session data", node->name);
bail = TRUE;
continue;
}
}
if (doc != NULL) {
xmlFreeDoc (doc);
}
}
if (doc != NULL) {
xmlFreeDoc (doc);
}
g_free (data);
if (bail) {
g_message ("failed to load session from %s", filename);
} else {
struct stat buf;
/* only remove file if it is regular, user-owned and the user has write access. */
if (g_stat (filename, &buf) == 0 &&
S_ISREG (buf.st_mode) &&
(buf.st_mode & S_IWUSR) &&
buf.st_uid == geteuid()) {
g_remove (filename);
}
}
}
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] = nautilus_application_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;
}
static void
set_session_restart (GnomeClient *client, gboolean restart)
{
gnome_client_set_priority (client, 40);
if (restart && g_getenv ("NAUTILUS_DEBUG") == NULL) {
/* Don't respawn in debug mode */
gnome_client_set_restart_style (client, GNOME_RESTART_IMMEDIATELY);
} else {
gnome_client_set_restart_style (client, GNOME_RESTART_IF_RUNNING);
}
}
static void
update_session (gpointer callback_data)
{
set_session_restart (callback_data,
/* Only ever add ourselves to the session
* if we have a desktop window. Prevents the
* session thrashing that's seen otherwise
*/
nautilus_application_desktop_windows != NULL);
}
static void
init_session (void)
{
GnomeClient *client;
client = gnome_master_client ();
g_signal_connect (client, "save_yourself",
G_CALLBACK (save_session), NULL);
g_signal_connect (client, "die",
G_CALLBACK (removed_from_session), NULL);
update_session (client);
g_message ("failed to load session");
}
}
#ifdef UGLY_HACK_TO_DETECT_KDE

View File

@ -30,6 +30,7 @@
#include <gdk/gdk.h>
#include <gio/gio.h>
#include <unique/unique.h>
#include <libegg/eggsmclient.h>
#include <libnautilus-private/nautilus-undo-manager.h>
#define NAUTILUS_DESKTOP_ICON_VIEW_IID "OAFIID:Nautilus_File_Manager_Desktop_Icon_View"
@ -55,6 +56,7 @@ typedef struct NautilusShell NautilusShell;
typedef struct {
GObject parent;
UniqueApp *unique_app;
EggSMClient *smclient;
NautilusUndoManager *undo_manager;
GVolumeMonitor *volume_monitor;
unsigned int automount_idle_id;
@ -68,12 +70,10 @@ GType nautilus_application_get_type (void);
NautilusApplication *nautilus_application_new (void);
void nautilus_application_startup (NautilusApplication *application,
gboolean kill_shell,
gboolean restart_shell,
gboolean no_default_window,
gboolean no_desktop,
gboolean browser_window,
const char *default_geometry,
const char *session_to_load,
char **urls);
GList * nautilus_application_get_window_list (void);
GList * nautilus_application_get_spatial_window_list (void);
@ -100,7 +100,4 @@ 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);
char * nautilus_application_save_session_to_file (void);
#endif /* NAUTILUS_APPLICATION_H */

View File

@ -39,6 +39,8 @@
#include <eel/eel-debug.h>
#include <eel/eel-glib-extensions.h>
#include <eel/eel-self-checks.h>
#include <libegg/eggsmclient.h>
#include <libegg/eggdesktopfile.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
@ -130,8 +132,9 @@ nautilus_main_event_loop_quit (gboolean explicit)
{
if (explicit) {
/* Explicit --quit, make sure we don't restart */
gnome_client_set_restart_style (gnome_master_client (),
GNOME_RESTART_IF_RUNNING);
/* TODO: With the old session we needed to set restart
style to GNOME_RESTART_IF_RUNNING here, but i don't think we need
that now since gnome-session doesn't restart apps except on startup. */
}
while (event_loop_registrants != NULL) {
gtk_object_destroy (event_loop_registrants->data);
@ -302,26 +305,22 @@ int
main (int argc, char *argv[])
{
gboolean kill_shell;
gboolean restart_shell;
gboolean no_default_window;
gboolean browser_window;
gboolean no_desktop;
gboolean version;
gboolean autostart_mode;
gboolean has_sm_argv;
const char *autostart_id;
char *session_to_load;
gchar *geometry;
const gchar **remaining;
char **p;
gboolean perform_self_check;
GOptionContext *context;
NautilusApplication *application;
char **argv_copy;
GnomeProgram *program;
GOptionContext *context;
GFile *file;
char *uri;
char **uris;
GPtrArray *uris_array;
GError *error;
int i;
const GOptionEntry options[] = {
@ -329,6 +328,8 @@ main (int argc, char *argv[])
{ "check", 'c', 0, G_OPTION_ARG_NONE, &perform_self_check,
N_("Perform a quick set of self-check tests."), NULL },
#endif
{ "version", '\0', 0, G_OPTION_ARG_NONE, &version,
N_("Show the version of the progam."), NULL },
{ "geometry", 'g', 0, G_OPTION_ARG_STRING, &geometry,
N_("Create the initial window with the given geometry."), N_("GEOMETRY") },
{ "no-default-window", 'n', 0, G_OPTION_ARG_NONE, &no_default_window,
@ -339,20 +340,13 @@ main (int argc, char *argv[])
N_("open a browser window."), NULL },
{ "quit", 'q', 0, G_OPTION_ARG_NONE, &kill_shell,
N_("Quit Nautilus."), NULL },
{ "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 }
};
g_thread_init (NULL);
setlocale (LC_ALL, "");
/* This will be done by gtk+ later, but for now, force it to GNOME */
g_desktop_app_info_set_desktop_env ("GNOME");
@ -372,51 +366,44 @@ main (int argc, char *argv[])
autostart_mode = TRUE;
}
/* detect whether this is a restart request by the SM */
has_sm_argv = FALSE;
for (p = argv; p - argv < argc; p++) {
if (g_str_has_prefix (*p, "--sm-client-id")) {
has_sm_argv = TRUE;
}
}
/* Get parameters. */
remaining = NULL;
geometry = NULL;
session_to_load = NULL;
version = FALSE;
kill_shell = FALSE;
no_default_window = FALSE;
no_desktop = FALSE;
perform_self_check = FALSE;
restart_shell = FALSE;
browser_window = FALSE;
g_set_prgname ("nautilus");
g_set_application_name (_("File Manager"));
egg_set_desktop_file (DATADIR "/applications/nautilus.desktop");
context = g_option_context_new (_("\n\nBrowse the file system with the file manager"));
g_option_context_add_main_entries (context, options, NULL);
g_option_context_add_group (context, gtk_get_option_group (TRUE));
g_option_context_add_group (context, egg_sm_client_get_option_group ());
error = NULL;
if (!g_option_context_parse (context, &argc, &argv, &error)) {
g_printerr ("Could not parse arguments: %s\n", error->message);
g_error_free (error);
return 1;
}
g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
if (version) {
g_print ("GNOME nautilus " PACKAGE_VERSION "\n");
return 0;
}
#ifdef HAVE_EXEMPI
xmp_init();
#endif
program = gnome_program_init ("nautilus", VERSION,
LIBGNOMEUI_MODULE, argc, argv,
GNOME_PROGRAM_STANDARD_PROPERTIES,
GNOME_PARAM_GOPTION_CONTEXT, context,
GNOME_PARAM_HUMAN_READABLE_NAME, _("Nautilus"),
NULL);
/* We do this after gnome_program_init(), since that function sets up
* its own handler for SIGSEGV and others --- we want to chain to those
* handlers.
*/
setup_debug_log ();
if (session_to_load != NULL) {
no_default_window = TRUE;
}
/* If in autostart mode (aka started by gnome-session), we need to ensure
* nautilus starts with the correct options.
*/
@ -425,16 +412,13 @@ main (int argc, char *argv[])
no_desktop = FALSE;
}
/* Set default icon for all nautilus windows */
gtk_window_set_default_icon_name (NAUTILUS_ICON_FOLDER);
if (perform_self_check && remaining != NULL) {
/* translators: %s is an option (e.g. --check) */
fprintf (stderr, _("nautilus: %s cannot be used with URIs.\n"),
"--check");
return EXIT_FAILURE;
}
if (perform_self_check && (kill_shell || restart_shell)) {
if (perform_self_check && kill_shell) {
fprintf (stderr, _("nautilus: --check cannot be used with other options.\n"));
return EXIT_FAILURE;
}
@ -443,11 +427,6 @@ main (int argc, char *argv[])
"--quit");
return EXIT_FAILURE;
}
if (restart_shell && remaining != NULL) {
fprintf (stderr, _("nautilus: %s cannot be used with URIs.\n"),
"--restart");
return EXIT_FAILURE;
}
if (geometry != NULL && remaining != NULL && remaining[0] != NULL && remaining[1] != NULL) {
fprintf (stderr, _("nautilus: --geometry cannot be used with more than one URI.\n"));
return EXIT_FAILURE;
@ -468,11 +447,6 @@ main (int argc, char *argv[])
(NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR, TRUE);
}
if (has_sm_argv && eel_preferences_get_boolean (NAUTILUS_PREFERENCES_SHOW_DESKTOP)) {
/* we were restarted by the session manager. Don't show default window */
no_default_window = TRUE;
}
application = NULL;
/* Do either the self-check or the real work. */
@ -509,12 +483,16 @@ main (int argc, char *argv[])
/* Run the nautilus application. */
application = nautilus_application_new ();
if (egg_sm_client_is_resumed (application->smclient)) {
no_default_window = TRUE;
}
nautilus_application_startup
(application,
kill_shell, restart_shell, no_default_window, no_desktop,
kill_shell, no_default_window, no_desktop,
browser_window,
geometry,
session_to_load,
uris);
g_strfreev (uris);
@ -531,25 +509,5 @@ main (int argc, char *argv[])
eel_debug_shut_down ();
/* If told to restart, exec() myself again. This is used when
* the program is told to restart with CORBA, for example when
* an update takes place.
*/
if (g_getenv ("_NAUTILUS_RESTART_SESSION_FILENAME") != NULL) {
argv_copy = g_new0 (char *, 4);
argv_copy[0] = g_strdup (argv[0]);
argv_copy[1] = g_strdup ("--load-session");
argv_copy[2] = g_strdup (g_getenv ("_NAUTILUS_RESTART_SESSION_FILENAME"));
g_unsetenv ("_NAUTILUS_RESTART_SESSION_FILENAME");
execvp (argv[0], argv_copy);
g_strfreev (argv_copy);
}
g_object_unref (G_OBJECT (program));
return EXIT_SUCCESS;
}