gnome-session r5355 - in trunk: . gnome-session



Author: vuntz
Date: Tue Mar 24 22:51:44 2009
New Revision: 5355
URL: http://svn.gnome.org/viewvc/gnome-session?rev=5355&view=rev

Log:
2009-03-24  Vincent Untz  <vuntz gnome org>

	Rework deeply the code that writes the saved session to desktop files:
	we now properly discard a client when removing it; we also make sure we
	save the current session before we completely remove the previously
	saved session (to be on the safe side).
	Note that we only discard a client when the new saved session doesn't
	use the same discard command: for example, when metacity saves its
	state, it will reuse the same discard command and so we can't discard
	the old metacity client (it would discard the new client).

	* gnome-session/gsm-util.[ch]: (gsm_util_get_empty_tmp_session_dir):
	new function to get a temporary directory where to save the new
	session, while we still keep the previously saved session. It also
	makes sure the directory is empty.
	* gnome-session/gsm-session-save.[ch]: (save_one_client): update to
	make sure we remember the discard command from the client.
	(gsm_session_save): rework to first save the session in the temporary
	directory (and remember the discard commands from the saved clients),
	and then clear the old session. We finish by renaming the temporary
	directory to its final name.
	(gsm_session_clear_one_client): new, to properly clear one client from
	a saved session. We unlink the desktop file, but also run the discard
	command if it's not used by any other client from the newly saved
	session.
	(gsm_session_clear_saved_session): change to clear a saved session in a
	specified directory, and use gsm_session_clear_one_client() instead of
	just unlinking the desktop file. Also add missing g_dir_close().


Modified:
   trunk/ChangeLog
   trunk/gnome-session/gsm-session-save.c
   trunk/gnome-session/gsm-session-save.h
   trunk/gnome-session/gsm-util.c
   trunk/gnome-session/gsm-util.h

Modified: trunk/gnome-session/gsm-session-save.c
==============================================================================
--- trunk/gnome-session/gsm-session-save.c	(original)
+++ trunk/gnome-session/gsm-session-save.c	Tue Mar 24 22:51:44 2009
@@ -28,18 +28,27 @@
 
 #include "gsm-session-save.h"
 
+static gboolean gsm_session_clear_saved_session (const char *directory,
+                                                 GHashTable *discard_hash);
+
+typedef struct {
+        char        *dir;
+        GHashTable  *discard_hash;
+        GError     **error;
+} SessionSaveData;
+
 static gboolean
-save_one_client (char     *id,
-                 GObject  *object,
-                 GError  **error)
+save_one_client (char            *id,
+                 GObject         *object,
+                 SessionSaveData *data)
 {
         GsmClient  *client;
         GKeyFile   *keyfile;
         char       *path = NULL;
         char       *filename = NULL;
         char       *contents = NULL;
-        const char *saved_session_dir;
         gsize       length = 0;
+        char       *discard_exec;
         GError     *local_error;
 
         client = GSM_CLIENT (object);
@@ -58,16 +67,10 @@
                 goto out;
         }
 
-        saved_session_dir = gsm_util_get_saved_session_dir ();
-
-        if (saved_session_dir == NULL) {
-                goto out;
-        }
-
         filename = g_strdup_printf ("%s.desktop",
                                     gsm_client_peek_startup_id (client));
 
-        path = g_build_filename (saved_session_dir, filename, NULL);
+        path = g_build_filename (data->dir, filename, NULL);
 
         g_file_set_contents (path,
                              contents,
@@ -78,6 +81,15 @@
                 goto out;
         }
 
+        discard_exec = g_key_file_get_string (keyfile,
+                                              G_KEY_FILE_DESKTOP_GROUP,
+                                              "X-GNOME-Autostart-discard-exec",
+                                              NULL);
+        if (discard_exec) {
+                g_hash_table_insert (data->discard_hash,
+                                     discard_exec, discard_exec);
+        }
+
         g_debug ("GsmSessionSave: saved client %s to %s", id, filename);
 
 out:
