mirror of
https://gitlab.gnome.org/GNOME/nautilus
synced 2024-10-03 22:45:26 +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:
parent
31d3fc91d8
commit
9c068ad3e6
35
ChangeLog
35
ChangeLog
|
@ -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:
|
||||
|
|
|
@ -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 = \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
1474
cut-n-paste-code/libegg/eggdesktopfile.c
Normal file
1474
cut-n-paste-code/libegg/eggdesktopfile.c
Normal file
File diff suppressed because it is too large
Load diff
159
cut-n-paste-code/libegg/eggdesktopfile.h
Normal file
159
cut-n-paste-code/libegg/eggdesktopfile.h
Normal 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__ */
|
53
cut-n-paste-code/libegg/eggsmclient-private.h
Normal file
53
cut-n-paste-code/libegg/eggsmclient-private.h
Normal 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__ */
|
1359
cut-n-paste-code/libegg/eggsmclient-xsmp.c
Normal file
1359
cut-n-paste-code/libegg/eggsmclient-xsmp.c
Normal file
File diff suppressed because it is too large
Load diff
578
cut-n-paste-code/libegg/eggsmclient.c
Normal file
578
cut-n-paste-code/libegg/eggsmclient.c
Normal 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);
|
||||
}
|
117
cut-n-paste-code/libegg/eggsmclient.h
Normal file
117
cut-n-paste-code/libegg/eggsmclient.h
Normal 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__ */
|
|
@ -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 */
|
||||
|
|
16
nautilus-browser.desktop.in.in
Normal file
16
nautilus-browser.desktop.in.in
Normal 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@
|
|
@ -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
|
||||
|
|
|
@ -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,13 +279,21 @@ 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 ();
|
||||
fm_desktop_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,296 +1637,223 @@ 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 = xmlReadMemory (data, strlen (data), NULL, "UTF-8", 0);
|
||||
if (doc != NULL && (root_node = xmlDocGetRootElement (doc)) != NULL) {
|
||||
xmlNodePtr node;
|
||||
|
||||
doc = xmlReadFile (filename, NULL, 0);
|
||||
if (doc != NULL && (root_node = xmlDocGetRootElement (doc)) != NULL) {
|
||||
xmlNodePtr node;
|
||||
bail = FALSE;
|
||||
|
||||
bail = FALSE;
|
||||
for (node = root_node->children; node != NULL; node = node->next) {
|
||||
|
||||
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;
|
||||
|
||||
if (!strcmp (node->name, "text")) {
|
||||
continue;
|
||||
} else if (!strcmp (node->name, "history")) {
|
||||
xmlNodePtr bookmark_node;
|
||||
gboolean emit_change;
|
||||
emit_change = FALSE;
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
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);
|
||||
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);
|
||||
location = g_file_new_for_uri (uri);
|
||||
|
||||
if (xmlHasProp (node, "maximized")) {
|
||||
gtk_window_maximize (GTK_WINDOW (window));
|
||||
} else {
|
||||
gtk_window_unmaximize (GTK_WINDOW (window));
|
||||
}
|
||||
emit_change |= nautilus_add_to_history_list_no_notify (location, name, has_custom_name, icon);
|
||||
|
||||
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 %s", type, filename);
|
||||
bail = TRUE;
|
||||
}
|
||||
|
||||
xmlFree (type);
|
||||
xmlFree (location_uri);
|
||||
} else {
|
||||
g_message ("unexpected node %s while parsing %s", node->name, filename);
|
||||
if (icon) {
|
||||
g_object_unref (icon);
|
||||
}
|
||||
xmlFree (name);
|
||||
xmlFree (uri);
|
||||
xmlFree (icon_str);
|
||||
} else {
|
||||
g_message ("unexpected bookmark node %s while parsing session data", bookmark_node->name);
|
||||
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 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);
|
||||
}
|
||||
g_message ("failed to load session");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef UGLY_HACK_TO_DETECT_KDE
|
||||
|
||||
static gboolean
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"));
|
||||
context = g_option_context_new (_("\n\nBrowse the file system with the file manager"));
|
||||
egg_set_desktop_file (DATADIR "/applications/nautilus.desktop");
|
||||
|
||||
g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue