diff --git a/README b/README index 1324bc6f6..67511bb92 100644 --- a/README +++ b/README @@ -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 diff --git a/src/session.c b/src/session.c index 15258516c..9f5c1cd8c 100644 --- a/src/session.c +++ b/src/session.c @@ -32,19 +32,27 @@ meta_session_init (const char *previous_id) #include #include #include +#include +#include #include +#include #include #include #include #include #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, @@ -186,6 +194,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 (); @@ -221,7 +232,11 @@ meta_session_init (const char *previous_id) return; } else - meta_verbose ("Obtained session ID '%s'\n", client_id); + { + 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,9 +442,16 @@ 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) */ prop1.name = SmRestartCommand; @@ -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; - - SmcSetProperties (session_connection, 2, props); + 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: + * + * + * 2 + * 4 + * + * + * + * + */ + + /* FIXME we are putting non-UTF-8 in here. */ + + fprintf (outfile, "\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, + " \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 (" \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, + "%d\n", n); + + w = w->next; + } + } + + fputs (" \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 ("\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) +{ + + } #endif /* HAVE_SM */ diff --git a/src/session.h b/src/session.h index 6cca5d4d2..3ec3eccea 100644 --- a/src/session.h +++ b/src/session.h @@ -24,24 +24,19 @@ #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); -void meta_session_init (const char *previous_id); #endif