@@ -91,7 +103,7 @@
 
         /* in case of any error, stop saving session */
         if (local_error) {
-                g_propagate_error (error, local_error);
+                g_propagate_error (data->error, local_error);
                 g_error_free (local_error);
 
                 return TRUE;
@@ -104,39 +116,121 @@
 gsm_session_save (GsmStore  *client_store,
                   GError   **error)
 {
-        gsm_session_clear_saved_session ();
+        const char      *save_dir;
+        char            *tmp_dir;
+        SessionSaveData  data;
 
         g_debug ("GsmSessionSave: Saving session");
 
+        save_dir = gsm_util_get_saved_session_dir ();
+        if (save_dir == NULL) {
+                g_warning ("GsmSessionSave: cannot create saved session directory");
+                return;
+        }
+
+        tmp_dir = gsm_util_get_empty_tmp_session_dir ();
+        if (tmp_dir == NULL) {
+                g_warning ("GsmSessionSave: cannot create new saved session directory");
+                return;
+        }
+
+        /* save the session in a temp directory, and remember the discard
+         * commands */
+        data.dir = tmp_dir;
+        data.discard_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                   g_free, NULL);
+        data.error = error;
+
         gsm_store_foreach (client_store,
                            (GsmStoreFunc) save_one_client,
-                           error);
+                           &data);
 
-        if (*error) {
+        if (!*error) {
+                /* remove the old saved session */
+                gsm_session_clear_saved_session (save_dir, data.discard_hash);
+
+                /* rename the temp session dir */
+                if (g_file_test (save_dir, G_FILE_TEST_IS_DIR))
+                        g_rmdir (save_dir);
+                g_rename (tmp_dir, save_dir);
+        } else {
                 g_warning ("GsmSessionSave: error saving session: %s", (*error)->message);
-                gsm_session_clear_saved_session ();
+                /* FIXME: we should create a hash table filled with the discard
+                 * commands that are in desktop files from save_dir. */
+                gsm_session_clear_saved_session (tmp_dir, NULL);
+                g_rmdir (tmp_dir);
+        }
+
+        g_hash_table_destroy (data.discard_hash);
+        g_free (tmp_dir);
+}
+
+static gboolean
+gsm_session_clear_one_client (const char *filename,
+                              GHashTable *discard_hash)
+{
+        gboolean  result = TRUE;
+        GKeyFile *key_file = NULL;
+        char     *discard_exec = NULL;
+
+        g_debug ("GsmSessionSave: removing '%s' from saved session", filename);
+
+        key_file = g_key_file_new ();
+        if (g_key_file_load_from_file (key_file, filename,
+                                       G_KEY_FILE_NONE, NULL)) {
+                char **argv;
+                int    argc;
+
+                discard_exec = g_key_file_get_string (key_file,
+                                                      G_KEY_FILE_DESKTOP_GROUP,
+                                                      "X-GNOME-Autostart-discard-exec",
+                                                      NULL);
+                if (!discard_exec)
+                        goto out;
+
+                if (g_hash_table_lookup (discard_hash, discard_exec))
+                        goto out;
+
+                if (!g_shell_parse_argv (discard_exec, &argc, &argv, NULL))
+                        goto out;
+
+                result = g_spawn_async (NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
+                                        NULL, NULL, NULL, NULL) && result;
+
+                g_strfreev (argv);
+        } else {
+                result = FALSE;
         }
+
+out:
+        if (key_file)
+                g_key_file_free (key_file);
+        if (discard_exec)
+                g_free (discard_exec);
+
+        result = (g_unlink (filename) == 0) && result;
+
+        return result;
 }
 
