1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 session.c for the Openbox window manager
4 Copyright (c) 2003-2007 Dana Jansens
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 See the COPYING file for a copy of the GNU General Public License.
19 /* This session code is largely inspired by metacity code. */
25 GList
*session_saved_state
= NULL
;
26 gint session_desktop
= -1;
27 gint session_num_desktops
= 0;
28 gboolean session_desktop_layout_present
= FALSE
;
29 ObDesktopLayout session_desktop_layout
;
30 GSList
*session_desktop_names
= NULL
;
33 void session_startup(gint argc
, gchar
**argv
) {}
34 void session_shutdown(gboolean permanent
) {}
35 GList
* session_state_find(struct _ObClient
*c
) { return NULL
; }
36 void session_request_logout(gboolean silent
) {}
45 #include "parser/parse.h"
52 # include <sys/types.h>
56 #include <X11/SM/SMlib.h>
58 #define SM_ERR_LEN 1024
60 static SmcConn sm_conn
;
62 static gchar
**sm_argv
;
64 /* Data saved from the first level save yourself */
66 ObClient
*focus_client
;
70 static gboolean
session_connect();
72 static void session_load_file(const gchar
*path
);
73 static gboolean
session_save_to_file(const ObSMSaveData
*savedata
);
75 static void session_setup_program();
76 static void session_setup_user();
77 static void session_setup_restart_style(gboolean restart
);
78 static void session_setup_pid();
79 static void session_setup_priority();
80 static void session_setup_clone_command();
81 static void session_setup_restart_command();
83 static void sm_save_yourself(SmcConn conn
, SmPointer data
, gint save_type
,
84 Bool shutdown
, gint interact_style
, Bool fast
);
85 static void sm_die(SmcConn conn
, SmPointer data
);
86 static void sm_save_complete(SmcConn conn
, SmPointer data
);
87 static void sm_shutdown_cancelled(SmcConn conn
, SmPointer data
);
89 static gboolean
session_state_cmp(ObSessionState
*s
, ObClient
*c
);
90 static void session_state_free(ObSessionState
*state
);
92 void session_startup(gint argc
, gchar
**argv
)
96 if (!ob_sm_use
) return;
101 dir
= g_build_filename(parse_xdg_data_home_path(),
102 "openbox", "sessions", NULL
);
103 if (!parse_mkdir_path(dir
, 0700)) {
104 g_message(_("Unable to make directory \"%s\": %s"),
105 dir
, g_strerror(errno
));
108 if (ob_sm_save_file
!= NULL
) {
110 ob_debug_type(OB_DEBUG_SM
, "Loading from session file %s\n",
112 session_load_file(ob_sm_save_file
);
117 /* this algo is from metacity */
118 filename
= g_strdup_printf("%u-%u-%u.obs",
122 ob_sm_save_file
= g_build_filename(dir
, filename
, NULL
);
126 if (session_connect()) {
127 session_setup_program();
128 session_setup_user();
129 session_setup_restart_style(TRUE
);
131 session_setup_priority();
132 session_setup_clone_command();
138 void session_shutdown(gboolean permanent
)
140 if (!ob_sm_use
) return;
143 /* if permanent is true then we will change our session state so that
144 the SM won't run us again */
146 session_setup_restart_style(FALSE
);
148 SmcCloseConnection(sm_conn
, 0, NULL
);
150 while (session_saved_state
) {
151 session_state_free(session_saved_state
->data
);
152 session_saved_state
= g_list_delete_link(session_saved_state
,
153 session_saved_state
);
158 /*! Connect to the session manager and set up our callback functions */
159 static gboolean
session_connect()
163 gchar sm_err
[SM_ERR_LEN
];
165 /* set up our callback functions */
166 cb
.save_yourself
.callback
= sm_save_yourself
;
167 cb
.save_yourself
.client_data
= NULL
;
168 cb
.die
.callback
= sm_die
;
169 cb
.die
.client_data
= NULL
;
170 cb
.save_complete
.callback
= sm_save_complete
;
171 cb
.save_complete
.client_data
= NULL
;
172 cb
.shutdown_cancelled
.callback
= sm_shutdown_cancelled
;
173 cb
.shutdown_cancelled
.client_data
= NULL
;
175 /* connect to the server */
177 ob_debug_type(OB_DEBUG_SM
, "Connecting to SM with id: %s\n",
178 oldid
? oldid
: "(null)");
179 sm_conn
= SmcOpenConnection(NULL
, NULL
, 1, 0,
180 SmcSaveYourselfProcMask
|
182 SmcSaveCompleteProcMask
|
183 SmcShutdownCancelledProcMask
,
184 &cb
, oldid
, &ob_sm_id
,
185 SM_ERR_LEN
-1, sm_err
);
187 ob_debug_type(OB_DEBUG_SM
, "Connected to SM with id: %s\n", ob_sm_id
);
189 ob_debug("Failed to connect to session manager: %s\n", sm_err
);
190 return sm_conn
!= NULL
;
193 static void session_setup_program()
197 .length
= strlen(sm_argv
[0]) + 1
200 .name
= g_strdup(SmProgram
),
201 .type
= g_strdup(SmARRAY8
),
205 SmProp
*list
= &prop
;
206 ob_debug_type(OB_DEBUG_SM
, "Setting program: %s\n", sm_argv
[0]);
207 SmcSetProperties(sm_conn
, 1, &list
);
212 static void session_setup_user()
214 char *user
= g_strdup(g_get_user_name());
218 .length
= strlen(user
) + 1
221 .name
= g_strdup(SmUserID
),
222 .type
= g_strdup(SmARRAY8
),
226 SmProp
*list
= &prop
;
227 ob_debug_type(OB_DEBUG_SM
, "Setting user: %s\n", user
);
228 SmcSetProperties(sm_conn
, 1, &list
);
234 static void session_setup_restart_style(gboolean restart
)
236 gchar restart_hint
= restart
? SmRestartImmediately
: SmRestartIfRunning
;
239 .value
= &restart_hint
,
243 .name
= g_strdup(SmRestartStyleHint
),
244 .type
= g_strdup(SmCARD8
),
248 SmProp
*list
= &prop
;
249 ob_debug_type(OB_DEBUG_SM
, "Setting restart: %d\n", restart
);
250 SmcSetProperties(sm_conn
, 1, &list
);
255 static void session_setup_pid()
257 gchar
*pid
= g_strdup_printf("%ld", (glong
) getpid());
261 .length
= strlen(pid
) + 1
264 .name
= g_strdup(SmProcessID
),
265 .type
= g_strdup(SmARRAY8
),
269 SmProp
*list
= &prop
;
270 ob_debug_type(OB_DEBUG_SM
, "Setting pid: %s\n", pid
);
271 SmcSetProperties(sm_conn
, 1, &list
);
277 /*! This is a gnome-session-manager extension */
278 static void session_setup_priority()
280 gchar priority
= 20; /* 20 is a lower prioity to run before other apps */
287 .name
= g_strdup("_GSM_Priority"),
288 .type
= g_strdup(SmCARD8
),
292 SmProp
*list
= &prop
;
293 ob_debug_type(OB_DEBUG_SM
, "Setting priority: %d\n", priority
);
294 SmcSetProperties(sm_conn
, 1, &list
);
299 static void session_setup_clone_command()
303 SmPropValue
*vals
= g_new(SmPropValue
, sm_argc
);
305 .name
= g_strdup(SmCloneCommand
),
306 .type
= g_strdup(SmLISTofARRAY8
),
310 SmProp
*list
= &prop
;
312 ob_debug_type(OB_DEBUG_SM
, "Setting clone command: (%d)\n", sm_argc
);
313 for (i
= 0; i
< sm_argc
; ++i
) {
314 vals
[i
].value
= sm_argv
[i
];
315 vals
[i
].length
= strlen(sm_argv
[i
]) + 1;
316 ob_debug_type(OB_DEBUG_SM
, " %s\n", vals
[i
].value
);
319 SmcSetProperties(sm_conn
, 1, &list
);
325 static void session_setup_restart_command()
329 SmPropValue
*vals
= g_new(SmPropValue
, sm_argc
+ 4);
331 .name
= g_strdup(SmRestartCommand
),
332 .type
= g_strdup(SmLISTofARRAY8
),
333 .num_vals
= sm_argc
+ 4,
336 SmProp
*list
= &prop
;
338 ob_debug_type(OB_DEBUG_SM
, "Setting restart command: (%d)\n", sm_argc
+4);
339 for (i
= 0; i
< sm_argc
; ++i
) {
340 vals
[i
].value
= sm_argv
[i
];
341 vals
[i
].length
= strlen(sm_argv
[i
]) + 1;
342 ob_debug_type(OB_DEBUG_SM
, " %s\n", vals
[i
].value
);
345 vals
[i
].value
= g_strdup("--sm-client-id");
346 vals
[i
].length
= strlen("--sm-client-id") + 1;
347 vals
[i
+1].value
= ob_sm_id
;
348 vals
[i
+1].length
= strlen(ob_sm_id
) + 1;
349 ob_debug_type(OB_DEBUG_SM
, " %s\n", vals
[i
].value
);
350 ob_debug_type(OB_DEBUG_SM
, " %s\n", vals
[i
+1].value
);
352 vals
[i
+2].value
= g_strdup("--sm-save-file");
353 vals
[i
+2].length
= strlen("--sm-save-file") + 1;
354 vals
[i
+3].value
= ob_sm_save_file
;
355 vals
[i
+3].length
= strlen(ob_sm_save_file
) + 1;
356 ob_debug_type(OB_DEBUG_SM
, " %s\n", vals
[i
+2].value
);
357 ob_debug_type(OB_DEBUG_SM
, " %s\n", vals
[i
+3].value
);
359 SmcSetProperties(sm_conn
, 1, &list
);
362 g_free(vals
[i
].value
);
363 g_free(vals
[i
+2].value
);
367 static ObSMSaveData
*sm_save_get_data()
369 ObSMSaveData
*savedata
= g_new0(ObSMSaveData
, 1);
370 /* save the active desktop and client.
371 we don't bother to preemptively save the other desktop state like
372 number and names of desktops, cuz those shouldn't be changing during
374 savedata
->focus_client
= focus_client
;
375 savedata
->desktop
= screen_desktop
;
379 static void sm_save_yourself_2(SmcConn conn
, SmPointer data
)
382 ObSMSaveData
*savedata
= data
;
384 /* save the current state */
385 ob_debug_type(OB_DEBUG_SM
, "Session save phase 2 requested\n");
386 ob_debug_type(OB_DEBUG_SM
,
387 " Saving session to file '%s'\n", ob_sm_save_file
);
388 if (savedata
== NULL
)
389 savedata
= sm_save_get_data();
390 success
= session_save_to_file(savedata
);
393 /* tell the session manager how to restore this state */
394 if (success
) session_setup_restart_command();
396 ob_debug_type(OB_DEBUG_SM
, "Saving is done (success = %d)\n", success
);
397 SmcSaveYourselfDone(conn
, success
);
401 static void sm_save_yourself(SmcConn conn
, SmPointer data
, gint save_type
,
402 Bool shutdown
, gint interact_style
, Bool fast
)
404 ObSMSaveData
*savedata
= NULL
;
407 ob_debug_type(OB_DEBUG_SM
, "Session save requested\n");
409 vendor
= SmcVendor(sm_conn
);
410 ob_debug_type(OB_DEBUG_SM
, "Session manager's vendor: %s\n", vendor
);
412 if (!strcmp(vendor
, "KDE")) {
413 /* ksmserver guarantees that phase 1 will complete before allowing any
414 clients interaction, so we can save this sanely here before they
415 get messed up from interaction */
416 savedata
= sm_save_get_data();
420 if (!SmcRequestSaveYourselfPhase2(conn
, sm_save_yourself_2
, savedata
)) {
421 ob_debug_type(OB_DEBUG_SM
, "Requst for phase 2 failed\n");
423 SmcSaveYourselfDone(conn
, FALSE
);
427 static void sm_die(SmcConn conn
, SmPointer data
)
429 ob_debug_type(OB_DEBUG_SM
, "Die requested\n");
433 static void sm_save_complete(SmcConn conn
, SmPointer data
)
435 ob_debug_type(OB_DEBUG_SM
, "Save complete\n");
438 static void sm_shutdown_cancelled(SmcConn conn
, SmPointer data
)
440 ob_debug_type(OB_DEBUG_SM
, "Shutdown cancelled\n");
443 static gboolean
session_save_to_file(const ObSMSaveData
*savedata
)
447 gboolean success
= TRUE
;
449 f
= fopen(ob_sm_save_file
, "w");
452 g_message(_("Unable to save the session to \"%s\": %s"),
453 ob_sm_save_file
, g_strerror(errno
));
455 fprintf(f
, "<?xml version=\"1.0\"?>\n\n");
456 fprintf(f
, "<openbox_session>\n\n");
458 fprintf(f
, "<desktop>%d</desktop>\n", savedata
->desktop
);
460 fprintf(f
, "<numdesktops>%d</numdesktops>\n", screen_num_desktops
);
462 fprintf(f
, "<desktoplayout>\n");
463 fprintf(f
, " <orientation>%d</orientation>\n",
464 screen_desktop_layout
.orientation
);
465 fprintf(f
, " <startcorner>%d</startcorner>\n",
466 screen_desktop_layout
.start_corner
);
467 fprintf(f
, " <columns>%d</columns>\n",
468 screen_desktop_layout
.columns
);
469 fprintf(f
, " <rows>%d</rows>\n",
470 screen_desktop_layout
.rows
);
471 fprintf(f
, "</desktoplayout>\n");
473 if (screen_desktop_names
) {
476 fprintf(f
, "<desktopnames>\n");
477 for (i
= 0; screen_desktop_names
[i
]; ++i
)
478 fprintf(f
, " <name>%s</name>\n", screen_desktop_names
[i
]);
479 fprintf(f
, "</desktopnames>\n");
482 /* they are ordered top to bottom in stacking order */
483 for (it
= stacking_list
; it
; it
= g_list_next(it
)) {
484 gint prex
, prey
, prew
, preh
;
488 if (WINDOW_IS_CLIENT(it
->data
))
489 c
= WINDOW_AS_CLIENT(it
->data
);
493 if (!client_normal(c
))
496 if (!c
->sm_client_id
) {
497 ob_debug_type(OB_DEBUG_SM
, "Client %s does not have a "
500 if (!c
->wm_command
) {
501 ob_debug_type(OB_DEBUG_SM
, "Client %s does not have an "
502 "oldskool wm_command set either. We won't "
503 "be saving its data\n",
509 ob_debug_type(OB_DEBUG_SM
, "Saving state for client %s\n",
514 prew
= c
->area
.width
;
515 preh
= c
->area
.height
;
517 prex
= c
->pre_fullscreen_area
.x
;
518 prey
= c
->pre_fullscreen_area
.x
;
519 prew
= c
->pre_fullscreen_area
.width
;
520 preh
= c
->pre_fullscreen_area
.height
;
523 prex
= c
->pre_max_area
.x
;
524 prew
= c
->pre_max_area
.width
;
527 prey
= c
->pre_max_area
.y
;
528 preh
= c
->pre_max_area
.height
;
532 fprintf(f
, "<window id=\"%s\">\n", c
->sm_client_id
);
534 fprintf(f
, "<window command=\"%s\">\n", c
->wm_command
);
536 t
= g_markup_escape_text(c
->name
, -1);
537 fprintf(f
, "\t<name>%s</name>\n", t
);
540 t
= g_markup_escape_text(c
->class, -1);
541 fprintf(f
, "\t<class>%s</class>\n", t
);
544 t
= g_markup_escape_text(c
->role
, -1);
545 fprintf(f
, "\t<role>%s</role>\n", t
);
548 fprintf(f
, "\t<windowtype>%d</windowtype>\n", c
->type
);
550 fprintf(f
, "\t<desktop>%d</desktop>\n", c
->desktop
);
551 fprintf(f
, "\t<x>%d</x>\n", prex
);
552 fprintf(f
, "\t<y>%d</y>\n", prey
);
553 fprintf(f
, "\t<width>%d</width>\n", prew
);
554 fprintf(f
, "\t<height>%d</height>\n", preh
);
556 fprintf(f
, "\t<shaded />\n");
558 fprintf(f
, "\t<iconic />\n");
560 fprintf(f
, "\t<skip_pager />\n");
562 fprintf(f
, "\t<skip_taskbar />\n");
564 fprintf(f
, "\t<fullscreen />\n");
566 fprintf(f
, "\t<above />\n");
568 fprintf(f
, "\t<below />\n");
570 fprintf(f
, "\t<max_horz />\n");
572 fprintf(f
, "\t<max_vert />\n");
574 fprintf(f
, "\t<undecorated />\n");
575 if (savedata
->focus_client
== c
)
576 fprintf(f
, "\t<focused />\n");
577 fprintf(f
, "</window>\n\n");
580 fprintf(f
, "</openbox_session>\n");
584 g_message(_("Error while saving the session to \"%s\": %s"),
585 ob_sm_save_file
, g_strerror(errno
));
593 static void session_state_free(ObSessionState
*state
)
597 g_free(state
->command
);
599 g_free(state
->class);
606 static gboolean
session_state_cmp(ObSessionState
*s
, ObClient
*c
)
608 ob_debug_type(OB_DEBUG_SM
, "Comparing client against saved state: \n");
609 ob_debug_type(OB_DEBUG_SM
, " client id: %s \n", c
->sm_client_id
);
610 ob_debug_type(OB_DEBUG_SM
, " client name: %s \n", c
->name
);
611 ob_debug_type(OB_DEBUG_SM
, " client class: %s \n", c
->class);
612 ob_debug_type(OB_DEBUG_SM
, " client role: %s \n", c
->role
);
613 ob_debug_type(OB_DEBUG_SM
, " client type: %d \n", c
->type
);
614 ob_debug_type(OB_DEBUG_SM
, " client command: %s \n",
615 c
->wm_command
? c
->wm_command
: "(null)");
616 ob_debug_type(OB_DEBUG_SM
, " state id: %s \n", s
->id
);
617 ob_debug_type(OB_DEBUG_SM
, " state name: %s \n", s
->name
);
618 ob_debug_type(OB_DEBUG_SM
, " state class: %s \n", s
->class);
619 ob_debug_type(OB_DEBUG_SM
, " state role: %s \n", s
->role
);
620 ob_debug_type(OB_DEBUG_SM
, " state type: %d \n", s
->type
);
621 ob_debug_type(OB_DEBUG_SM
, " state command: %s \n",
622 s
->command
? s
->command
: "(null)");
624 if ((c
->sm_client_id
&& s
->id
&& !strcmp(c
->sm_client_id
, s
->id
)) ||
625 (c
->wm_command
&& s
->command
&& !strcmp(c
->wm_command
, s
->command
)))
627 return (!strcmp(s
->name
, c
->name
) &&
628 !strcmp(s
->class, c
->class) &&
629 !strcmp(s
->role
, c
->role
) &&
630 /* the check for type is to catch broken clients, like
631 firefox, which open a different window on startup
632 with the same info as the one we saved. only do this
633 check for old windows that dont use xsmp, others should
635 (!s
->command
|| c
->type
== s
->type
));
640 GList
* session_state_find(ObClient
*c
)
644 for (it
= session_saved_state
; it
; it
= g_list_next(it
)) {
645 ObSessionState
*s
= it
->data
;
646 if (!s
->matched
&& session_state_cmp(s
, c
)) {
654 static void session_load_file(const gchar
*path
)
657 xmlNodePtr node
, n
, m
;
660 if (!parse_load(path
, "openbox_session", &doc
, &node
))
663 if ((n
= parse_find_node("desktop", node
->children
)))
664 session_desktop
= parse_int(doc
, n
);
666 if ((n
= parse_find_node("numdesktops", node
->children
)))
667 session_num_desktops
= parse_int(doc
, n
);
669 if ((n
= parse_find_node("desktoplayout", node
->children
))) {
670 /* make sure they are all there for it to be valid */
671 if ((m
= parse_find_node("orientation", n
->children
)))
672 session_desktop_layout
.orientation
= parse_int(doc
, m
);
673 if (m
&& (m
= parse_find_node("startcorner", n
->children
)))
674 session_desktop_layout
.start_corner
= parse_int(doc
, m
);
675 if (m
&& (m
= parse_find_node("columns", n
->children
)))
676 session_desktop_layout
.columns
= parse_int(doc
, m
);
677 if (m
&& (m
= parse_find_node("rows", n
->children
)))
678 session_desktop_layout
.rows
= parse_int(doc
, m
);
679 session_desktop_layout_present
= m
!= NULL
;
682 if ((n
= parse_find_node("desktopnames", node
->children
))) {
683 for (m
= parse_find_node("name", n
->children
); m
;
684 m
= parse_find_node("name", m
->next
))
686 session_desktop_names
= g_slist_append(session_desktop_names
,
687 parse_string(doc
, m
));
691 for (node
= parse_find_node("window", node
->children
); node
!= NULL
;
692 node
= parse_find_node("window", node
->next
))
694 ObSessionState
*state
;
696 state
= g_new0(ObSessionState
, 1);
698 if (!parse_attr_string("id", node
, &state
->id
))
699 if (!parse_attr_string("command", node
, &state
->command
))
700 goto session_load_bail
;
701 if (!(n
= parse_find_node("name", node
->children
)))
702 goto session_load_bail
;
703 state
->name
= parse_string(doc
, n
);
704 if (!(n
= parse_find_node("class", node
->children
)))
705 goto session_load_bail
;
706 state
->class = parse_string(doc
, n
);
707 if (!(n
= parse_find_node("role", node
->children
)))
708 goto session_load_bail
;
709 state
->role
= parse_string(doc
, n
);
710 if (!(n
= parse_find_node("windowtype", node
->children
)))
711 goto session_load_bail
;
712 state
->type
= parse_int(doc
, n
);
713 if (!(n
= parse_find_node("desktop", node
->children
)))
714 goto session_load_bail
;
715 state
->desktop
= parse_int(doc
, n
);
716 if (!(n
= parse_find_node("x", node
->children
)))
717 goto session_load_bail
;
718 state
->x
= parse_int(doc
, n
);
719 if (!(n
= parse_find_node("y", node
->children
)))
720 goto session_load_bail
;
721 state
->y
= parse_int(doc
, n
);
722 if (!(n
= parse_find_node("width", node
->children
)))
723 goto session_load_bail
;
724 state
->w
= parse_int(doc
, n
);
725 if (!(n
= parse_find_node("height", node
->children
)))
726 goto session_load_bail
;
727 state
->h
= parse_int(doc
, n
);
730 parse_find_node("shaded", node
->children
) != NULL
;
732 parse_find_node("iconic", node
->children
) != NULL
;
734 parse_find_node("skip_pager", node
->children
) != NULL
;
735 state
->skip_taskbar
=
736 parse_find_node("skip_taskbar", node
->children
) != NULL
;
738 parse_find_node("fullscreen", node
->children
) != NULL
;
740 parse_find_node("above", node
->children
) != NULL
;
742 parse_find_node("below", node
->children
) != NULL
;
744 parse_find_node("max_horz", node
->children
) != NULL
;
746 parse_find_node("max_vert", node
->children
) != NULL
;
748 parse_find_node("undecorated", node
->children
) != NULL
;
750 parse_find_node("focused", node
->children
) != NULL
;
752 /* save this. they are in the file in stacking order, so preserve
754 session_saved_state
= g_list_append(session_saved_state
, state
);
758 session_state_free(state
);
761 /* Remove any duplicates. This means that if two windows (or more) are
762 saved with the same session state, we won't restore a session for any
763 of them because we don't know what window to put what on. AHEM FIREFOX.
765 This is going to be an O(2^n) kind of operation unfortunately.
767 for (it
= session_saved_state
; it
; it
= inext
) {
769 gboolean founddup
= FALSE
;
770 ObSessionState
*s1
= it
->data
;
772 inext
= g_list_next(it
);
774 for (jt
= g_list_next(it
); jt
; jt
= jnext
) {
775 ObSessionState
*s2
= jt
->data
;
778 jnext
= g_list_next(jt
);
780 if (s1
->id
&& s2
->id
)
781 match
= strcmp(s1
->id
, s2
->id
) == 0;
782 else if (s1
->command
&& s2
->command
)
783 match
= strcmp(s1
->command
, s2
->command
) == 0;
788 !strcmp(s1
->name
, s2
->name
) &&
789 !strcmp(s1
->class, s2
->class) &&
790 !strcmp(s1
->role
, s2
->role
))
792 session_state_free(s2
);
793 session_saved_state
=
794 g_list_delete_link(session_saved_state
, jt
);
800 session_state_free(s1
);
801 session_saved_state
= g_list_delete_link(session_saved_state
, it
);
808 void session_request_logout(gboolean silent
)
811 SmcRequestSaveYourself(sm_conn
,
815 SmInteractStyleNone
: SmInteractStyleAny
),
816 TRUE
, /* if false, with GSM, it shows the old
821 g_message(_("Not connected to a session manager"));