diff --git a/src/run-metacity.sh b/src/run-metacity.sh index a1aa05019..0919c9423 100755 --- a/src/run-metacity.sh +++ b/src/run-metacity.sh @@ -40,5 +40,5 @@ if test -z "$ONLY_WM"; then fi if test -z "$ONLY_SETUP"; then - METACITY_UISLAVE_DIR=./uislave METACITY_DISPLAY=:1 exec unst libtool --mode=execute $DEBUG ./metacity $OPTIONS + METACITY_DISPLAY=:1 exec unst libtool --mode=execute $DEBUG ./metacity $OPTIONS fi diff --git a/src/session.c b/src/session.c index bb9b72672..980a8b635 100644 --- a/src/session.c +++ b/src/session.c @@ -448,7 +448,7 @@ set_clone_restart_commands (void) char *session_file; session_file = g_strconcat (g_get_home_dir (), - ".metacity/sessions/", + "/.metacity/sessions/", client_id, NULL); @@ -701,7 +701,7 @@ save_state (void) int n; n = meta_workspace_screen_index (w->data); fprintf (outfile, - "\n", n); + " \n", n); w = w->next; } @@ -796,8 +796,8 @@ load_state (const char *previous_id) char *session_file; session_file = g_strconcat (g_get_home_dir (), - ".metacity/sessions/", - client_id, + "/.metacity/sessions/", + previous_id, NULL); error = NULL; @@ -845,7 +845,7 @@ load_state (const char *previous_id) g_free (text); } - +/* FIXME this isn't very robust against bogus session files */ static void start_element_handler (GMarkupParseContext *context, const gchar *element_name, @@ -858,7 +858,11 @@ start_element_handler (GMarkupParseContext *context, pd = user_data; - if (strcmp (element_name, "window") == 0) + if (strcmp (element_name, "metacity_session") == 0) + { + /* do nothing */ + } + else if (strcmp (element_name, "window") == 0) { int i; @@ -1051,8 +1055,7 @@ get_possible_matches (MetaWindow *window) info = tmp->data; - if (both_null_or_matching (info->id, - window->sm_client_id) && + if (both_null_or_matching (info->id, window->sm_client_id) && both_null_or_matching (info->res_class, window->res_class) && both_null_or_matching (info->res_name, window->res_name) && both_null_or_matching (info->role, window->role)) @@ -1065,7 +1068,37 @@ get_possible_matches (MetaWindow *window) retval = g_slist_prepend (retval, info); } - + else + { + if (meta_is_verbose ()) + { + if (!both_null_or_matching (info->id, window->sm_client_id)) + meta_verbose ("Window %s has SM client ID %s, saved state has %s, no match\n", + window->desc, + window->sm_client_id ? window->sm_client_id : "(none)", + info->id ? info->id : "(none)"); + else if (!both_null_or_matching (info->res_class, window->res_class)) + meta_verbose ("Window %s has class %s doesn't match saved class %s, no match\n", + window->desc, + window->res_class ? window->res_class : "(none)", + info->res_class ? info->res_class : "(none)"); + + else if (!both_null_or_matching (info->res_name, window->res_name)) + meta_verbose ("Window %s has name %s doesn't match saved name %s, no match\n", + window->desc, + window->res_name ? window->res_name : "(none)", + info->res_name ? info->res_name : "(none)"); + else if (!both_null_or_matching (info->role, window->role)) + meta_verbose ("Window %s has role %s doesn't match saved role %s, no match\n", + window->desc, + window->role ? window->role : "(none)", + info->role ? info->role : "(none)"); + else + meta_verbose ("???? should not happen - window %s doesn't match saved state %s for no good reason\n", + window->desc, info->id); + } + } + tmp = tmp->next; } @@ -1129,14 +1162,21 @@ meta_window_lookup_saved_state (MetaWindow *window) * situations other than on session restore. */ if (window->sm_client_id == NULL) - return NULL; + { + meta_verbose ("Window %s is not session managed, not checking for saved state\n", window->desc); + return NULL; + } possibles = get_possible_matches (window); if (possibles == NULL) - return NULL; + { + meta_verbose ("Window %s has no possible matches in the list of saved window states\n", + window->desc); + return NULL; + } - info = find_best_match (possibles, window); + info = find_best_match (possibles, window); g_slist_free (possibles); diff --git a/src/session.h b/src/session.h index 3ec3eccea..7250a5a84 100644 --- a/src/session.h +++ b/src/session.h @@ -28,14 +28,39 @@ typedef struct _MetaWindowSessionInfo MetaWindowSessionInfo; struct _MetaWindowSessionInfo { - int workspace; + /* Fields we use to match against */ + char *id; + char *res_class; + char *res_name; + char *title; + char *role; + MetaWindowType type; + + /* Information we restore */ + + GSList *workspace_indices; + + /* width/height should be multiplied by resize inc and + * added to base size; position should be interpreted in + * light of gravity. This preserves semantics of the + * window size/pos, even if fonts/themes change, etc. + */ + int gravity; + MetaRectangle rect; + guint on_all_workspaces : 1; + + guint geometry_set : 1; + guint on_all_workspaces_set : 1; }; -void meta_window_lookup_saved_state (MetaWindow *window, - MetaWindowSessionInfo *info); +/* If lookup_saved_state returns something, it should be used, + * and then released when you're done with it. + */ +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 *previous_id); #endif diff --git a/src/window.c b/src/window.c index 37cfda0b4..35649dbe7 100644 --- a/src/window.c +++ b/src/window.c @@ -28,6 +28,7 @@ #include "keybindings.h" #include "ui.h" #include "place.h" +#include "session.h" #include @@ -86,6 +87,10 @@ static gboolean get_cardinal (MetaDisplay *display, void meta_window_unqueue_calc_showing (MetaWindow *window); +static void meta_window_apply_session_info (MetaWindow *window, + const MetaWindowSessionInfo *info); + + MetaWindow* meta_window_new (MetaDisplay *display, Window xwindow, gboolean must_be_viewable) @@ -451,6 +456,19 @@ meta_window_new (MetaDisplay *display, Window xwindow, meta_stack_add (window->screen->stack, window); + /* Now try applying saved stuff from the session */ + { + const MetaWindowSessionInfo *info; + + info = meta_window_lookup_saved_state (window); + + if (info) + { + meta_window_apply_session_info (window, info); + meta_window_release_saved_state (info); + } + } + /* Sync stack changes */ meta_stack_thaw (window->screen->stack); @@ -461,6 +479,72 @@ meta_window_new (MetaDisplay *display, Window xwindow, return window; } +/* This function should only be called from the end of meta_window_new () */ +static void +meta_window_apply_session_info (MetaWindow *window, + const MetaWindowSessionInfo *info) +{ + if (info->on_all_workspaces_set) + { + window->on_all_workspaces = info->on_all_workspaces; + meta_verbose ("Restoring sticky state %d for window %s\n", + window->on_all_workspaces, window->desc); + } + + if (info->workspace_indices) + { + GSList *tmp; + GSList *spaces; + + spaces = NULL; + + tmp = info->workspace_indices; + while (tmp != NULL) + { + MetaWorkspace *space; + + space = + meta_display_get_workspace_by_screen_index (window->display, + window->screen, + GPOINTER_TO_INT (tmp->data)); + + if (space) + spaces = g_slist_prepend (spaces, space); + + tmp = tmp->next; + } + + if (spaces) + { + /* This briefly breaks the invariant that we are supposed + * to always be on some workspace. But we paranoically + * ensured that one of the workspaces from the session was + * indeed valid, so we know we'll go right back to one. + */ + while (window->workspaces) + meta_workspace_remove_window (window->workspaces->next->data, window); + + tmp = spaces; + while (tmp != NULL) + { + MetaWorkspace *space; + + space = tmp->data; + + meta_workspace_add_window (space, window); + + meta_verbose ("Restoring saved window %s to workspace %d\n", + window->desc, + meta_workspace_screen_index (space)); + + tmp = tmp->next; + } + + g_slist_free (spaces); + } + } +} + void meta_window_free (MetaWindow *window) {