-gboolean
-gsm_session_clear_saved_session ()
+static gboolean
+gsm_session_clear_saved_session (const char *directory,
+                                 GHashTable *discard_hash)
 {
         GDir       *dir;
-        const char *saved_session_dir;
         const char *filename;
         gboolean    result = TRUE;
         GError     *error;
 
-        saved_session_dir = gsm_util_get_saved_session_dir ();
+        g_debug ("GsmSessionSave: clearing currectly saved session at %s",
+                 directory);
 
-        g_debug ("GsmSessionSave: clearing currectly saved session at %s", saved_session_dir);
-
-        if (saved_session_dir == NULL) {
+        if (directory == NULL) {
                 return FALSE;
         }
 
         error = NULL;
-        dir = g_dir_open (saved_session_dir, 0, &error);
+        dir = g_dir_open (directory, 0, &error);
         if (error) {
                 g_warning ("GsmSessionSave: error loading saved session directory: %s", error->message);
                 g_error_free (error);
@@ -144,15 +238,16 @@
         }
 
         while ((filename = g_dir_read_name (dir))) {
-                char *path = g_build_filename (saved_session_dir,
+                char *path = g_build_filename (directory,
                                                filename, NULL);
 
-                g_debug ("GsmSessionSave: removing '%s' from saved session", path);
-
-                result = result && (g_unlink (path) == 0);
+                result = gsm_session_clear_one_client (path, discard_hash)
+                         && result;
 
                 g_free (path);
         }
 
+        g_dir_close (dir);
+
         return result;
 }

Modified: trunk/gnome-session/gsm-session-save.h
==============================================================================
--- trunk/gnome-session/gsm-session-save.h	(original)
+++ trunk/gnome-session/gsm-session-save.h	Tue Mar 24 22:51:44 2009
@@ -29,8 +29,6 @@
 void      gsm_session_save                 (GsmStore  *client_store,
                                             GError   **error);
 
-gboolean  gsm_session_clear_saved_session  (void);
-
 G_END_DECLS
 
 #endif /* __GSM_SESSION_SAVE_H__ */

Modified: trunk/gnome-session/gsm-util.c
==============================================================================
--- trunk/gnome-session/gsm-util.c	(original)
+++ trunk/gnome-session/gsm-util.c	Tue Mar 24 22:51:44 2009
@@ -139,6 +139,42 @@
         return FALSE;
 }
 
+gchar *
+gsm_util_get_empty_tmp_session_dir (void)
+{
+        char *tmp;
+        gboolean exists;
+
+        tmp = g_build_filename (g_get_user_config_dir (),
+                                "gnome-session",
+                                "saved-session.new",
+                                NULL);
+
+        exists = ensure_dir_exists (tmp);
+
+        if (G_UNLIKELY (!exists)) {
+                g_warning ("GsmSessionSave: could not create directory for saved session: %s", tmp);
+                g_free (tmp);
+                return NULL;
+        } else {
+                /* make sure it's empty */
+                GDir       *dir;
+                const char *filename;
+
+                dir = g_dir_open (tmp, 0, NULL);
+                if (dir) {
+                        while ((filename = g_dir_read_name (dir))) {
+                                char *path = g_build_filename (tmp, filename,
+                                                               NULL);
+                                g_unlink (path);
+                        }
+                        g_dir_close (dir);
+                }
+        }
+
+        return tmp;
+}
+
 const gchar *
 gsm_util_get_saved_session_dir (void)
 {

Modified: trunk/gnome-session/gsm-util.h
==============================================================================
--- trunk/gnome-session/gsm-util.h	(original)
+++ trunk/gnome-session/gsm-util.h	Tue Mar 24 22:51:44 2009
@@ -27,6 +27,8 @@
 char *      gsm_util_find_desktop_file_for_app_name (const char  *app_name,
                                                      char       **dirs);
 
+gchar      *gsm_util_get_empty_tmp_session_dir      (void);
+
 const char *gsm_util_get_saved_session_dir          (void);
 
 gchar**     gsm_util_get_app_dirs                   (void);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]