don't save a file here, only in response to SaveYourself. Change the code

2002-03-13  Havoc Pennington  <hp@pobox.com>

	* src/session.c (meta_session_init): don't save a file here, only
	in response to SaveYourself. Change the code to properly use a
	unique state file for each SaveYourself. Totally, totally
	untested.
This commit is contained in:
Havoc Pennington 2002-03-14 04:09:42 +00:00 committed by Havoc Pennington
parent 9b86849068
commit 9e2cfcd699
4 changed files with 145 additions and 79 deletions

View File

@ -1,3 +1,10 @@
2002-03-13 Havoc Pennington <hp@pobox.com>
* src/session.c (meta_session_init): don't save a file here, only
in response to SaveYourself. Change the code to properly use a
unique state file for each SaveYourself. Totally, totally
untested.
2002-03-12 Havoc Pennington <hp@pobox.com>
* src/theme-viewer.c: improve the theme viewer so people

View File

@ -58,7 +58,7 @@ log_handler (const gchar *log_domain,
static void
usage (void)
{
g_print ("metacity [--disable-sm] [--sm-client-id=ID] [--display=DISPLAY]\n");
g_print ("metacity [--disable-sm] [--sm-save-file=FILENAME] [--display=DISPLAY]\n");
exit (1);
}
@ -72,6 +72,7 @@ main (int argc, char **argv)
const char *client_id;
gboolean disable_sm;
const char *prev_arg;
const char *save_file;
sigemptyset (&empty_mask);
act.sa_handler = SIG_IGN;
@ -100,6 +101,7 @@ main (int argc, char **argv)
display_name = NULL;
client_id = NULL;
save_file = NULL;
disable_sm = FALSE;
prev_arg = NULL;
i = 1;
@ -136,27 +138,27 @@ main (int argc, char **argv)
}
else if (strcmp (arg, "--display") == 0)
; /* wait for next arg */
else if (strstr (arg, "--sm-client-id=") == arg)
else if (strstr (arg, "--sm-save-file=") == arg)
{
const char *id;
const char *file;
if (client_id)
meta_fatal ("Can't specify client ID twice\n");
if (save_file)
meta_fatal ("Can't specify SM save file twice\n");
id = strchr (arg, '=');
++id;
file = strchr (arg, '=');
++file;
client_id = g_strdup (id);
save_file = g_strdup (file);
}
else if (prev_arg &&
strcmp (prev_arg, "--sm-client-id") == 0)
strcmp (prev_arg, "--sm-save-file") == 0)
{
if (client_id)
meta_fatal ("Can't specify client ID twice\n");
if (save_file)
meta_fatal ("Can't specify SM save file twice\n");
client_id = g_strdup (arg);
save_file = g_strdup (arg);
}
else if (strcmp (arg, "--sm-client-id") == 0)
else if (strcmp (arg, "--sm-save-file") == 0)
; /* wait for next arg */
else
usage ();
@ -241,7 +243,7 @@ main (int argc, char **argv)
* info
*/
if (!disable_sm)
meta_session_init (client_id); /* client_id == NULL is fine */
meta_session_init (save_file);
if (!meta_display_open (NULL))
meta_exit (META_EXIT_ERROR);

View File

