refactor all the session stuff. yay, it works properly now.
make sessions save the desktop being displayed. can we get rid of config_firstdesk now? refactor startup a bit. focus the window that was focused when we were restarted. have clients properly restore their session state. add undecorated to the saved session state for clients.
This commit is contained in:
parent
a6aaabe62c
commit
1bf9de3809
9 changed files with 540 additions and 341 deletions
152
openbox/client.c
152
openbox/client.c
|
@ -83,12 +83,13 @@ static void client_change_state(ObClient *self);
|
|||
static void client_change_wm_state(ObClient *self);
|
||||
static void client_apply_startup_state(ObClient *self, gint x, gint y);
|
||||
static void client_restore_session_state(ObClient *self);
|
||||
static void client_restore_session_stacking(ObClient *self);
|
||||
static gboolean client_restore_session_stacking(ObClient *self);
|
||||
static ObAppSettings *client_get_settings_state(ObClient *self);
|
||||
static void client_update_transient_tree(ObClient *self,
|
||||
ObGroup *oldgroup, ObGroup *newgroup,
|
||||
ObClient* oldparent,
|
||||
ObClient *newparent);
|
||||
static void client_present(ObClient *self, gboolean here, gboolean raise);
|
||||
|
||||
void client_startup(gboolean reconfig)
|
||||
{
|
||||
|
@ -321,10 +322,10 @@ void client_manage(Window window)
|
|||
grab_server(FALSE);
|
||||
|
||||
stacking_add_nonintrusive(CLIENT_AS_WINDOW(self));
|
||||
client_restore_session_stacking(self);
|
||||
|
||||
/* focus the new window? */
|
||||
if (ob_state() != OB_STATE_STARTING &&
|
||||
(!self->session || self->session->focused) &&
|
||||
!self->iconic &&
|
||||
/* this means focus=true for window is same as config_focus_new=true */
|
||||
((config_focus_new || (settings && settings->focus == 1)) ||
|
||||
|
@ -377,6 +378,10 @@ void client_manage(Window window)
|
|||
*/
|
||||
ob_debug("placing window 0x%x at %d, %d with size %d x %d\n",
|
||||
self->window, newx, newy, self->area.width, self->area.height);
|
||||
if (self->session)
|
||||
ob_debug("session requested %d %d\n",
|
||||
self->session->x, self->session->y);
|
||||
|
||||
client_apply_startup_state(self, newx, newy);
|
||||
|
||||
mouse_grab_for_client(self, TRUE);
|
||||
|
@ -443,7 +448,8 @@ void client_manage(Window window)
|
|||
Also if you don't have focus_new enabled, then it's going to get
|
||||
raised to the top. Legacy begets legacy I guess?
|
||||
*/
|
||||
client_raise(self);
|
||||
if (!client_restore_session_stacking(self))
|
||||
client_raise(self);
|
||||
}
|
||||
|
||||
/* this has to happen before we try focus the window, but we want it to
|
||||
|
@ -456,8 +462,10 @@ void client_manage(Window window)
|
|||
a window maps since its not based on an action from the user like
|
||||
clicking a window to activate it. so keep the new window out of the way
|
||||
but do focus it. */
|
||||
if (activate)
|
||||
client_activate(self, FALSE, TRUE);
|
||||
if (activate) {
|
||||
gboolean stacked = client_restore_session_stacking(self);
|
||||
client_present(self, FALSE, !stacked);
|
||||
}
|
||||
|
||||
/* add to client list/map */
|
||||
client_list = g_list_append(client_list, self);
|
||||
|
@ -685,13 +693,22 @@ static void client_restore_session_state(ObClient *self)
|
|||
{
|
||||
GList *it;
|
||||
|
||||
if (!(it = session_state_find(self)))
|
||||
ob_debug_type(OB_DEBUG_SM,
|
||||
"Restore session for client %s\n", self->title);
|
||||
|
||||
if (!(it = session_state_find(self))) {
|
||||
ob_debug_type(OB_DEBUG_SM,
|
||||
"Session data not found for client %s\n", self->title);
|
||||
return;
|
||||
}
|
||||
|
||||
self->session = it->data;
|
||||
|
||||
ob_debug_type(OB_DEBUG_SM, "Session data loaded for client %s\n",
|
||||
self->title);
|
||||
|
||||
RECT_SET_POINT(self->area, self->session->x, self->session->y);
|
||||
self->positioned = PPosition;
|
||||
self->positioned = USPosition;
|
||||
if (self->session->w > 0)
|
||||
self->area.width = self->session->w;
|
||||
if (self->session->h > 0)
|
||||
|
@ -713,28 +730,33 @@ static void client_restore_session_state(ObClient *self)
|
|||
self->below = self->session->below;
|
||||
self->max_horz = self->session->max_horz;
|
||||
self->max_vert = self->session->max_vert;
|
||||
self->undecorated = self->session->undecorated;
|
||||
}
|
||||
|
||||
static void client_restore_session_stacking(ObClient *self)
|
||||
static gboolean client_restore_session_stacking(ObClient *self)
|
||||
{
|
||||
GList *it;
|
||||
GList *it, *mypos;
|
||||
|
||||
if (!self->session) return;
|
||||
if (!self->session) return FALSE;
|
||||
|
||||
it = g_list_find(session_saved_state, self->session);
|
||||
for (it = g_list_previous(it); it; it = g_list_previous(it)) {
|
||||
mypos = g_list_find(session_saved_state, self->session);
|
||||
if (!mypos) return FALSE;
|
||||
|
||||
/* start above me and look for the first client */
|
||||
for (it = g_list_previous(mypos); it; it = g_list_previous(it)) {
|
||||
GList *cit;
|
||||
|
||||
for (cit = client_list; cit; cit = g_list_next(cit))
|
||||
if (session_state_cmp(it->data, cit->data))
|
||||
break;
|
||||
if (cit) {
|
||||
client_calc_layer(self);
|
||||
stacking_below(CLIENT_AS_WINDOW(self),
|
||||
CLIENT_AS_WINDOW(cit->data));
|
||||
break;
|
||||
for (cit = client_list; cit; cit = g_list_next(cit)) {
|
||||
ObClient *c = cit->data;
|
||||
/* found a client that was in the session, so go below it */
|
||||
if (c->session == it->data) {
|
||||
stacking_below(CLIENT_AS_WINDOW(self),
|
||||
CLIENT_AS_WINDOW(cit->data));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void client_move_onscreen(ObClient *self, gboolean rude)
|
||||
|
@ -3252,6 +3274,47 @@ gboolean client_focus(ObClient *self)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/*! Present the client to the user.
|
||||
@param raise If the client should be raised or not. You should only set
|
||||
raise to false if you don't care if the window is completely
|
||||
hidden.
|
||||
*/
|
||||
static void client_present(ObClient *self, gboolean here, gboolean raise)
|
||||
{
|
||||
/* if using focus_delay, stop the timer now so that focus doesn't
|
||||
go moving on us */
|
||||
event_halt_focus_delay();
|
||||
|
||||
if (client_normal(self) && screen_showing_desktop)
|
||||
screen_show_desktop(FALSE, FALSE);
|
||||
if (self->iconic)
|
||||
client_iconify(self, FALSE, here);
|
||||
if (self->desktop != DESKTOP_ALL &&
|
||||
self->desktop != screen_desktop)
|
||||
{
|
||||
if (here)
|
||||
client_set_desktop(self, screen_desktop, FALSE);
|
||||
else
|
||||
screen_set_desktop(self->desktop);
|
||||
} else if (!self->frame->visible)
|
||||
/* if its not visible for other reasons, then don't mess
|
||||
with it */
|
||||
return;
|
||||
if (self->shaded)
|
||||
client_shade(self, FALSE);
|
||||
|
||||
client_focus(self);
|
||||
|
||||
if (raise) {
|
||||
/* we do this as an action here. this is rather important. this is
|
||||
because we want the results from the focus change to take place
|
||||
BEFORE we go about raising the window. when a fullscreen window
|
||||
loses focus, we need this or else the raise wont be able to raise
|
||||
above the to-lose-focus fullscreen window. */
|
||||
client_raise(self);
|
||||
}
|
||||
}
|
||||
|
||||
void client_activate(ObClient *self, gboolean here, gboolean user)
|
||||
{
|
||||
guint32 last_time = focus_client ? focus_client->user_time : CurrentTime;
|
||||
|
@ -3274,36 +3337,7 @@ void client_activate(ObClient *self, gboolean here, gboolean user)
|
|||
if (event_curtime != CurrentTime)
|
||||
self->user_time = event_curtime;
|
||||
|
||||
/* if using focus_delay, stop the timer now so that focus doesn't
|
||||
go moving on us */
|
||||
event_halt_focus_delay();
|
||||
|
||||
if (client_normal(self) && screen_showing_desktop)
|
||||
screen_show_desktop(FALSE, FALSE);
|
||||
if (self->iconic)
|
||||
client_iconify(self, FALSE, here);
|
||||
if (self->desktop != DESKTOP_ALL &&
|
||||
self->desktop != screen_desktop)
|
||||
{
|
||||
if (here)
|
||||
client_set_desktop(self, screen_desktop, FALSE);
|
||||
else
|
||||
screen_set_desktop(self->desktop);
|
||||
} else if (!self->frame->visible)
|
||||
/* if its not visible for other reasons, then don't mess
|
||||
with it */
|
||||
return;
|
||||
if (self->shaded)
|
||||
client_shade(self, FALSE);
|
||||
|
||||
client_focus(self);
|
||||
|
||||
/* we do this as an action here. this is rather important. this is
|
||||
because we want the results from the focus change to take place
|
||||
BEFORE we go about raising the window. when a fullscreen window
|
||||
loses focus, we need this or else the raise wont be able to raise
|
||||
above the to-lose-focus fullscreen window. */
|
||||
client_raise(self);
|
||||
client_present(self, here, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3517,15 +3551,25 @@ void client_update_sm_client_id(ObClient *self)
|
|||
self->sm_client_id = NULL;
|
||||
|
||||
if (!PROP_GETS(self->window, sm_client_id, locale, &self->sm_client_id) &&
|
||||
self->group)
|
||||
PROP_GETS(self->group->leader, sm_client_id, locale,
|
||||
&self->sm_client_id);
|
||||
self->group) {
|
||||
ob_debug_type(OB_DEBUG_SM, "Client %s does not have session id\n",
|
||||
self->title);
|
||||
if (!PROP_GETS(self->group->leader, sm_client_id, locale,
|
||||
&self->sm_client_id)) {
|
||||
ob_debug_type(OB_DEBUG_SM, "Client %s does not have session id on "
|
||||
"group window\n", self->title);
|
||||
} else
|
||||
ob_debug_type(OB_DEBUG_SM, "Client %s has session id on "
|
||||
"group window\n", self->title);
|
||||
} else
|
||||
ob_debug_type(OB_DEBUG_SM, "Client %s has session id\n",
|
||||
self->title);
|
||||
}
|
||||
|
||||
#define WANT_EDGE(cur, c) \
|
||||
if(cur == c) \
|
||||
continue; \
|
||||
if(!client_normal(cur)) \
|
||||
if(!client_normal(cur)) \
|
||||
continue; \
|
||||
if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL) \
|
||||
continue; \
|
||||
|
|
|
@ -64,6 +64,9 @@ void ob_debug_type(ObDebugType type, const gchar *a, ...)
|
|||
case OB_DEBUG_APP_BUGS:
|
||||
fprintf(stderr, "APPLICATION BUG: ");
|
||||
break;
|
||||
case OB_DEBUG_SM:
|
||||
fprintf(stderr, "SESSION: ");
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ void ob_debug(const gchar *a, ...);
|
|||
typedef enum {
|
||||
OB_DEBUG_FOCUS,
|
||||
OB_DEBUG_APP_BUGS,
|
||||
OB_DEBUG_SM,
|
||||
OB_DEBUG_TYPE_NUM
|
||||
} ObDebugType;
|
||||
|
||||
|
|
|
@ -232,24 +232,19 @@ ObClient* focus_fallback_target(gboolean allow_refocus, ObClient *old)
|
|||
ObClient *c = it->data;
|
||||
/* fallback focus to a window if:
|
||||
1. it is actually focusable, cuz if it's not then we're sending
|
||||
focus off to nothing
|
||||
2. it is validated. if the window is about to disappear, then
|
||||
don't try focus it.
|
||||
3. it is visible on the current desktop. this ignores
|
||||
omnipresent windows, which are problematic in their own rite.
|
||||
4. it's not iconic
|
||||
5. it is a normal type window, don't fall back onto a dock or
|
||||
focus off to nothing. this includes if it is visible right now
|
||||
2. it is on the current desktop. this ignores omnipresent
|
||||
windows, which are problematic in their own rite.
|
||||
3. it is a normal type window, don't fall back onto a dock or
|
||||
a splashscreen or a desktop window (save the desktop as a
|
||||
backup fallback though)
|
||||
*/
|
||||
if (client_can_focus(c) && !c->iconic)
|
||||
if (client_can_focus(c))
|
||||
{
|
||||
if (c->desktop == screen_desktop && client_normal(c)) {
|
||||
ob_debug_type(OB_DEBUG_FOCUS, "found in focus order\n");
|
||||
return it->data;
|
||||
} else if ((c->desktop == screen_desktop ||
|
||||
c->desktop == DESKTOP_ALL) &&
|
||||
c->type == OB_CLIENT_TYPE_DESKTOP &&
|
||||
} else if (c->type == OB_CLIENT_TYPE_DESKTOP &&
|
||||
desktop == NULL)
|
||||
desktop = c;
|
||||
}
|
||||
|
|
|
@ -81,6 +81,9 @@ ObMainLoop *ob_main_loop;
|
|||
Display *ob_display;
|
||||
gint ob_screen;
|
||||
gboolean ob_replace_wm = FALSE;
|
||||
gboolean ob_sm_use = TRUE;
|
||||
gchar *ob_sm_id = NULL;
|
||||
gchar *ob_sm_save_file = NULL;
|
||||
|
||||
static ObState state;
|
||||
static gboolean xsync = FALSE;
|
||||
|
@ -95,7 +98,9 @@ static gboolean being_replaced = FALSE;
|
|||
static gchar *config_type = NULL;
|
||||
|
||||
static void signal_handler(gint signal, gpointer data);
|
||||
static void parse_args(gint argc, gchar **argv);
|
||||
static void parse_env(char **argv0);
|
||||
static void remove_args(gint *argc, gchar **argv, gint index, gint num);
|
||||
static void parse_args(gint *argc, gchar **argv);
|
||||
static Cursor load_cursor(const gchar *name, guint fontval);
|
||||
|
||||
gint main(gint argc, gchar **argv)
|
||||
|
@ -115,8 +120,9 @@ gint main(gint argc, gchar **argv)
|
|||
g_message(_("Unable to change to home directory '%s': %s"),
|
||||
g_get_home_dir(), g_strerror(errno));
|
||||
|
||||
/* parse out command line args */
|
||||
parse_args(argc, argv);
|
||||
/* parse out environment and command line args */
|
||||
parse_env(&argv[0]);
|
||||
parse_args(&argc, argv);
|
||||
|
||||
if (!remote_control) {
|
||||
parse_paths_startup();
|
||||
|
@ -124,6 +130,7 @@ gint main(gint argc, gchar **argv)
|
|||
session_startup(argc, argv);
|
||||
}
|
||||
|
||||
|
||||
ob_display = XOpenDisplay(NULL);
|
||||
if (ob_display == NULL)
|
||||
ob_exit_with_error("Failed to open the display.");
|
||||
|
@ -284,9 +291,21 @@ gint main(gint argc, gchar **argv)
|
|||
menu_frame_startup(reconfigure);
|
||||
|
||||
if (!reconfigure) {
|
||||
guint32 xid;
|
||||
ObWindow *w;
|
||||
|
||||
/* get all the existing windows */
|
||||
client_manage_all();
|
||||
focus_fallback(TRUE);
|
||||
focus_nothing();
|
||||
|
||||
/* focus what was focused if a wm was already running */
|
||||
if (PROP_GET32(RootWindow(ob_display, ob_screen),
|
||||
net_active_window, window, &xid) &&
|
||||
(w = g_hash_table_lookup(window_map, &xid)) &&
|
||||
WINDOW_IS_CLIENT(w))
|
||||
{
|
||||
client_focus(WINDOW_AS_CLIENT(w));
|
||||
}
|
||||
} else {
|
||||
GList *it;
|
||||
|
||||
|
@ -359,12 +378,33 @@ gint main(gint argc, gchar **argv)
|
|||
}
|
||||
}
|
||||
|
||||
/* we remove the session arguments from argv, so put them back */
|
||||
if (ob_sm_save_file != NULL) {
|
||||
guint l = g_strv_length(argv);
|
||||
argv = g_renew(gchar*, argv, l+2);
|
||||
argv[l] = g_strdup("--sm-save-file");
|
||||
argv[l+1] = ob_sm_save_file;
|
||||
argv[l+2] = NULL;
|
||||
}
|
||||
if (ob_sm_id != NULL) {
|
||||
guint l = g_strv_length(argv);
|
||||
argv = g_renew(gchar*, argv, l+2);
|
||||
argv[l] = g_strdup("--sm-client-id");
|
||||
argv[l+1] = ob_sm_id;
|
||||
argv[l+2] = NULL;
|
||||
}
|
||||
|
||||
/* re-run me */
|
||||
execvp(argv[0], argv); /* try how we were run */
|
||||
execlp(argv[0], g_path_get_basename(argv[0]),
|
||||
(char *)NULL); /* last resort */
|
||||
}
|
||||
|
||||
/* free stuff passed in from the command line or environment */
|
||||
g_free(ob_sm_save_file);
|
||||
g_free(ob_sm_id);
|
||||
g_free(config_type);
|
||||
|
||||
return exitcode;
|
||||
}
|
||||
|
||||
|
@ -405,30 +445,52 @@ static void print_version()
|
|||
static void print_help()
|
||||
{
|
||||
g_print(_("Syntax: openbox [options]\n"));
|
||||
g_print(_("\nOptions:\n\n"));
|
||||
g_print(_("\nOptions:\n"));
|
||||
g_print(_(" --config TYPE Specify the configuration profile to use\n"));
|
||||
#ifdef USE_SM
|
||||
g_print(_(" --sm-disable Disable connection to session manager\n"));
|
||||
g_print(_(" --sm-client-id ID Specify session management ID\n"));
|
||||
g_print(_(" --sm-save-file FILE Specify file to load a saved session from\n"));
|
||||
g_print(_(" --sm-disable Disable connection to the session manager\n"));
|
||||
#endif
|
||||
g_print(_(" --replace Replace the currently running window manager\n"));
|
||||
g_print(_(" --help Display this help and exit\n"));
|
||||
g_print(_(" --version Display the version and exit\n"));
|
||||
g_print(_("\nPassing messages to a running Openbox instance:\n\n"));
|
||||
g_print(_("\nPassing messages to a running Openbox instance:\n"));
|
||||
g_print(_(" --reconfigure Reload Openbox's configuration\n"));
|
||||
g_print(_("\nDebugging options:\n\n"));
|
||||
g_print(_("\nOptions for internal use:\n"));
|
||||
g_print(_(" --sm-save-file FILE Specify file to load a saved session from\n"));
|
||||
g_print(_(" --sm-client-id ID Specify session management ID\n"));
|
||||
g_print(_("\nDebugging options:\n"));
|
||||
g_print(_(" --sync Run in synchronous mode\n"));
|
||||
g_print(_(" --debug Display debugging output\n"));
|
||||
g_print(_(" --debug-focus Display debugging output for focus handling\n"));
|
||||
g_print(_("\nPlease report bugs at %s\n\n"), PACKAGE_BUGREPORT);
|
||||
g_print(_("\nPlease report bugs at %s\n"), PACKAGE_BUGREPORT);
|
||||
}
|
||||
|
||||
static void parse_args(gint argc, gchar **argv)
|
||||
static void parse_env(gchar **argv0)
|
||||
{
|
||||
const char *c;
|
||||
|
||||
/* pretend we are this other application */
|
||||
if ((c = getenv("OPENBOX_RESTART_BINARY")))
|
||||
*argv0 = g_strdup(c);
|
||||
unsetenv("OPENBOX_RESTART_BINARY");
|
||||
}
|
||||
|
||||
static void remove_args(gint *argc, gchar **argv, gint index, gint num)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 1; i < argc; ++i) {
|
||||
for (i = index; i < index + num; ++i)
|
||||
argv[i] = argv[i+num];
|
||||
for (; i < *argc; ++i)
|
||||
argv[i] = NULL;
|
||||
*argc -= num;
|
||||
}
|
||||
|
||||
static void parse_args(gint *argc, gchar **argv)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 1; i < *argc; ++i) {
|
||||
if (!strcmp(argv[i], "--version")) {
|
||||
print_version();
|
||||
exit(0);
|
||||
|
@ -443,23 +505,54 @@ static void parse_args(gint argc, gchar **argv)
|
|||
xsync = TRUE;
|
||||
} else if (!strcmp(argv[i], "--debug")) {
|
||||
ob_debug_show_output(TRUE);
|
||||
ob_debug_enable(OB_DEBUG_SM, TRUE);
|
||||
ob_debug_enable(OB_DEBUG_APP_BUGS, TRUE);
|
||||
} else if (!strcmp(argv[i], "--debug-focus")) {
|
||||
ob_debug_show_output(TRUE);
|
||||
ob_debug_enable(OB_DEBUG_SM, TRUE);
|
||||
ob_debug_enable(OB_DEBUG_APP_BUGS, TRUE);
|
||||
ob_debug_enable(OB_DEBUG_FOCUS, TRUE);
|
||||
} else if (!strcmp(argv[i], "--reconfigure")) {
|
||||
remote_control = 1;
|
||||
/* don't make this do anything if it's not in --help ..
|
||||
} else if (!strcmp(argv[i], "--restart")) {
|
||||
remote_control = 2;
|
||||
*/
|
||||
} else if (!strcmp(argv[i], "--config")) {
|
||||
if (i == argc - 1) /* no args left */
|
||||
g_printerr(_("--config-file requires an argument\n"));
|
||||
if (i == *argc - 1) /* no args left */
|
||||
g_printerr(_("--config requires an argument\n"));
|
||||
else {
|
||||
config_type = g_strdup(argv[i+1]);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
#ifdef USE_SM
|
||||
else if (!strcmp(argv[i], "--sm-save-file")) {
|
||||
if (i == *argc - 1) /* no args left */
|
||||
g_printerr(_("--sm-save-file requires an argument\n"));
|
||||
else {
|
||||
ob_sm_save_file = g_strdup(argv[i+1]);
|
||||
remove_args(argc, argv, i, 2);
|
||||
--i; /* this arg was removed so go back */
|
||||
}
|
||||
} else if (!strcmp(argv[i], "--sm-client-id")) {
|
||||
if (i == *argc - 1) /* no args left */
|
||||
g_printerr(_("--sm-client-id requires an argument\n"));
|
||||
else {
|
||||
ob_sm_id = g_strdup(argv[i+1]);
|
||||
remove_args(argc, argv, i, 2);
|
||||
--i; /* this arg was removed so go back */
|
||||
}
|
||||
} else if (!strcmp(argv[i], "--sm-disable")) {
|
||||
ob_sm_use = FALSE;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
/* this is a memleak.. oh well.. heh */
|
||||
gchar *err = g_strdup_printf
|
||||
("Invalid command line argument '%s'\n", argv[i]);
|
||||
ob_exit_with_error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,8 +40,11 @@ extern Display *ob_display;
|
|||
/*! The number of the screen on which we're running */
|
||||
extern gint ob_screen;
|
||||
|
||||
extern gchar *ob_sm_id;
|
||||
extern gboolean ob_sm_use;
|
||||
extern gchar *ob_sm_id;
|
||||
/* This save_file will get pass to ourselves if we restart too! So we won't
|
||||
make a new file every time, yay. */
|
||||
extern gchar *ob_sm_save_file;
|
||||
extern gboolean ob_replace_wm;
|
||||
|
||||
/* The state of execution of the window manager */
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "config.h"
|
||||
#include "screen.h"
|
||||
#include "client.h"
|
||||
#include "session.h"
|
||||
#include "frame.h"
|
||||
#include "event.h"
|
||||
#include "focus.h"
|
||||
|
@ -328,7 +329,10 @@ void screen_startup(gboolean reconfig)
|
|||
d < screen_num_desktops)
|
||||
{
|
||||
screen_set_desktop(d);
|
||||
} else
|
||||
} else if (session_desktop >= 0)
|
||||
screen_set_desktop(MIN((guint)session_desktop,
|
||||
screen_num_desktops));
|
||||
else
|
||||
screen_set_desktop(MIN(config_screen_firstdesk,
|
||||
screen_num_desktops) - 1);
|
||||
|
||||
|
|
|
@ -18,26 +18,24 @@
|
|||
|
||||
/* This session code is largely inspired by metacity code. */
|
||||
|
||||
#ifndef USE_SM
|
||||
|
||||
#include "session.h"
|
||||
#include "client.h"
|
||||
|
||||
GList *session_saved_state;
|
||||
struct _ObClient;
|
||||
|
||||
GList *session_saved_state = NULL;
|
||||
gint session_desktop = -1;
|
||||
|
||||
#ifndef USE_SM
|
||||
void session_startup(gint argc, gchar **argv) {}
|
||||
void session_shutdown(gboolean permanent) {}
|
||||
GList* session_state_find(ObClient *c) { return NULL; }
|
||||
gboolean session_state_cmp(ObSessionState *s, ObClient *c) { return FALSE; }
|
||||
void session_state_free(ObSessionState *state) {}
|
||||
|
||||
GList* session_state_find(struct _ObClient *c) { return NULL; }
|
||||
#else
|
||||
|
||||
#include "debug.h"
|
||||
#include "openbox.h"
|
||||
#include "session.h"
|
||||
#include "client.h"
|
||||
#include "prop.h"
|
||||
#include "screen.h"
|
||||
#include "gettext.h"
|
||||
#include "parser/parse.h"
|
||||
|
||||
|
@ -52,18 +50,24 @@ void session_state_free(ObSessionState *state) {}
|
|||
|
||||
#include <X11/SM/SMlib.h>
|
||||
|
||||
GList *session_saved_state;
|
||||
#define SM_ERR_LEN 1024
|
||||
|
||||
static gboolean sm_disable;
|
||||
static SmcConn sm_conn;
|
||||
static gchar *save_file;
|
||||
static gchar *sm_id;
|
||||
static gint sm_argc;
|
||||
static gchar **sm_argv;
|
||||
static gchar *sm_sessions_path;
|
||||
static SmcConn sm_conn;
|
||||
static gint sm_argc;
|
||||
static gchar **sm_argv;
|
||||
|
||||
static void session_load(gchar *path);
|
||||
static gboolean session_save();
|
||||
static gboolean session_connect();
|
||||
|
||||
static void session_load_file(gchar *path);
|
||||
static gboolean session_save_to_file();
|
||||
|
||||
static void session_setup_program();
|
||||
static void session_setup_user();
|
||||
static void session_setup_restart_style(gboolean restart);
|
||||
static void session_setup_pid();
|
||||
static void session_setup_priority();
|
||||
static void session_setup_clone_command();
|
||||
static void session_setup_restart_command();
|
||||
|
||||
static void sm_save_yourself(SmcConn conn, SmPointer data, gint save_type,
|
||||
Bool shutdown, gint interact_style, Bool fast);
|
||||
|
@ -71,223 +75,61 @@ static void sm_die(SmcConn conn, SmPointer data);
|
|||
static void sm_save_complete(SmcConn conn, SmPointer data);
|
||||
static void sm_shutdown_cancelled(SmcConn conn, SmPointer data);
|
||||
|
||||
static void save_commands()
|
||||
{
|
||||
SmProp *props[2];
|
||||
SmProp prop_cmd = { SmCloneCommand, SmLISTofARRAY8, 1, };
|
||||
SmProp prop_res = { SmRestartCommand, SmLISTofARRAY8 };
|
||||
gint i;
|
||||
|
||||
prop_cmd.vals = g_new(SmPropValue, sm_argc);
|
||||
prop_cmd.num_vals = sm_argc;
|
||||
for (i = 0; i < sm_argc; ++i) {
|
||||
prop_cmd.vals[i].value = sm_argv[i];
|
||||
prop_cmd.vals[i].length = strlen(sm_argv[i]);
|
||||
}
|
||||
|
||||
prop_res.vals = g_new(SmPropValue, sm_argc + 2);
|
||||
prop_res.num_vals = sm_argc + 2;
|
||||
for (i = 0; i < sm_argc; ++i) {
|
||||
prop_res.vals[i].value = sm_argv[i];
|
||||
prop_res.vals[i].length = strlen(sm_argv[i]);
|
||||
}
|
||||
|
||||
prop_res.vals[i].value = "--sm-save-file";
|
||||
prop_res.vals[i++].length = strlen("--sm-save-file");
|
||||
prop_res.vals[i].value = save_file;
|
||||
prop_res.vals[i++].length = strlen(save_file);
|
||||
|
||||
props[0] = &prop_res;
|
||||
props[1] = &prop_cmd;
|
||||
SmcSetProperties(sm_conn, 2, props);
|
||||
|
||||
g_free(prop_res.vals);
|
||||
g_free(prop_cmd.vals);
|
||||
}
|
||||
|
||||
static void remove_args(gint *argc, gchar ***argv, gint index, gint num)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = index; i < index + num; ++i)
|
||||
(*argv)[i] = (*argv)[i+num];
|
||||
*argc -= num;
|
||||
}
|
||||
|
||||
static void parse_args(gint *argc, gchar ***argv)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 1; i < *argc; ++i) {
|
||||
if (!strcmp((*argv)[i], "--sm-client-id")) {
|
||||
if (i == *argc - 1) /* no args left */
|
||||
g_printerr(_("--sm-client-id requires an argument\n"));
|
||||
else {
|
||||
sm_id = g_strdup((*argv)[i+1]);
|
||||
remove_args(argc, argv, i, 2);
|
||||
++i;
|
||||
}
|
||||
} else if (!strcmp((*argv)[i], "--sm-save-file")) {
|
||||
if (i == *argc - 1) /* no args left */
|
||||
g_printerr(_("--sm-save-file requires an argument\n"));
|
||||
else {
|
||||
save_file = g_strdup((*argv)[i+1]);
|
||||
remove_args(argc, argv, i, 2);
|
||||
++i;
|
||||
}
|
||||
} else if (!strcmp((*argv)[i], "--sm-disable")) {
|
||||
sm_disable = TRUE;
|
||||
remove_args(argc, argv, i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
static gboolean session_state_cmp(ObSessionState *s, ObClient *c);
|
||||
static void session_state_free(ObSessionState *state);
|
||||
|
||||
void session_startup(gint argc, gchar **argv)
|
||||
{
|
||||
#define SM_ERR_LEN 1024
|
||||
gchar *dir;
|
||||
|
||||
SmcCallbacks cb;
|
||||
gchar sm_err[SM_ERR_LEN];
|
||||
gint i;
|
||||
if (!ob_sm_use) return;
|
||||
|
||||
sm_argc = argc;
|
||||
sm_argv = g_new(gchar*, argc);
|
||||
for (i = 0; i < argc; ++i)
|
||||
sm_argv[i] = argv[i];
|
||||
sm_argv = argv;
|
||||
|
||||
parse_args(&sm_argc, &sm_argv);
|
||||
|
||||
if (sm_disable) {
|
||||
g_free(sm_argv);
|
||||
return;
|
||||
}
|
||||
|
||||
sm_sessions_path = g_build_filename(parse_xdg_data_home_path(),
|
||||
"openbox", "sessions", NULL);
|
||||
if (!parse_mkdir_path(sm_sessions_path, 0700)) {
|
||||
dir = g_build_filename(parse_xdg_data_home_path(),
|
||||
"openbox", "sessions", NULL);
|
||||
if (!parse_mkdir_path(dir, 0700)) {
|
||||
g_message(_("Unable to make directory '%s': %s"),
|
||||
sm_sessions_path, g_strerror(errno));
|
||||
dir, g_strerror(errno));
|
||||
}
|
||||
|
||||
if (save_file)
|
||||
session_load(save_file);
|
||||
else {
|
||||
if (ob_sm_save_file != NULL) {
|
||||
ob_debug_type(OB_DEBUG_SM, "Loading from session file %s\n",
|
||||
ob_sm_save_file);
|
||||
session_load_file(ob_sm_save_file);
|
||||
} else {
|
||||
gchar *filename;
|
||||
|
||||
/* this algo is from metacity */
|
||||
filename = g_strdup_printf("%d-%d-%u.obs",
|
||||
(gint) time(NULL),
|
||||
(gint) getpid(),
|
||||
filename = g_strdup_printf("%u-%u-%u.obs",
|
||||
(guint)time(NULL),
|
||||
(guint)getpid(),
|
||||
g_random_int());
|
||||
save_file = g_build_filename(sm_sessions_path, filename, NULL);
|
||||
ob_sm_save_file = g_build_filename(dir, filename, NULL);
|
||||
g_free(filename);
|
||||
}
|
||||
|
||||
cb.save_yourself.callback = sm_save_yourself;
|
||||
cb.save_yourself.client_data = NULL;
|
||||
|
||||
cb.die.callback = sm_die;
|
||||
cb.die.client_data = NULL;
|
||||
|
||||
cb.save_complete.callback = sm_save_complete;
|
||||
cb.save_complete.client_data = NULL;
|
||||
|
||||
cb.shutdown_cancelled.callback = sm_shutdown_cancelled;
|
||||
cb.shutdown_cancelled.client_data = NULL;
|
||||
|
||||
sm_conn = SmcOpenConnection(NULL, NULL, 1, 0,
|
||||
SmcSaveYourselfProcMask |
|
||||
SmcDieProcMask |
|
||||
SmcSaveCompleteProcMask |
|
||||
SmcShutdownCancelledProcMask,
|
||||
&cb, sm_id, &sm_id,
|
||||
SM_ERR_LEN, sm_err);
|
||||
if (sm_conn == NULL)
|
||||
ob_debug("Failed to connect to session manager: %s\n", sm_err);
|
||||
else {
|
||||
SmPropValue val_prog;
|
||||
SmPropValue val_uid;
|
||||
SmPropValue val_hint;
|
||||
SmPropValue val_pri;
|
||||
SmPropValue val_pid;
|
||||
SmProp prop_prog = { SmProgram, SmARRAY8, 1, };
|
||||
SmProp prop_uid = { SmUserID, SmARRAY8, 1, };
|
||||
SmProp prop_hint = { SmRestartStyleHint, SmCARD8, 1, };
|
||||
SmProp prop_pid = { SmProcessID, SmARRAY8, 1, };
|
||||
SmProp prop_pri = { "_GSM_Priority", SmCARD8, 1, };
|
||||
SmProp *props[6];
|
||||
gchar hint, pri;
|
||||
gchar pid[32];
|
||||
|
||||
val_prog.value = sm_argv[0];
|
||||
val_prog.length = strlen(sm_argv[0]);
|
||||
|
||||
val_uid.value = g_strdup(g_get_user_name());
|
||||
val_uid.length = strlen(val_uid.value);
|
||||
|
||||
hint = SmRestartImmediately;
|
||||
val_hint.value = &hint;
|
||||
val_hint.length = 1;
|
||||
|
||||
g_snprintf(pid, sizeof(pid), "%ld", (glong) getpid());
|
||||
val_pid.value = pid;
|
||||
val_pid.length = strlen(pid);
|
||||
|
||||
/* priority with gnome-session-manager, low to run before other apps */
|
||||
pri = 20;
|
||||
val_pri.value = &pri;
|
||||
val_pri.length = 1;
|
||||
|
||||
prop_prog.vals = &val_prog;
|
||||
prop_uid.vals = &val_uid;
|
||||
prop_hint.vals = &val_hint;
|
||||
prop_pid.vals = &val_pid;
|
||||
prop_pri.vals = &val_pri;
|
||||
|
||||
props[0] = &prop_prog;
|
||||
props[1] = &prop_uid;
|
||||
props[2] = &prop_hint;
|
||||
props[3] = &prop_pid;
|
||||
props[4] = &prop_pri;
|
||||
|
||||
SmcSetProperties(sm_conn, 5, props);
|
||||
|
||||
g_free(val_uid.value);
|
||||
|
||||
save_commands();
|
||||
if (session_connect()) {
|
||||
session_setup_program();
|
||||
session_setup_user();
|
||||
session_setup_restart_style(TRUE);
|
||||
session_setup_pid();
|
||||
session_setup_priority();
|
||||
session_setup_clone_command();
|
||||
}
|
||||
|
||||
g_free(dir);
|
||||
}
|
||||
|
||||
void session_shutdown(gboolean permanent)
|
||||
{
|
||||
if (sm_disable)
|
||||
return;
|
||||
|
||||
g_free(sm_sessions_path);
|
||||
g_free(save_file);
|
||||
g_free(sm_id);
|
||||
g_free(sm_argv);
|
||||
if (!ob_sm_use) return;
|
||||
|
||||
if (sm_conn) {
|
||||
/* if permanent is true then we will change our session state so that
|
||||
the SM won't run us again */
|
||||
if (permanent) {
|
||||
SmPropValue val_hint;
|
||||
SmProp prop_hint = { SmRestartStyleHint, SmCARD8, 1, };
|
||||
SmProp *props[1];
|
||||
gulong hint;
|
||||
|
||||
/* when we exit, we want to reset this to a more friendly state */
|
||||
hint = SmRestartIfRunning;
|
||||
val_hint.value = &hint;
|
||||
val_hint.length = 1;
|
||||
|
||||
prop_hint.vals = &val_hint;
|
||||
|
||||
props[0] = &prop_hint;
|
||||
|
||||
SmcSetProperties(sm_conn, 1, props);
|
||||
}
|
||||
session_setup_restart_style(!permanent);
|
||||
|
||||
SmcCloseConnection(sm_conn, 0, NULL);
|
||||
|
||||
|
@ -299,55 +141,263 @@ void session_shutdown(gboolean permanent)
|
|||
}
|
||||
}
|
||||
|
||||
static void sm_save_yourself_phase2(SmcConn conn, SmPointer data)
|
||||
/*! Connect to the session manager and set up our callback functions */
|
||||
static gboolean session_connect()
|
||||
{
|
||||
SmcCallbacks cb;
|
||||
gchar *oldid;
|
||||
gchar sm_err[SM_ERR_LEN];
|
||||
|
||||
/* set up our callback functions */
|
||||
cb.save_yourself.callback = sm_save_yourself;
|
||||
cb.save_yourself.client_data = NULL;
|
||||
cb.die.callback = sm_die;
|
||||
cb.die.client_data = NULL;
|
||||
cb.save_complete.callback = sm_save_complete;
|
||||
cb.save_complete.client_data = NULL;
|
||||
cb.shutdown_cancelled.callback = sm_shutdown_cancelled;
|
||||
cb.shutdown_cancelled.client_data = NULL;
|
||||
|
||||
/* connect to the server */
|
||||
oldid = ob_sm_id;
|
||||
ob_debug_type(OB_DEBUG_SM, "Connecting to SM with id: %s\n",
|
||||
oldid ? oldid : "(null)");
|
||||
sm_conn = SmcOpenConnection(NULL, NULL, 1, 0,
|
||||
SmcSaveYourselfProcMask |
|
||||
SmcDieProcMask |
|
||||
SmcSaveCompleteProcMask |
|
||||
SmcShutdownCancelledProcMask,
|
||||
&cb, oldid, &ob_sm_id,
|
||||
SM_ERR_LEN, sm_err);
|
||||
g_free(oldid);
|
||||
if (sm_conn == NULL)
|
||||
ob_debug("Failed to connect to session manager: %s\n", sm_err);
|
||||
return sm_conn != NULL;
|
||||
}
|
||||
|
||||
static void session_setup_program()
|
||||
{
|
||||
SmPropValue vals = {
|
||||
.value = sm_argv[0],
|
||||
.length = strlen(sm_argv[0]) + 1
|
||||
};
|
||||
SmProp prop = {
|
||||
.name = g_strdup(SmProgram),
|
||||
.type = g_strdup(SmARRAY8),
|
||||
.num_vals = 1,
|
||||
.vals = &vals
|
||||
};
|
||||
SmProp *list = ∝
|
||||
SmcSetProperties(sm_conn, 1, &list);
|
||||
g_free(prop.name);
|
||||
g_free(prop.type);
|
||||
}
|
||||
|
||||
static void session_setup_user()
|
||||
{
|
||||
char *user = g_strdup(g_get_user_name());
|
||||
|
||||
SmPropValue vals = {
|
||||
.value = user,
|
||||
.length = strlen(user) + 1
|
||||
};
|
||||
SmProp prop = {
|
||||
.name = g_strdup(SmUserID),
|
||||
.type = g_strdup(SmARRAY8),
|
||||
.num_vals = 1,
|
||||
.vals = &vals
|
||||
};
|
||||
SmProp *list = ∝
|
||||
SmcSetProperties(sm_conn, 1, &list);
|
||||
g_free(prop.name);
|
||||
g_free(prop.type);
|
||||
g_free(user);
|
||||
}
|
||||
|
||||
static void session_setup_restart_style(gboolean restart)
|
||||
{
|
||||
char restart_hint = restart ? SmRestartImmediately : SmRestartIfRunning;
|
||||
|
||||
SmPropValue vals = {
|
||||
.value = &restart_hint,
|
||||
.length = 1
|
||||
};
|
||||
SmProp prop = {
|
||||
.name = g_strdup(SmRestartStyleHint),
|
||||
.type = g_strdup(SmCARD8),
|
||||
.num_vals = 1,
|
||||
.vals = &vals
|
||||
};
|
||||
SmProp *list = ∝
|
||||
SmcSetProperties(sm_conn, 1, &list);
|
||||
g_free(prop.name);
|
||||
g_free(prop.type);
|
||||
}
|
||||
|
||||
static void session_setup_pid()
|
||||
{
|
||||
gchar *pid = g_strdup_printf("%ld", (glong) getpid());
|
||||
|
||||
SmPropValue vals = {
|
||||
.value = pid,
|
||||
.length = strlen(pid) + 1
|
||||
};
|
||||
SmProp prop = {
|
||||
.name = g_strdup(SmProcessID),
|
||||
.type = g_strdup(SmARRAY8),
|
||||
.num_vals = 1,
|
||||
.vals = &vals
|
||||
};
|
||||
SmProp *list = ∝
|
||||
SmcSetProperties(sm_conn, 1, &list);
|
||||
g_free(prop.name);
|
||||
g_free(prop.type);
|
||||
g_free(pid);
|
||||
}
|
||||
|
||||
/*! This is a gnome-session-manager extension */
|
||||
static void session_setup_priority()
|
||||
{
|
||||
gchar priority = 20; /* 20 is a lower prioity to run before other apps */
|
||||
|
||||
SmPropValue vals = {
|
||||
.value = &priority,
|
||||
.length = 1
|
||||
};
|
||||
SmProp prop = {
|
||||
.name = g_strdup("_GSM_Priority"),
|
||||
.type = g_strdup(SmCARD8),
|
||||
.num_vals = 1,
|
||||
.vals = &vals
|
||||
};
|
||||
SmProp *list = ∝
|
||||
SmcSetProperties(sm_conn, 1, &list);
|
||||
g_free(prop.name);
|
||||
g_free(prop.type);
|
||||
}
|
||||
|
||||
static void session_setup_clone_command()
|
||||
{
|
||||
gint i;
|
||||
|
||||
SmPropValue *vals = g_new(SmPropValue, sm_argc);
|
||||
SmProp prop = {
|
||||
.name = g_strdup(SmCloneCommand),
|
||||
.type = g_strdup(SmLISTofARRAY8),
|
||||
.num_vals = sm_argc,
|
||||
.vals = vals
|
||||
};
|
||||
|
||||
for (i = 0; i < sm_argc; ++i) {
|
||||
vals[i].value = sm_argv[i];
|
||||
vals[i].length = strlen(sm_argv[i]) + 1;
|
||||
}
|
||||
|
||||
SmProp *list = ∝
|
||||
SmcSetProperties(sm_conn, 1, &list);
|
||||
g_free(prop.name);
|
||||
g_free(prop.type);
|
||||
g_free(vals);
|
||||
}
|
||||
|
||||
static void session_setup_restart_command()
|
||||
{
|
||||
gint i;
|
||||
|
||||
SmPropValue *vals = g_new(SmPropValue, sm_argc + 4);
|
||||
SmProp prop = {
|
||||
.name = g_strdup(SmRestartCommand),
|
||||
.type = g_strdup(SmLISTofARRAY8),
|
||||
.num_vals = sm_argc + 4,
|
||||
.vals = vals
|
||||
};
|
||||
|
||||
for (i = 0; i < sm_argc; ++i) {
|
||||
vals[i].value = sm_argv[i];
|
||||
vals[i].length = strlen(sm_argv[i]) + 1;
|
||||
}
|
||||
|
||||
vals[i].value = g_strdup("--sm-save-file");
|
||||
vals[i].length = strlen("--sm-save-file") + 1;
|
||||
vals[i+1].value = ob_sm_save_file;
|
||||
vals[i+1].length = strlen(ob_sm_save_file) + 1;
|
||||
|
||||
vals[i+2].value = g_strdup("--sm-client-id");
|
||||
vals[i+2].length = strlen("--sm-client-id") + 1;
|
||||
vals[i+3].value = ob_sm_id;
|
||||
vals[i+3].length = strlen(ob_sm_id) + 1;
|
||||
|
||||
SmProp *list = ∝
|
||||
SmcSetProperties(sm_conn, 1, &list);
|
||||
g_free(prop.name);
|
||||
g_free(prop.type);
|
||||
g_free(vals[i].value);
|
||||
g_free(vals[i+2].value);
|
||||
g_free(vals);
|
||||
}
|
||||
|
||||
static void sm_save_yourself_2(SmcConn conn, SmPointer data)
|
||||
{
|
||||
gboolean success;
|
||||
|
||||
success = session_save();
|
||||
save_commands();
|
||||
/* save the current state */
|
||||
ob_debug_type(OB_DEBUG_SM, "Session save phase 2 requested\n");
|
||||
ob_debug_type(OB_DEBUG_SM,
|
||||
" Saving session to file '%s'\n", ob_sm_save_file);
|
||||
success = session_save_to_file();
|
||||
|
||||
/* tell the session manager how to restore this state */
|
||||
if (success) session_setup_restart_command();
|
||||
|
||||
ob_debug_type(OB_DEBUG_SM, "Saving is done (success = %d)\n", success);
|
||||
SmcSaveYourselfDone(conn, success);
|
||||
}
|
||||
|
||||
|
||||
static void sm_save_yourself(SmcConn conn, SmPointer data, gint save_type,
|
||||
Bool shutdown, gint interact_style, Bool fast)
|
||||
{
|
||||
if (!SmcRequestSaveYourselfPhase2(conn, sm_save_yourself_phase2, data)) {
|
||||
ob_debug("SAVE YOURSELF PHASE 2 failed\n");
|
||||
ob_debug_type(OB_DEBUG_SM, "Session save requested\n");
|
||||
if (!SmcRequestSaveYourselfPhase2(conn, sm_save_yourself_2, data)) {
|
||||
ob_debug_type(OB_DEBUG_SM, "Requst for phase 2 failed\n");
|
||||
SmcSaveYourselfDone(conn, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void sm_die(SmcConn conn, SmPointer data)
|
||||
{
|
||||
ob_debug_type(OB_DEBUG_SM, "Die requested\n");
|
||||
ob_exit(0);
|
||||
}
|
||||
|
||||
static void sm_save_complete(SmcConn conn, SmPointer data)
|
||||
{
|
||||
ob_debug_type(OB_DEBUG_SM, "Save complete\n");
|
||||
}
|
||||
|
||||
static void sm_shutdown_cancelled(SmcConn conn, SmPointer data)
|
||||
{
|
||||
ob_debug_type(OB_DEBUG_SM, "Shutdown cancelled\n");
|
||||
}
|
||||
|
||||
static gboolean session_save()
|
||||
static gboolean session_save_to_file()
|
||||
{
|
||||
FILE *f;
|
||||
GList *it;
|
||||
gboolean success = TRUE;
|
||||
|
||||
f = fopen(save_file, "w");
|
||||
f = fopen(ob_sm_save_file, "w");
|
||||
if (!f) {
|
||||
success = FALSE;
|
||||
g_message(_("Unable to save the session to '%s': %s"),
|
||||
save_file, g_strerror(errno));
|
||||
ob_sm_save_file, g_strerror(errno));
|
||||
} else {
|
||||
guint stack_pos = 0;
|
||||
|
||||
fprintf(f, "<?xml version=\"1.0\"?>\n\n");
|
||||
fprintf(f, "<openbox_session id=\"%s\">\n\n", sm_id);
|
||||
fprintf(f, "<openbox_session>\n\n");
|
||||
|
||||
fprintf(f, "<desktop>%d</desktop>\n", screen_desktop);
|
||||
|
||||
/* they are ordered top to bottom in stacking order */
|
||||
for (it = stacking_list; it; it = g_list_next(it)) {
|
||||
gint prex, prey, prew, preh;
|
||||
ObClient *c;
|
||||
|
@ -361,8 +411,15 @@ static gboolean session_save()
|
|||
if (!client_normal(c))
|
||||
continue;
|
||||
|
||||
if (!c->sm_client_id)
|
||||
if (!c->sm_client_id) {
|
||||
ob_debug_type(OB_DEBUG_SM, "Client %s does not have a client "
|
||||
"id set, so we can't save its state\n",
|
||||
c->title);
|
||||
continue;
|
||||
}
|
||||
|
||||
ob_debug_type(OB_DEBUG_SM, "Saving state for client %s\n",
|
||||
c->title);
|
||||
|
||||
prex = c->area.x;
|
||||
prey = c->area.y;
|
||||
|
@ -398,7 +455,6 @@ static gboolean session_save()
|
|||
g_free(t);
|
||||
|
||||
fprintf(f, "\t<desktop>%d</desktop>\n", c->desktop);
|
||||
fprintf(f, "\t<stacking>%d</stacking>\n", stack_pos);
|
||||
fprintf(f, "\t<x>%d</x>\n", prex);
|
||||
fprintf(f, "\t<y>%d</y>\n", prey);
|
||||
fprintf(f, "\t<width>%d</width>\n", prew);
|
||||
|
@ -421,9 +477,11 @@ static gboolean session_save()
|
|||
fprintf(f, "\t<max_horz />\n");
|
||||
if (c->max_vert)
|
||||
fprintf(f, "\t<max_vert />\n");
|
||||
if (c->undecorated)
|
||||
fprintf(f, "\t<undecorated />\n");
|
||||
if (client_focused(c))
|
||||
fprintf(f, "\t<focused />\n");
|
||||
fprintf(f, "</window>\n\n");
|
||||
|
||||
++stack_pos;
|
||||
}
|
||||
|
||||
fprintf(f, "</openbox_session>\n");
|
||||
|
@ -431,7 +489,7 @@ static gboolean session_save()
|
|||
if (fflush(f)) {
|
||||
success = FALSE;
|
||||
g_message(_("Error while saving the session to '%s': %s"),
|
||||
save_file, g_strerror(errno));
|
||||
ob_sm_save_file, g_strerror(errno));
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
@ -439,7 +497,7 @@ static gboolean session_save()
|
|||
return success;
|
||||
}
|
||||
|
||||
void session_state_free(ObSessionState *state)
|
||||
static void session_state_free(ObSessionState *state)
|
||||
{
|
||||
if (state) {
|
||||
g_free(state->id);
|
||||
|
@ -451,8 +509,17 @@ void session_state_free(ObSessionState *state)
|
|||
}
|
||||
}
|
||||
|
||||
gboolean session_state_cmp(ObSessionState *s, ObClient *c)
|
||||
static gboolean session_state_cmp(ObSessionState *s, ObClient *c)
|
||||
{
|
||||
ob_debug_type(OB_DEBUG_SM, "Comparing client against saved state: \n");
|
||||
ob_debug_type(OB_DEBUG_SM, " client id: %s \n", c->sm_client_id);
|
||||
ob_debug_type(OB_DEBUG_SM, " client name: %s \n", c->name);
|
||||
ob_debug_type(OB_DEBUG_SM, " client class: %s \n", c->class);
|
||||
ob_debug_type(OB_DEBUG_SM, " client role: %s \n", c->role);
|
||||
ob_debug_type(OB_DEBUG_SM, " state id: %s \n", s->id);
|
||||
ob_debug_type(OB_DEBUG_SM, " state name: %s \n", s->name);
|
||||
ob_debug_type(OB_DEBUG_SM, " state class: %s \n", s->class);
|
||||
ob_debug_type(OB_DEBUG_SM, " state role: %s \n", s->role);
|
||||
return (c->sm_client_id &&
|
||||
!strcmp(s->id, c->sm_client_id) &&
|
||||
!strcmp(s->name, c->name) &&
|
||||
|
@ -474,27 +541,20 @@ GList* session_state_find(ObClient *c)
|
|||
return it;
|
||||
}
|
||||
|
||||
static gint stack_sort(const ObSessionState *s1, const ObSessionState *s2)
|
||||
{
|
||||
return s1->stacking - s2->stacking;
|
||||
}
|
||||
|
||||
static void session_load(gchar *path)
|
||||
static void session_load_file(gchar *path)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
xmlNodePtr node, n;
|
||||
gchar *id;
|
||||
|
||||
if (!parse_load(path, "openbox_session", &doc, &node))
|
||||
return;
|
||||
|
||||
if (!parse_attr_string("id", node, &id))
|
||||
return;
|
||||
g_free(sm_id);
|
||||
sm_id = id;
|
||||
if ((n = parse_find_node("desktop", node->children)))
|
||||
session_desktop = parse_int(doc, n);
|
||||
|
||||
node = parse_find_node("window", node->children);
|
||||
while (node) {
|
||||
for (node = parse_find_node("window", node->children); node != NULL;
|
||||
node = parse_find_node("window", node->next))
|
||||
{
|
||||
ObSessionState *state;
|
||||
|
||||
state = g_new0(ObSessionState, 1);
|
||||
|
@ -510,9 +570,6 @@ static void session_load(gchar *path)
|
|||
if (!(n = parse_find_node("role", node->children)))
|
||||
goto session_load_bail;
|
||||
state->role = parse_string(doc, n);
|
||||
if (!(n = parse_find_node("stacking", node->children)))
|
||||
goto session_load_bail;
|
||||
state->stacking = parse_int(doc, n);
|
||||
if (!(n = parse_find_node("desktop", node->children)))
|
||||
goto session_load_bail;
|
||||
state->desktop = parse_int(doc, n);
|
||||
|
@ -547,23 +604,20 @@ static void session_load(gchar *path)
|
|||
parse_find_node("max_horz", node->children) != NULL;
|
||||
state->max_vert =
|
||||
parse_find_node("max_vert", node->children) != NULL;
|
||||
state->undecorated =
|
||||
parse_find_node("undecorated", node->children) != NULL;
|
||||
state->focused =
|
||||
parse_find_node("focused", node->children) != NULL;
|
||||
|
||||
/* save this */
|
||||
session_saved_state = g_list_prepend(session_saved_state, state);
|
||||
goto session_load_ok;
|
||||
/* save this. they are in the file in stacking order, so preserve
|
||||
that order here */
|
||||
session_saved_state = g_list_append(session_saved_state, state);
|
||||
continue;
|
||||
|
||||
session_load_bail:
|
||||
session_state_free(state);
|
||||
|
||||
session_load_ok:
|
||||
|
||||
node = parse_find_node("window", node->next);
|
||||
}
|
||||
|
||||
/* sort them by their stacking order */
|
||||
session_saved_state = g_list_sort(session_saved_state,
|
||||
(GCompareFunc)stack_sort);
|
||||
|
||||
xmlFreeDoc(doc);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,22 +27,24 @@ typedef struct _ObSessionState ObSessionState;
|
|||
|
||||
struct _ObSessionState {
|
||||
gchar *id, *name, *class, *role;
|
||||
guint stacking;
|
||||
guint desktop;
|
||||
gint x, y, w, h;
|
||||
gboolean shaded, iconic, skip_pager, skip_taskbar, fullscreen;
|
||||
gboolean above, below, max_horz, max_vert;
|
||||
gboolean above, below, max_horz, max_vert, undecorated;
|
||||
gboolean focused;
|
||||
|
||||
gboolean matched;
|
||||
};
|
||||
|
||||
/*! The desktop being viewed when the session was saved. A valud of -1 means
|
||||
it was not saved */
|
||||
extern gint session_desktop;
|
||||
|
||||
extern GList *session_saved_state;
|
||||
|
||||
void session_startup(gint argc, gchar **argv);
|
||||
void session_shutdown(gboolean permanent);
|
||||
|
||||
GList* session_state_find(struct _ObClient *c);
|
||||
gboolean session_state_cmp(ObSessionState *s, struct _ObClient *c);
|
||||
void session_state_free(ObSessionState *state);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue