summaryrefslogtreecommitdiff
path: root/xfce4-session/manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'xfce4-session/manager.c')
-rw-r--r--xfce4-session/manager.c1011
1 files changed, 0 insertions, 1011 deletions
diff --git a/xfce4-session/manager.c b/xfce4-session/manager.c
deleted file mode 100644
index 3af993ae..00000000
--- a/xfce4-session/manager.c
+++ /dev/null
@@ -1,1011 +0,0 @@
-/* $Id$ */
-/*-
- * Copyright (c) 2003,2004 Benedikt Meurer <benny@xfce.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * TODO:
- *
- * - Fix Linux weirdness with utsname.machine
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_SYS_UTSNAME_H
-#include <sys/utsname.h>
-#endif
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_TIME_H
-#include <time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <X11/ICE/ICElib.h>
-#include <X11/ICE/ICEutil.h>
-#include <X11/SM/SMlib.h>
-
-#include <libxfce4util/i18n.h>
-#include <libxfce4util/util.h>
-#include <libxfcegui4/dialogs.h>
-#include <gdk/gdkx.h>
-#include <gtk/gtk.h>
-
-#include "client.h"
-#include "ice-layer.h"
-#include "manager.h"
-#include "startup.h"
-#include "shutdown.h"
-#include "util.h"
-
-#include <xfce4-session/session-control.h>
-#include <xfce4-session/xfce_trayicon.h>
-
-#define XFSM_VERSION 2
-
-/* current manager status */
-int state = MANAGER_IDLE;
-
-/* list of currently connected SM clients */
-GList *clients = NULL;
-
-/* session filename */
-gchar *sessionFile = NULL;
-
-/* type of shutdown to do */
-gint shutdownType = SHUTDOWN_LOGOUT;
-gboolean shutdownSave = TRUE;
-
-/* id of running "Die" timeout if any */
-static guint dieTimeoutId = 0;
-
-/* id of running "Save yourself" timeout if any */
-static guint saveTimeoutId = 0;
-
-/* ICE socket listener objects */
-static int numListeners;
-static IceListenObj *listenObjs;
-
-/* client list GUI */
-GtkWidget *sessionControl = NULL;
-
-/* system tray icon */
-extern XfceTrayIcon *trayIcon;
-
-/* prototypes */
-static Status new_client(SmsConn, SmPointer, unsigned long *, SmsCallbacks *,
- char **);
-static Status register_client(SmsConn, Client *, char *);
-static void interact_request(SmsConn, Client *, int);
-static void interact_done(SmsConn, Client *, Bool);
-static void save_yourself_request(SmsConn, Client *, int, Bool, int, Bool,
- Bool);
-static void save_yourself_phase2_request(SmsConn, Client *);
-static gboolean save_yourself_timeout();
-static void save_yourself_done(SmsConn, Client *, Bool);
-static void close_connection(SmsConn, Client *, int, char **);
-static void set_properties(SmsConn, Client *, int, SmProp **);
-static void delete_properties(SmsConn, Client *, int, char **);
-static void get_properties(SmsConn, Client *);
-
-#define CALLBACK(_callbacks, _callback, _client) \
-do { \
- (void *)_callbacks->_callback.callback = (void *)_callback; \
- (void *)_callbacks->_callback.manager_data = (void *)_client; \
-} while (0)
-
-/*
- * Convince macro
- */
-#define client_set_state(_client, _state) \
-do { \
- CLIENT((_client))->state = _state; \
- xfsm_session_control_update(XFSM_SESSION_CONTROL(sessionControl),\
- CLIENT((_client))); \
-} while (0)
-
-/*
- */
-gboolean
-manager_init(gboolean disable_tcp)
-{
- char *sessionManager;
- char error[2048];
-
- /* check if theres already a session manager running */
- if (g_getenv("SESSION_MANAGER") != NULL) {
- g_warning("Another session manager is already running, unable to continue");
- return(FALSE);
- }
-
- if (!SmsInitialize(PACKAGE, VERSION, new_client, NULL, ice_auth_proc,
- 2048, error)) {
- g_warning("Unable to register XSM protocol: %s", error);
- return(FALSE);
- }
-
-#ifdef HAVE__ICETRANSNOLISTEN
- if (disable_tcp) {
- extern void _IceTransNoListen(char *);
- _IceTransNoListen("tcp");
- }
-#endif
-
- if (!IceListenForConnections(&numListeners, &listenObjs, 2048,
- error)) {
- g_error("Unable to listen for ICE connections: %s", error);
- return(FALSE);
- }
-
- /* setup ICE authentication layer */
- ice_setup_listeners(numListeners, listenObjs);
-
- /* set SESSION_MANAGER environment variable */
- sessionManager = IceComposeNetworkIdList(numListeners, listenObjs);
- xfce_setenv("SESSION_MANAGER", sessionManager, TRUE);
- free(sessionManager);
-
- /* XXX */
- sessionControl = xfsm_session_control_new();
-
- return(TRUE);
-}
-
-/*
- */
-gboolean
-manager_save(void)
-{
- struct utsname name;
- GList *lp;
- FILE *fp;
- int n, v;
-
- g_return_val_if_fail(sessionFile != NULL, FALSE);
-
- if ((n = g_list_length(clients)) == 0) {
- /* nothing to save */
- (void)unlink(sessionFile);
- return(TRUE);
- }
-
- /* get system information */
- if (uname(&name) < 0) {
- g_warning("Unable to retrieve system information: %s",
- g_strerror(errno));
- return(FALSE);
- }
-
- if ((fp = fopen(sessionFile, "wb")) == NULL) {
- g_warning("Unable to open session file %s for writing: %s",
- sessionFile, g_strerror(errno));
- return(FALSE);
- }
-
- /* write version */
- v = XFSM_VERSION;
- if (fwrite(&v, sizeof(v), 1, fp) != 1)
- goto end;
-
- /* write system name */
- fstrwrite(fp, name.sysname);
-
- /* write machine hardware plattform */
- fstrwrite(fp, name.machine);
-
- /* write number of clients */
- if (fwrite(&n, sizeof(n), 1, fp) != 1)
- goto end;
-
- /* save all active clients */
- for (lp = g_list_first(clients); lp; lp = lp->next) {
- Client *client = CLIENT(lp->data);
- gchar **argv;
-
- /*
- * Do not save clients that set SmRestartStyleHint to
- * SmRestartNever.
- */
- if (client_get_restart_style_hint(client) == SmRestartNever)
- continue;
-
- /*
- * Save only clients that have the SmRestartCommand
- * property set.
- */
- if ((argv = client_get_restart_command(client)) == NULL) {
- g_warning("Client %s has no SmRestartCommand set",
- client->id);
- continue;
- }
- g_strfreev(argv);
-
- if (!client_save(client, fp) && ferror(fp))
- break;
- }
-
-end:
- n = !ferror(fp);
- (void)fclose(fp);
- return(n);
-}
-
-/*
- * This does the initial startup. Starting up have to be done after atleast
- * one run through the gtk main loop, else the splash screen will use the
- * old screen height/width that was set before the mcs manager (with the
- * Xrandr plugin) fired up.
- */
-static gboolean
-manager_startup(void)
-{
- /* sort list of pending clients by priority */
- pendingClients = g_list_sort(pendingClients,
- (GCompareFunc)client_compare_priority);
-
- pending_continue(NULL);
-
- return(FALSE);
-}
-
-/*
- */
-gboolean
-manager_restart(void)
-{
- gchar *sysname;
- gchar *machine;
- gchar *hostname;
- struct utsname name;
- Client *client;
- gchar *file;
- FILE *fp;
- int n;
-
- g_return_val_if_fail(sessionFile == NULL, FALSE);
-
- hostname = xfce_gethostname();
- file = g_strdup_printf("xfsm-%s", hostname);
- sessionFile = xfce_get_userfile("sessions", file, NULL);
- g_free(file);
- g_free(hostname);
-
- /* get system information */
- if (uname(&name) < 0) {
- g_warning("Unable to retrieve system information: %s",
- g_strerror(errno));
- return(FALSE);
- }
-
- if ((fp = fopen(sessionFile, "rb")) == NULL) {
- g_warning("Unable to open session file %s for reading: %s",
- sessionFile, g_strerror(errno));
- return(FALSE);
- }
-
- /* read version */
- if (fread(&n, sizeof(n), 1, fp) != 1)
- goto end;
-
- /* version < 2 does not have system information */
- if (n > 1) {
- if ((sysname = fstrread(fp)) == NULL ||
- (machine = fstrread(fp)) == NULL)
- goto end;
-
- /* check if system and machine equals */
- if (strcmp(sysname, name.sysname) != 0 ||
- strcmp(machine, name.machine) != 0) {
- g_warning("Session file %s was written on a different "
- "machine", sessionFile);
- goto end;
- }
- }
-
- /* read number of clients */
- if (fread(&n, sizeof(n), 1, fp) != 1 || n < 1)
- goto end;
-
- while (n-- > 0) {
- if ((client = client_load(fp)) == NULL)
- goto end;
-
- pendingClients = g_list_append(pendingClients, client);
- }
-
- (void)fclose(fp);
-
- (void)g_idle_add((GSourceFunc)manager_startup, NULL);
-
- return(TRUE);
-
-end:
- (void)fclose(fp);
-
- /* notify the user that we were unable to restore the session */
- xfce_err(_(
- "The session manager was unable to restore your\n"
- "previous session. It'll therefore start a default\n"
- "session."));
-
- return(FALSE);
-}
-
-/*
- * Safe way to generate a client id, in case SmsGenerateClientID() fails
- */
-char *
-manager_generate_client_id(SmsConn smsConn)
-{
- static char *addr = NULL;
- static int sequence = 0;
- char *id;
-
- if (smsConn == NULL || (id = SmsGenerateClientID(smsConn)) == NULL) {
- if (addr == NULL) {
- /*
- * Faking our IP address, the 0 below is "unknown"
- * address format (1 would be IP, 2 would be DEC-NET
- * format). Stolen from KDE :-)
- */
- addr = g_strdup_printf("0%.8x", g_random_int());
- }
-
- id = (char *)malloc(50);
- (void)g_snprintf(id, 50, "1%s%.13ld%.10d%.4d", addr,
- (long)time(NULL), (int)getpid(), sequence);
- sequence = (sequence + 1) % 10000;
- }
-
- return(id);
-}
-
-/*
- */
-void
-manager_saveyourself(int saveType, Bool shutdown, int interactStyle, Bool fast)
-{
- GList *lp;
-
- g_return_if_fail(state == MANAGER_IDLE);
-
- shutdownSave = TRUE;
-
- /* ask user whether to logout */
- if (!fast && shutdown && !shutdownDialog(&shutdownType, &shutdownSave))
- return;
-
- /* */
- if (!shutdown || shutdownSave) {
- /* */
- state = shutdown ? MANAGER_SHUTDOWN : MANAGER_CHECKPOINT;
-
- /* put all clients into SaveYourself state */
- for (lp = g_list_first(clients); lp; lp = lp->next) {
- if (client_state(lp->data) == CLIENT_SAVINGLOCAL) {
- /*
- * client is already in saving state, no need
- * to send another SaveYourself message.
- */
- CLIENT(lp->data)->state = CLIENT_SAVING;
- continue;
- }
-
- client_set_state(lp->data, CLIENT_SAVING);
- SmsSaveYourself(CLIENT(lp->data)->smsConn, saveType,
- shutdown, interactStyle, fast);
- }
-
- /* give all clients the chance to complete the SaveYourself phase */
- saveTimeoutId = g_timeout_add(10 * 1000,
- (GSourceFunc)save_yourself_timeout, NULL);
- }
- else {
- /*
- * We are about to shutdown the manager without saving, so
- * send all SM clients the SmDie message.
- */
- state = MANAGER_SHUTDOWNPHASE2;
- for (lp = g_list_first(clients); lp; lp = lp->next)
- SmsDie(CLIENT(lp->data)->smsConn);
-
- /* give all clients the chance to close the connection */
- dieTimeoutId = g_timeout_add(5 * 1000,
- (GSourceFunc)gtk_main_quit, NULL);
- }
-}
-
-/*
- */
-static Status
-new_client(SmsConn smsConn, SmPointer managerData, unsigned long *mask,
- SmsCallbacks *callbacks, char **failureReason)
-{
- Client *client;
-
- client = client_new(smsConn);
-
- CALLBACK(callbacks, register_client, client);
- CALLBACK(callbacks, interact_request, client);
- CALLBACK(callbacks, interact_done, client);
- CALLBACK(callbacks, save_yourself_request, client);
- CALLBACK(callbacks, save_yourself_phase2_request, client);
- CALLBACK(callbacks, save_yourself_done, client);
- CALLBACK(callbacks, close_connection, client);
- CALLBACK(callbacks, set_properties, client);
- CALLBACK(callbacks, delete_properties, client);
- CALLBACK(callbacks, get_properties, client);
-
- *mask = SmsRegisterClientProcMask | SmsInteractRequestProcMask |
- SmsInteractDoneProcMask | SmsSaveYourselfRequestProcMask |
- SmsSaveYourselfP2RequestProcMask | SmsSaveYourselfDoneProcMask |
- SmsCloseConnectionProcMask | SmsSetPropertiesProcMask |
- SmsDeletePropertiesProcMask | SmsGetPropertiesProcMask;
-
- return(True);
-}
-
-/*
- */
-static Status
-register_client(SmsConn smsConn, Client *client, char *previousId)
-{
- gchar *tip;
- GList *lp;
-
- if (previousId != NULL) {
- for (lp = g_list_first(pendingClients); lp; lp = lp->next)
- if (!strcmp(CLIENT(lp->data)->id, previousId))
- break;
-
- /*
- * If previous-ID is not valied, the SM will send a BadValue
- * error message to the client. At this point the SM reverts
- * to the register state and waits for another RegisterClient.
- */
- if (lp == NULL)
- return(False);
-
- /* set initial properties */
- client->nProps = CLIENT(lp->data)->nProps;
- client->props = CLIENT(lp->data)->props;
- client->id = previousId;
-
- /* remove pending client data */
- CLIENT(lp->data)->props = NULL;
- pending_continue(CLIENT(lp->data));
- }
- else {
- /* generate a new client id */
- client->id = manager_generate_client_id(smsConn);
-
- /* previous-ID is no longer needed */
- free(previousId);
- }
-
- /* send register reply to client */
- SmsRegisterClientReply(smsConn, client->id);
-
- /* */
- client->hostname = SmsClientHostName(smsConn);
-
- /* add client to the list of connected clients */
- clients = g_list_append(clients, client);
-
- /*
- * If the client didn't supply a previous-ID field to the
- * RegisterClient message, the SM must send a SaveYourself
- * message with type = Local, shutdown = False, interact-style
- * = None and fast = False immediatly after the RegisterClientReply.
- * The client should respond to this like any other SaveYourself
- * message.
- */
- if (previousId == NULL) {
- client->state = CLIENT_SAVINGLOCAL;
- SmsSaveYourself(smsConn, SmSaveLocal, False,
- SmInteractStyleNone, False);
- }
-
- /* XXX */
- xfsm_session_control_append(XFSM_SESSION_CONTROL(sessionControl),
- client);
-
- /* update the tray icon tooltip */
- tip = g_strdup_printf(_("%u clients connected"),
- g_list_length(clients));
- xfce_tray_icon_set_tooltip(trayIcon, tip, NULL);
- g_free(tip);
-
- return(True);
-}
-
-/*
- */
-static void
-interact_request(SmsConn smsConn, Client *client, int dialogType)
-{
- GList *lp;
-
- g_return_if_fail(state == MANAGER_CHECKPOINT ||
- state == MANAGER_SHUTDOWN);
- g_return_if_fail(client->state == CLIENT_SAVING);
-
- for (lp = g_list_first(clients); lp; lp = lp->next) {
- if (client_state(lp->data) == CLIENT_INTERACTING) {
- /*
- * Theres already a client interacting, so put this
- * one on the wait queue
- */
- client_set_state(client, CLIENT_WAITFORINTERACT);
- return;
- }
- }
-
- /* let this client interact with the user */
- client_set_state(client, CLIENT_INTERACTING);
- SmsInteract(smsConn);
-}
-
-/*
- */
-static void
-interact_done(SmsConn smsConn, Client *client, Bool cancelShutdown)
-{
- GList *lp;
-
- g_return_if_fail(state == MANAGER_CHECKPOINT ||
- state == MANAGER_SHUTDOWN);
- g_return_if_fail(client_state(client) == CLIENT_INTERACTING);
-
- client_set_state(client, CLIENT_SAVING);
-
- /*
- * Setting the cancel-shutdown field to True indicates that the user
- * has requested that the entire shutdown be cancelled. Cancel-
- * shutdown may only be True if the corresponding SaveYourself
- * message specified True for the shutdown field and Any or Error
- * for the interact-style field. Otherwise, cancel-shutdown must be
- * False.
- */
- if (cancelShutdown && state == MANAGER_SHUTDOWN) {
- /* we go into checkpoint state from here... */
- state = MANAGER_CHECKPOINT;
-
- /*
- * If a shutdown is in progress, the user may have the option
- * of cancelling the shutdown. If the shutdown is cancelled
- * (specified in the "Interact Done" message), the session
- * manager should send a "Shutdown Cancelled" message to each
- * client that requested to interact.
- */
- for (lp = g_list_first(clients); lp; lp = lp->next) {
- if (client_state(lp->data) != CLIENT_WAITFORINTERACT)
- continue;
-
- /* reset all clients that are waiting for interact */
- client_set_state(client, CLIENT_SAVING);
- SmsShutdownCancelled(CLIENT(lp->data)->smsConn);
- }
-
- return;
- }
-
- /* Let the next client interact */
- for (lp = g_list_first(clients); lp; lp = lp->next) {
- if (client_state(lp->data) == CLIENT_WAITFORINTERACT) {
- client_set_state(lp->data, CLIENT_INTERACTING);
- SmsInteract(CLIENT(lp->data)->smsConn);
- break;
- }
- }
-}
-
-/*
- */
-static void
-save_yourself_request(SmsConn smsConn, Client *client, int saveType,
- Bool shutdown, int interactStyle, Bool fast, Bool global)
-{
- g_return_if_fail(client_state(client) == CLIENT_IDLE);
-
- if (!global) {
- /*
- * client requests a local checkpoint. We slightly ignore
- * shutdown here, since it does not make sense for a local
- * checkpoint.
- */
- client_set_state(client, CLIENT_SAVINGLOCAL);
- SmsSaveYourself(smsConn, saveType, FALSE, interactStyle, fast);
- }
- else {
- /* request the manager to do a SaveYourself */
- manager_saveyourself(saveType, shutdown, interactStyle, fast);
- }
-}
-
-/*
- */
-static void
-save_yourself_phase2_request(SmsConn smsConn, Client *client)
-{
- GList *lp;
-
- if (state != MANAGER_CHECKPOINT && state != MANAGER_SHUTDOWN) {
- /*
- * If we are not in checkpoint or shutdown state, just
- * send the save yourself phase2.
- */
- SmsSaveYourselfPhase2(client->smsConn);
- return;
- }
-
- client->state = CLIENT_WAITFORPHASE2;
-
- /* check if we are ready to enter Phase2 */
- for (lp = g_list_first(clients); lp; lp = lp->next) {
- if (client_state(lp->data) == CLIENT_SAVING) {
- /* still clients in SaveYourself state */
- return;
- }
- }
-
- /* ok, we are ready to enter SaveYourselfPhase2 */
- for (lp = g_list_first(clients); lp; lp = lp->next) {
- if (client_state(lp->data) == CLIENT_WAITFORPHASE2) {
- client_set_state(lp->data, CLIENT_SAVING);
- SmsSaveYourselfPhase2(CLIENT(lp->data)->smsConn);
- }
- }
-}
-
-/**
- **/
-static gboolean
-save_yourself_timeout()
-{
-#ifdef TESTING_TIMEOUT
- IceConn iceConn;
- Client *client;
- GList *lp;
-
-
- /* find first client to remove */
- for (lp = g_list_first(clients); lp; lp = lp->next) {
- if (client_state(lp->data) != CLIENT_SAVING)
- continue;
-
- client = CLIENT(lp->data);
-
- /* XXX */
- xfsm_session_control_remove(XFSM_SESSION_CONTROL(sessionControl), client);
-
- /* shutdown the XSMP/ICE connection */
- iceConn = SmsGetIceConnection(client->smsConn);
- SmsCleanUp(client->smsConn);
- IceSetShutdownNegotiation(iceConn, False);
- IceCloseConnection(iceConn);
-
- /* remove client */
- clients = g_list_remove(clients, client);
- client_free(client);
-
- /* get the timeout going... */
- return(TRUE);
- }
-#endif
-
- /* no more clients in SaveYourself state */
-
- g_warning("SaveYourself timeout occurred! EVIL! EVIL!");
- return(FALSE);
-}
-
-/*
- */
-static void
-save_yourself_done(SmsConn smsConn, Client *client, Bool success)
-{
- gboolean enterPhase2;
- GList *lp;
-
- /* A client completed a local SaveYourself */
- if (client_state(client) == CLIENT_SAVINGLOCAL) {
- client_set_state(client, CLIENT_IDLE);
- SmsSaveComplete(client->smsConn);
- return;
- }
-
- /* validate client requests */
- if (client_state(client) != CLIENT_SAVING) {
-#ifdef DEBUG
- g_warning("The client %s which is neither in SaveYourself "
- "nor in SaveYourselfPhase2 state send a "
- "SaveYourselfDone message", client->id);
-#endif
- return;
- }
-
- /* manager has to be in checkpoint or shutdown state here */
- g_return_if_fail(state == MANAGER_CHECKPOINT ||
- state == MANAGER_SHUTDOWN);
-
- client_set_state(client, CLIENT_SAVEDONE);
-
- enterPhase2 = FALSE;
-
- /* check if all clients completed the SaveYourself */
- for (lp = g_list_first(clients); lp; lp = lp->next) {
- if (client_state(lp->data) == CLIENT_SAVING) {
- /*
- * atleast one client did not finish the SaveYourself
- * yet, so wait another round.
- */
- return;
- }
- else if (CLIENT(lp->data)->state == CLIENT_WAITFORPHASE2)
- enterPhase2 = TRUE;
- }
-
- /* Remove a running Save Yourself timer */
- if (saveTimeoutId) {
- g_source_remove(saveTimeoutId);
- saveTimeoutId = 0;
- }
-
- /*
- * Ok, all clients completed the SaveYourself Phase1, and there's
- * atleast one client that requested to enter save Phase2, so lets
- * enter SaveYourselfPhase2.
- */
- if (enterPhase2) {
- for (lp = g_list_first(clients); lp; lp = lp->next) {
- if (CLIENT(lp->data)->state != CLIENT_WAITFORPHASE2)
- continue;
-
- client_set_state(lp->data, CLIENT_SAVING);
- SmsSaveYourselfPhase2(CLIENT(lp->data)->smsConn);
- }
-
- return;
- }
-
- /*
- * At this point all clients completed the SaveYourself, so we
- * are now save to complete the CheckPoint (and shutdown the
- * session manager).
- */
- if (!manager_save())
- g_warning("Unable to save session checkpoint");
-
- if (state == MANAGER_CHECKPOINT) {
- /* Notify all clients that we passed the checkpoint */
- for (lp = g_list_first(clients); lp; lp = lp->next) {
-#ifdef DEBUG
- if (CLIENT(lp->data)->state != CLIENT_SAVEDONE) {
- g_warning("Client %s survied in non "
- "CLIENT_SAVEDONE state.",
- CLIENT(lp->data)->id);
- }
-#endif
- client_set_state(lp->data, CLIENT_IDLE);
- SmsSaveComplete(CLIENT(lp->data)->smsConn);
- }
-
- /* reset manager to idle state */
- state = MANAGER_IDLE;
-
- return;
- }
-
- /*
- * We are about to shutdown the manager, so send all SM clients the
- * SmDie message.
- */
- state = MANAGER_SHUTDOWNPHASE2;
- for (lp = g_list_first(clients); lp; lp = lp->next)
- SmsDie(CLIENT(lp->data)->smsConn);
-
- /* give all clients the chance to close the connection */
- dieTimeoutId = g_timeout_add(5 * 1000, (GSourceFunc)gtk_main_quit,NULL);
-}
-
-/*
- */
-static void
-close_connection(SmsConn smsConn, Client *client, int nReasons, char **reasons)
-{
- IceConn iceConn;
- gchar *program;
- gchar *reason;
- gchar *tip;
- GList *lp;
-
- /* XXX */
- xfsm_session_control_remove(XFSM_SESSION_CONTROL(sessionControl),
- client);
-
- /* shutdown the XSMP/ICE connection */
- iceConn = SmsGetIceConnection(smsConn);
- SmsCleanUp(smsConn);
- IceSetShutdownNegotiation(iceConn, False);
- IceCloseConnection(iceConn);
-
- /* remember this client to be in "Disconnect"-state, see below */
- client_set_state(client, CLIENT_DISCONNECTED);
-
- if (state == MANAGER_SHUTDOWNPHASE2) {
- /* Check if there are still clients connected to the manager */
- for (lp = g_list_first(clients); lp; lp = lp->next)
- if (CLIENT(lp->data)->state != CLIENT_DISCONNECTED)
- return;
-
- /* remove a running "Die" timeout */
- if (dieTimeoutId != 0)
- g_source_remove(dieTimeoutId);
-
- /* All clients disconnected before the timeout, nice */
- gtk_main_quit();
- }
- else {
- if ((program = client_get_program(client)) == NULL)
- program = client_get_id(client);
-
- /* we are not in frozen shutdown state, so save to remove */
- clients = g_list_remove(clients, client);
- client_free(client);
-
- if (nReasons) {
- reason = xfce_strjoin("\n", reasons, nReasons);
-
- xfce_err(_(
- "The client \"%s\" closed the connection\n"
- "to the session manager. The following reason\n"
- "was given:\n\n%s"), program, reason);
-
- g_free(reason);
- }
-
- g_free(program);
- }
-
- /* update the tray icon tooltip */
- tip = g_strdup_printf(_("%u clients connected"),
- g_list_length(clients));
- xfce_tray_icon_set_tooltip(trayIcon, tip, NULL);
- g_free(tip);
-
- if (nReasons)
- SmFreeReasons(nReasons, reasons);
-}
-
-/*
- */
-static void
-set_properties(SmsConn smsConn, Client *client, int nProps, SmProp **props)
-{
- int i, j, n;
-
- if (client->props == NULL) {
- /* First time, SetProperties is called, just use the given
- * properties
- */
- client->nProps = nProps;
- client->props = props;
- return;
- }
-
- n = client->nProps;
-
- /* check new array size and update existing properties */
- for (j = 0; j < nProps; j++) {
- for (i = 0; i < n; i++) {
- if (!strcmp(client->props[i]->name, props[j]->name)) {
- /* update existing property */
- SmFreeProperty(client->props[i]);
- client->props[i] = props[j];
- props[j] = NULL;
- break;
- }
- }
-
- if (i == n)
- client->nProps++;
- }
-
- /* resize properties array */
- client->props = (SmProp **)realloc(client->props,
- client->nProps * sizeof(*props));
-
- /* add leftover properties */
- for (j = 0; j < nProps; j++)
- if (props[j] != NULL)
- client->props[n++] = props[j];
-
- free(props);
-
- /* update client list GUI */
- xfsm_session_control_update(XFSM_SESSION_CONTROL(sessionControl),
- client);
-}
-
-/*
- */
-static void
-delete_properties(SmsConn smsConn, Client *client, int numProps,
- char **propNames)
-{
- char **name;
- int n, m;
-
- if (client->props == NULL)
- return;
-
- for (n = m = 0; n < client->nProps; n++) {
- for (name = propNames; name < propNames + numProps; name++) {
- if (!strcmp(client->props[n]->name, *name)) {
- SmFreeProperty(client->props[n]);
- break;
- }
- }
-
- if (name >= propNames + numProps)
- client->props[m++] = client->props[n];
- }
-
- /* any properties left? */
- if ((client->nProps = m) == 0) {
- free(client->props);
- client->props = NULL;
- }
-
- /* free property names */
- for (name = propNames; name < propNames + numProps; name++)
- free(*name);
- free(propNames);
-
- /* update client list GUI */
- xfsm_session_control_update(XFSM_SESSION_CONTROL(sessionControl),
- client);
-}
-
-/*
- */
-static void
-get_properties(SmsConn smsConn, Client *client)
-{
- if (client->props != NULL)
- SmsReturnProperties(smsConn, client->nProps, client->props);
-}
-