This commit is contained in:
rhp 2001-07-26 05:10:01 +00:00
parent c18a8137ce
commit 5c2ac489f1
3 changed files with 233 additions and 16 deletions

3
README
View File

@ -64,6 +64,9 @@ METACITY FEATURES
the window will come with you to the new desktop, this is
a feature copied from Enlightenment.
If you hold down Shift while moving a window, the window snaps
to edges of other windows and the screen.
- Session management:
Metacity connects to the session manager and will set itself up

View File

@ -32,19 +32,27 @@ meta_session_init (const char *previous_id)
#include <X11/ICE/ICElib.h>
#include <X11/SM/SMlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <glib.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "main.h"
#include "util.h"
#include "display.h"
#include "workspace.h"
static void ice_io_error_handler (IceConn connection);
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);
/* This is called when data is available on an ICE connection. */
static gboolean
process_ice_messages (GIOChannel *channel,
@ -187,6 +195,9 @@ meta_session_init (const char *previous_id)
meta_verbose ("Initializing session with session ID '%s'\n",
previous_id ? previous_id : "(none)");
if (previous_id)
load_state (previous_id);
ice_init ();
mask = SmcSaveYourselfProcMask | SmcDieProcMask |
@ -221,7 +232,11 @@ meta_session_init (const char *previous_id)
return;
}
else
{
if (client_id == NULL)
meta_bug ("Session manager gave us a NULL client ID?");
meta_verbose ("Obtained session ID '%s'\n", client_id);
}
if (previous_id && strcmp (previous_id, client_id) == 0)
current_state = STATE_IDLE;
@ -333,6 +348,8 @@ save_phase_2_callback (SmcConn smc_conn, SmPointer client_data)
current_state = STATE_SAVING_PHASE_2;
save_state ();
save_yourself_possibly_done (shutdown, TRUE);
}
@ -425,8 +442,15 @@ set_clone_restart_commands (void)
{
char *restartv[10];
char *clonev[10];
char *discardv[10];
int i;
SmProp prop1, prop2, *props[2];
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) */
@ -472,10 +496,205 @@ set_clone_restart_commands (void)
}
prop2.num_vals = i;
/* Discard */
i = 0;
discardv[i] = "rm";
++i;
discardv[i] = "-f";
++i;
discardv[i] = session_file;
prop3.name = SmCloneCommand;
prop3.type = SmLISTofARRAY8;
prop3.vals = g_new (SmPropValue, i);
i = 0;
while (clonev[i])
{
prop3.vals[i].value = discardv[i];
prop3.vals[i].length = strlen (discardv[i]);
++i;
}
prop3.num_vals = i;
props[0] = &prop1;
props[1] = &prop2;
props[2] = &prop3;
SmcSetProperties (session_connection, 3, props);
g_free (session_file);
}
/* The remaining code in this file actually loads/saves the session,
* while the code above this comment handles chatting with the
* session manager.
*/
static void
save_state (void)
{
char *metacity_dir;
char *session_dir;
char *session_file;
FILE *outfile;
GSList *displays;
GSList *display_iter;
g_assert (client_id);
outfile = NULL;
metacity_dir = g_strconcat (g_get_home_dir (), "/.metacity",
NULL);
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)
{
meta_warning (_("Could not create directory '%s': %s\n"),
metacity_dir, g_strerror (errno));
}
if (mkdir (session_dir, 0700) < 0 &&
errno != EEXIST)
{
meta_warning (_("Could not create directory '%s': %s\n"),
session_dir, g_strerror (errno));
}
meta_verbose ("Saving session to '%s'\n", session_file);
outfile = fopen (session_file, "w");
if (outfile == NULL)
{
meta_warning (_("Could not open session file '%s' for writing: %s\n"),
session_file, g_strerror (errno));
goto out;
}
/* The file format is:
* <metacity_session id="foo">
* <window id="bar" class="XTerm" name="xterm" title="/foo/bar" role="blah">
* <workspace>2</workspace>
* <workspace>4</workspace>
* <sticky/>
* <geometry x="100" y="100" width="200" height="200" gravity="northwest"/>
* </window>
* </metacity_session>
*/
/* FIXME we are putting non-UTF-8 in here. */
fprintf (outfile, "<metacity_session id=\"%s\">\n",
client_id);
displays = meta_displays_list ();
display_iter = displays;
while (display_iter != NULL)
{
GSList *windows;
GSList *tmp;
windows = meta_display_list_windows (display_iter->data);
tmp = windows;
while (tmp != NULL)
{
MetaWindow *window;
window = tmp->data;
if (window->sm_client_id)
{
meta_verbose ("Saving session managed window %s, client ID '%s'\n",
window->desc, window->sm_client_id);
fprintf (outfile,
" <window id=\"%s\" class=\"%s\" name=\"%s\" title=\"%s\" role=\"%s\">\n",
window->sm_client_id,
window->res_class ? window->res_class : "",
window->res_name ? window->res_name : "",
window->title ? window->title : "",
window->role ? window->role : "");
/* Sticky */
if (window->on_all_workspaces)
fputs (" <sticky/>\n", outfile);
/* Workspaces we're on */
{
GSList *w;
w = window->workspaces;
while (w != NULL)
{
int n;
n = meta_workspace_screen_index (w->data);
fprintf (outfile,
"<workspace>%d</workspace>\n", n);
w = w->next;
}
}
fputs (" </window>\n", outfile);
}
else
{
meta_verbose ("Not saving window '%s', not session managed\n",
window->desc);
}
tmp = tmp->next;
}
g_slist_free (windows);
display_iter = display_iter->next;
}
/* don't need to free displays */
displays = NULL;
fputs ("</metacity_session>\n", outfile);
out:
if (outfile)
{
if (fclose (outfile) != 0)
{
meta_warning (_("Error writing session file '%s': %s\n"),
session_file, g_strerror (errno));
}
}
g_free (metacity_dir);
g_free (session_dir);
g_free (session_file);
}
static void
load_state (const char *previous_id)
{
}
void
meta_window_lookup_saved_state (MetaWindow *window,
MetaWindowSessionInfo *info)
{
SmcSetProperties (session_connection, 2, props);
}
#endif /* HAVE_SM */

View File

@ -24,25 +24,20 @@
#include "window.h"
typedef struct _MetaSessionInfo MetaSessionInfo;
typedef struct _MetaWindowSessionInfo MetaWindowSessionInfo;
struct _MetaSessionInfo
struct _MetaWindowSessionInfo
{
/* In -geometry format; x, y are affected by gravity, width, height
* are to be multiplied by resize increments, etc. This way we're
* robust against theme changes, client resize inc changes, client
* base size changes, and so on.
*/
MetaRectangle rect;
/* A per-screen index (_NET_WM_DESKTOP) */
int workspace;
};
MetaSessionInfo* meta_window_lookup_session_info (MetaWindow *window);
void meta_window_lookup_saved_state (MetaWindow *window,
MetaWindowSessionInfo *info);
void meta_session_init (const char *previous_id);
#endif