@ -17,15 +17,18 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. */
* 02111-1307, USA.
*/
#include <config.h>
#include "session.h"
#include <time.h>
#ifndef HAVE_SM
void
meta_session_init (const char *previous_id)
meta_session_init (const char *save_file)
{
meta_topic (META_DEBUG_SM, "Compiled without session management support\n");
}
@ -65,7 +68,11 @@ static void new_ice_connection (IceConn connection, IcePointer client_data,
Bool opening, IcePointer *watch_data);
static void save_state (void);
static void load_state (const char *previous_id);
static void load_state (const char *previous_save_file);
static const char* get_previous_id (void);
static void regenerate_save_file (void);
static const char* full_save_file (void);
static const char* base_save_file (void);
/* This is called when data is available on an ICE connection. */
static gboolean
@ -196,29 +203,38 @@ static void save_yourself_callback (SmcConn smc_conn,
Bool fast);
static void set_clone_restart_commands (void);
static gchar *client_id = NULL;
static char *client_id = NULL;
static gpointer session_connection = NULL;
static ClientState current_state = STATE_DISCONNECTED;
void
meta_session_init (const char *previous_id)
meta_session_init (const char *previous_save_file)
{
/* Some code here from twm */
char buf[256];
unsigned long mask;
SmcCallbacks callbacks;
const char *previous_id;
meta_topic (META_DEBUG_SM, "Initializing session with session ID '%s'\n",
previous_id ? previous_id : "(none)");
meta_topic (META_DEBUG_SM, "Initializing session with save file '%s'\n",
previous_save_file ? previous_save_file : "(none)");
if (previous_id)
load_state (previous_id);
if (previous_save_file)
load_state (previous_save_file);
previous_id = get_previous_id (); /* from the file if any, null otherwise */
ice_init ();
mask = SmcSaveYourselfProcMask | SmcDieProcMask |
SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask;
#if 0
/* note this isn't in the mask above */
callbacks.interact.callback = interact_callback;
callbacks.interact.client_data = NULL;
#endif
callbacks.save_yourself.callback = save_yourself_callback;
callbacks.save_yourself.client_data = NULL;
@ -238,7 +254,7 @@ meta_session_init (const char *previous_id)
SmProtoMinor,
mask,
&callbacks,
previous_id,
(char*) previous_id,
&client_id,
255, buf);
@ -280,7 +296,7 @@ meta_session_init (const char *previous_id)
prop2.type = SmARRAY8;
prop2.num_vals = 1;
prop2.vals = &prop2val;
prop2val.value = g_get_user_name ();
prop2val.value = (char*) g_get_user_name ();
prop2val.length = strlen (prop2val.value);
prop3.name = SmRestartStyleHint;
@ -303,7 +319,7 @@ meta_session_init (const char *previous_id)
prop5.type = SmARRAY8;
prop5.num_vals = 1;
prop5.vals = &prop5val;
prop5val.value = g_get_home_dir ();
prop5val.value = (char*) g_get_home_dir ();
prop5val.length = strlen (prop5val.value);
prop6.name = "_GSM_Priority";
@ -322,8 +338,6 @@ meta_session_init (const char *previous_id)
SmcSetProperties (session_connection, 6, props);
}
set_clone_restart_commands ();
}
static void
@ -392,30 +406,12 @@ save_yourself_callback (SmcConn smc_conn,
/* The first SaveYourself after registering for the first time
* is a special case (SM specs 7.2).
*
* This SaveYourself seems to be included in the protocol to
* ask the client to specify its initial SmProperties since
* there is little point saving a copy of the initial state.
*
* A bug in xsm means that it does not send us a SaveComplete
* in response to this initial SaveYourself. Therefore, we
* must not set a grab because it would never be released.
* Indeed, even telling the app that this SaveYourself has
* arrived is hazardous as the app may take its own steps
* to freeze its WM state while waiting for the SaveComplete.
*
* Fortunately, we have already set the SmProperties during
* gnome_client_connect so there is little lost in simply
* returning immediately.
*
* Apps which really want to save their initial states can
* do so safely using gnome_client_save_yourself_request.
*/
#if 0 /* I think the GnomeClient rationale for this doesn't apply */
if (current_state == STATE_REGISTERING)
{
current_state = STATE_IDLE;
/* Double check that this is a section 7.2 SaveYourself: */
if (save_style == SmSaveLocal &&
@ -427,9 +423,12 @@ save_yourself_callback (SmcConn smc_conn,
return;
}
}
#endif
current_state = STATE_SAVING_PHASE_1;
regenerate_save_file ();
set_clone_restart_commands ();
save_yourself_possibly_done (shutdown, successful);
@ -470,12 +469,6 @@ set_clone_restart_commands (void)
char *discardv[10];
int i;
SmProp prop1, prop2, prop3, *props[3];
char *session_file;
session_file = g_strconcat (g_get_home_dir (),
"/.metacity/sessions/",
client_id,
NULL);
/* Restart (use same client ID) */
@ -485,9 +478,9 @@ set_clone_restart_commands (void)
i = 0;
restartv[i] = "metacity";
++i;
restartv[i] = "--sm-client-id";
restartv[i] = "--sm-save-file";
++i;
restartv[i] = client_id;
restartv[i] = (char*) base_save_file ();
++i;
restartv[i] = NULL;
@ -528,7 +521,7 @@ set_clone_restart_commands (void)
++i;
discardv[i] = "-f";
++i;
discardv[i] = session_file;
discardv[i] = (char*) full_save_file ();
prop3.name = SmCloneCommand;
prop3.type = SmLISTofARRAY8;
@ -553,8 +546,6 @@ set_clone_restart_commands (void)
g_free (prop1.vals);
g_free (prop2.vals);
g_free (prop3.vals);
g_free (session_file);
}
/* The remaining code in this file actually loads/saves the session,
@ -743,7 +734,6 @@ save_state (void)
{
char *metacity_dir;
char *session_dir;
char *session_file;
FILE *outfile;
GSList *displays;
GSList *display_iter;
@ -758,12 +748,6 @@ save_state (void)
session_dir = g_strconcat (metacity_dir, "/sessions",
NULL);
/* Assuming client ID is a workable filename. */
session_file = g_strconcat (session_dir, "/",
client_id,
NULL);
if (mkdir (metacity_dir, 0700) < 0 &&
errno != EEXIST)
{
@ -778,14 +762,14 @@ save_state (void)
session_dir, g_strerror (errno));
}
meta_topic (META_DEBUG_SM, "Saving session to '%s'\n", session_file);
meta_topic (META_DEBUG_SM, "Saving session to '%s'\n", full_save_file ());
outfile = fopen (session_file, "w");
outfile = fopen (full_save_file (), "w");
if (outfile == NULL)
{
meta_warning (_("Could not open session file '%s' for writing: %s\n"),
session_file, g_strerror (errno));
full_save_file (), g_strerror (errno));
goto out;
}
@ -917,18 +901,17 @@ save_state (void)
if (ferror (outfile))
{
meta_warning (_("Error writing session file '%s': %s\n"),
session_file, g_strerror (errno));
full_save_file (), g_strerror (errno));
}
if (fclose (outfile))
{
meta_warning (_("Error closing session file '%s': %s\n"),
session_file, g_strerror (errno));
full_save_file (), g_strerror (errno));
}
}
g_free (metacity_dir);
g_free (session_dir);
g_free (session_file);
}
typedef enum
@ -973,9 +956,10 @@ static GMarkupParser metacity_session_parser = {
};
static GSList *window_info_list = NULL;
static char* previous_id = NULL;
static void
load_state (const char *previous_id)
load_state (const char *previous_save_file)
{
GMarkupParseContext *context;
GError *error;
@ -986,7 +970,7 @@ load_state (const char *previous_id)
session_file = g_strconcat (g_get_home_dir (),
"/.metacity/sessions/",
previous_id,
previous_save_file,
NULL);
error = NULL;
@ -1056,7 +1040,43 @@ start_element_handler (GMarkupParseContext *context,
if (strcmp (element_name, "metacity_session") == 0)
{
/* do nothing */
/* Get previous ID */
int i;
i = 0;
while (attribute_names[i])
{
const char *name;
const char *val;
name = attribute_names[i];
val = attribute_values[i];
if (previous_id)
{
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_PARSE,
_("<metacity_session> attribute seen but we already have the session ID"));
return;
}
if (strcmp (name, "id") == 0)
{
previous_id = decode_text_from_utf8 (val);
}
else
{
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
_("Unknown attribute %s on <metacity_session> element"),
name);
return;
}
++i;
}
}
else if (strcmp (element_name, "window") == 0)
{
@ -1277,6 +1297,11 @@ text_handler (GMarkupParseContext *context,
*/
}
static const char*
get_previous_id (void)
{
return previous_id;
}
static gboolean
both_null_or_matching (const char *a,
@ -1360,7 +1385,7 @@ get_possible_matches (MetaWindow *window)
return retval;
}
const MetaWindowSessionInfo*
static const MetaWindowSessionInfo*
find_best_match (GSList *infos,
MetaWindow *window)
{
@ -1478,4 +1503,36 @@ session_info_new (void)
return info;
}
static char* relative_save_path = NULL;
static char* full_save_path = NULL;
static void
regenerate_save_file (void)
{
g_free (relative_save_path);
g_free (full_save_path);
relative_save_path = g_strdup_printf ("%d-%d-%u.ms",
(int) time (NULL),
(int) getpid (),
g_random_int ());
full_save_path = g_strconcat (g_get_home_dir (),
"/.metacity/sessions/",
relative_save_path,
NULL);
}
static const char*
full_save_file (void)
{
return full_save_path;
}
static const char*
base_save_file (void)
{
return relative_save_path;
}
#endif /* HAVE_SM */

View File

@ -60,7 +60,7 @@ struct _MetaWindowSessionInfo
const MetaWindowSessionInfo* meta_window_lookup_saved_state (MetaWindow *window);
void meta_window_release_saved_state (const MetaWindowSessionInfo *info);
void meta_session_init (const char *previous_id);
void meta_session_init (const char *save_file);
#endif