diff options
author | Brian Tarricone <brian@tarricone.org> | 2008-10-03 22:51:22 +0000 |
---|---|---|
committer | Brian Tarricone <brian@tarricone.org> | 2008-10-03 22:51:22 +0000 |
commit | c4f978186f4c3972c313907648fc5b5b6ec56a4e (patch) | |
tree | 0a67dbfb820de35c978214a5b483ad5430c57058 /xfce4-session | |
parent | 543f507292680e39d6db40afe56c9821f197cb1c (diff) | |
download | xfce4-session-c4f978186f4c3972c313907648fc5b5b6ec56a4e.tar.gz |
* xfce4-session/*.[ch]: Turn XfsmManager into a GObject, and
remove most of the app-global variables. This is a first
step toward fixing bug 798, as well as making xfce4-session
ready for a D-Bus interface.
(Old svn revision: 28025)
Diffstat (limited to 'xfce4-session')
-rw-r--r-- | xfce4-session/ice-layer.c | 37 | ||||
-rw-r--r-- | xfce4-session/ice-layer.h | 5 | ||||
-rw-r--r-- | xfce4-session/main.c | 35 | ||||
-rw-r--r-- | xfce4-session/shutdown.c | 16 | ||||
-rw-r--r-- | xfce4-session/shutdown.h | 2 | ||||
-rw-r--r-- | xfce4-session/sm-layer.c | 30 | ||||
-rw-r--r-- | xfce4-session/sm-layer.h | 6 | ||||
-rw-r--r-- | xfce4-session/xfsm-client.h | 1 | ||||
-rw-r--r-- | xfce4-session/xfsm-compat-gnome.c | 11 | ||||
-rw-r--r-- | xfce4-session/xfsm-compat-kde.c | 13 | ||||
-rw-r--r-- | xfce4-session/xfsm-global.c | 20 | ||||
-rw-r--r-- | xfce4-session/xfsm-global.h | 13 | ||||
-rw-r--r-- | xfce4-session/xfsm-manager.c | 662 | ||||
-rw-r--r-- | xfce4-session/xfsm-manager.h | 131 | ||||
-rw-r--r-- | xfce4-session/xfsm-properties.c | 2 | ||||
-rw-r--r-- | xfce4-session/xfsm-startup.c | 199 | ||||
-rw-r--r-- | xfce4-session/xfsm-startup.h | 7 |
17 files changed, 785 insertions, 405 deletions
diff --git a/xfce4-session/ice-layer.c b/xfce4-session/ice-layer.c index 4eb88c06..ecbafb9b 100644 --- a/xfce4-session/ice-layer.c +++ b/xfce4-session/ice-layer.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2003-2004 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2008 Brian Tarricone <bjt23@cornell.edu> * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -51,6 +52,13 @@ #include <xfce4-session/xfsm-global.h> #include <xfce4-session/xfsm-manager.h> +typedef struct +{ + XfsmManager *manager; + IceConn ice_conn; +} XfsmIceConnData; + + /* prototypes */ static void ice_error_handler (IceConn); static gboolean ice_process_messages (GIOChannel *channel, @@ -98,13 +106,14 @@ ice_process_messages (GIOChannel *channel, gpointer user_data) { IceProcessMessagesStatus status; - IceConn ice_conn = (IceConn) user_data; + XfsmIceConnData *icdata = user_data; - status = IceProcessMessages (ice_conn, NULL, NULL); + status = IceProcessMessages (icdata->ice_conn, NULL, NULL); if (status == IceProcessMessagesIOError) { - xfsm_manager_close_connection_by_ice_conn (ice_conn); + xfsm_manager_close_connection_by_ice_conn (icdata->manager, + icdata->ice_conn); /* remove the I/O watch */ return FALSE; @@ -121,12 +130,17 @@ ice_connection_watch (IceConn ice_conn, Bool opening, IcePointer *watch_data) { - GIOChannel *channel; - guint watchid; - gint fd; + XfsmManager *manager = XFSM_MANAGER (client_data); + GIOChannel *channel; + guint watchid; + gint fd; if (opening) { + XfsmIceConnData *icdata = g_new(XfsmIceConnData, 1); + icdata->manager = manager; + icdata->ice_conn = ice_conn; + fd = IceConnectionNumber (ice_conn); /* Make sure we don't pass on these file descriptors to an @@ -135,8 +149,10 @@ ice_connection_watch (IceConn ice_conn, fcntl (fd, F_SETFD, fcntl (fd, F_GETFD, 0) | FD_CLOEXEC); channel = g_io_channel_unix_new (fd); - watchid = g_io_add_watch (channel, G_IO_ERR | G_IO_HUP | G_IO_IN, - ice_process_messages, ice_conn); + watchid = g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, + G_IO_ERR | G_IO_HUP | G_IO_IN, + ice_process_messages, + icdata, (GDestroyNotify) g_free); g_io_channel_unref (channel); *watch_data = (IcePointer) GUINT_TO_POINTER (watchid); @@ -271,7 +287,8 @@ ice_auth_add (FILE *setup_fp, gboolean ice_setup_listeners (int num_listeners, - IceListenObj *listen_objs) + IceListenObj *listen_objs, + XfsmManager *manager) { GIOChannel *channel; char *auth_setup_file; @@ -282,7 +299,7 @@ ice_setup_listeners (int num_listeners, int n; IceSetIOErrorHandler (ice_error_handler); - IceAddConnectionWatch (ice_connection_watch, NULL); + IceAddConnectionWatch (ice_connection_watch, manager); cleanup_fp = ice_tmpfile(&auth_cleanup_file); if (cleanup_fp == NULL) diff --git a/xfce4-session/ice-layer.h b/xfce4-session/ice-layer.h index 82edce5c..8425b3bb 100644 --- a/xfce4-session/ice-layer.h +++ b/xfce4-session/ice-layer.h @@ -26,9 +26,12 @@ #include <glib.h> +#include "xfsm-manager.h" + Bool ice_auth_proc (char *hostname); gboolean ice_setup_listeners (int num_listeners, - IceListenObj *listen_objs); + IceListenObj *listen_objs, + XfsmManager *manager); void ice_cleanup (void); #endif /* !__XFSM_ICE_LAYER_H__ */ diff --git a/xfce4-session/main.c b/xfce4-session/main.c index acf793b4..e7c43198 100644 --- a/xfce4-session/main.c +++ b/xfce4-session/main.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2003-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2008 Brian Tarricone <bjt23@cornell.edu> * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -125,9 +126,10 @@ usage (int exit_code) static void -init_display (GdkDisplay *dpy, - XfceRc *rc, - gboolean disable_tcp) +init_display (XfsmManager *manager, + GdkDisplay *dpy, + XfceRc *rc, + gboolean disable_tcp) { const gchar *engine; @@ -140,7 +142,7 @@ init_display (GdkDisplay *dpy, gdk_flush (); xfce_rc_set_group (rc, "General"); - sm_init (rc, disable_tcp); + sm_init (rc, disable_tcp, manager); /* start xfsettingsd */ if ( !g_spawn_command_line_async ("xfsettingsd", NULL)) @@ -155,7 +157,9 @@ init_display (GdkDisplay *dpy, static void -initialize (int argc, char **argv) +initialize (XfsmManager *manager, + int argc, + char **argv) { gboolean disable_tcp = FALSE; GdkDisplay *dpy; @@ -192,7 +196,7 @@ initialize (int argc, char **argv) rc = xfsm_open_config (TRUE); dpy = gdk_display_get_default (); - init_display (dpy, rc, disable_tcp); + init_display (manager, dpy, rc, disable_tcp); /* verify that the DNS settings are ok */ xfsm_splash_screen_next (splash_screen, _("Verifying DNS settings")); @@ -200,13 +204,9 @@ initialize (int argc, char **argv) xfsm_splash_screen_next (splash_screen, _("Loading session data")); - xfce_rc_set_group (rc, "Compatibility"); - compat_gnome = xfce_rc_read_bool_entry (rc, "LaunchGnome", FALSE); - compat_kde = xfce_rc_read_bool_entry (rc, "LaunchKDE", FALSE); - xfce_rc_set_group (rc, "General"); xfsm_startup_init (rc); - xfsm_manager_init (rc); + xfsm_manager_load (manager, rc); /* cleanup obsolete entries */ xfce_rc_set_group (rc, "General"); @@ -223,8 +223,8 @@ initialize (int argc, char **argv) int main (int argc, char **argv) { - /* imported from xfsm-manager.c */ - extern gint shutdown_type; + XfsmManager *manager; + gint shutdown_type; xfce_textdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8"); @@ -238,11 +238,14 @@ main (int argc, char **argv) */ gdk_set_sm_client_id (xfsm_manager_generate_client_id (NULL)); - initialize (argc, argv); - - xfsm_manager_restart (); + manager = xfsm_manager_new (); + initialize (manager, argc, argv); + xfsm_manager_restart (manager); gtk_main (); + + shutdown_type = xfsm_manager_get_shutdown_type (manager); + g_object_unref (manager); ice_cleanup (); diff --git a/xfce4-session/shutdown.c b/xfce4-session/shutdown.c index 171d5843..a9a2e7b1 100644 --- a/xfce4-session/shutdown.c +++ b/xfce4-session/shutdown.c @@ -63,7 +63,7 @@ static GtkWidget *shutdown_dialog = NULL; #ifdef SESSION_SCREENSHOTS static void -screenshot_save (GdkPixmap *pm, GdkRectangle *area) +screenshot_save (const gchar *session_name, GdkPixmap *pm, GdkRectangle *area) { gchar *display_name; gchar *resource; @@ -137,7 +137,7 @@ halt_button_clicked (GtkWidget *b, gint *shutdownType) /* */ gboolean -shutdownDialog(gint *shutdownType, gboolean *saveSession) +shutdownDialog(const gchar *sessionName, gint *shutdownType, gboolean *saveSession) { gboolean accessibility; XfsmFadeout *fadeout = NULL; @@ -549,7 +549,7 @@ shutdownDialog(gint *shutdownType, gboolean *saveSession) if (result == GTK_RESPONSE_OK) { xfce_rc_set_group (rc, "General"); - xfce_rc_write_entry (rc, "SessionName", session_name); + xfce_rc_write_entry (rc, "SessionName", sessionName); xfce_rc_write_bool_entry (rc, "SaveOnExit", *saveSession); } else @@ -562,7 +562,7 @@ shutdownDialog(gint *shutdownType, gboolean *saveSession) if (screenshot_pm != NULL) { if (result == GTK_RESPONSE_OK) - screenshot_save (screenshot_pm, &screenshot_area); + screenshot_save (sessionName, screenshot_pm, &screenshot_area); g_object_unref (G_OBJECT (screenshot_pm)); } @@ -581,11 +581,9 @@ xfsm_shutdown(gint type) { gboolean result; - if (compat_gnome) - xfsm_compat_gnome_shutdown (); - - if (compat_kde) - xfsm_compat_kde_shutdown (); + /* these two remember if they were started or not */ + xfsm_compat_gnome_shutdown (); + xfsm_compat_kde_shutdown (); /* kill legacy clients */ xfsm_legacy_shutdown (); diff --git a/xfce4-session/shutdown.h b/xfce4-session/shutdown.h index 6fc4b2bd..ec2d1fcb 100644 --- a/xfce4-session/shutdown.h +++ b/xfce4-session/shutdown.h @@ -30,7 +30,7 @@ #define SHUTDOWN_HALT 2 /* prototypes */ -extern gboolean shutdownDialog(gint *, gboolean *); +extern gboolean shutdownDialog(const gchar *, gint *, gboolean *); extern gint xfsm_shutdown(gint); #endif /* !__XFSM_SHUTDOWN_H__ */ diff --git a/xfce4-session/sm-layer.c b/xfce4-session/sm-layer.c index 620d4a98..18f2efc8 100644 --- a/xfce4-session/sm-layer.c +++ b/xfce4-session/sm-layer.c @@ -97,8 +97,9 @@ static IceListenObj *listen_objs; void -sm_init (XfceRc *rc, - gboolean disable_tcp) +sm_init (XfceRc *rc, + gboolean disable_tcp, + XfsmManager *manager) { char *network_idlist; char error[2048]; @@ -119,7 +120,7 @@ sm_init (XfceRc *rc, #endif } - if (!SmsInitialize (PACKAGE, VERSION, sm_new_client, NULL, ice_auth_proc, + if (!SmsInitialize (PACKAGE, VERSION, sm_new_client, manager, ice_auth_proc, 2048, error)) { fprintf (stderr, "xfce4-session: Unable to register XSM protocol: %s\n", error); @@ -132,7 +133,7 @@ sm_init (XfceRc *rc, exit (EXIT_FAILURE); } - ice_setup_listeners (num_listeners, listen_objs); + ice_setup_listeners (num_listeners, listen_objs, manager); network_idlist = IceComposeNetworkIdList (num_listeners, listen_objs); xfce_setenv ("SESSION_MANAGER", network_idlist, TRUE); @@ -147,13 +148,14 @@ sm_new_client (SmsConn sms_conn, SmsCallbacks *callbacks, char **failure_reason) { - XfsmClient *client; - gchar *error = NULL; + XfsmManager *manager = XFSM_MANAGER (manager_data); + XfsmClient *client; + gchar *error = NULL; xfsm_verbose ("ICE connection fd = %d, received NEW CLIENT\n\n", IceConnectionNumber (SmsGetIceConnection (sms_conn))); - client = xfsm_manager_new_client (sms_conn, &error); + client = xfsm_manager_new_client (manager, sms_conn, &error); if (client == NULL) { xfsm_verbose ("NEW CLIENT failed: %s\n", error); @@ -202,7 +204,7 @@ sm_register_client (SmsConn sms_conn, IceConnectionNumber (SmsGetIceConnection (sms_conn)), previous_id != NULL ? previous_id : "None"); - result = xfsm_manager_register_client (client, previous_id); + result = xfsm_manager_register_client (client->manager, client, previous_id); if (previous_id != NULL) free (previous_id); @@ -221,7 +223,7 @@ sm_interact_request (SmsConn sms_conn, xfsm_verbose ("Client Id = %s, received INTERACT REQUEST [Dialog type = %s]\n\n", client->id, dialog_type == SmDialogError ? "Error" : "Normal"); - xfsm_manager_interact (client, dialog_type); + xfsm_manager_interact (client->manager, client, dialog_type); } @@ -235,7 +237,7 @@ sm_interact_done (SmsConn sms_conn, xfsm_verbose ("Client Id = %s, received INTERACT DONE [Cancel shutdown = %s]\n\n", client->id, cancel_shutdown ? "True" : "False"); - xfsm_manager_interact_done (client, cancel_shutdown); + xfsm_manager_interact_done (client->manager, client, cancel_shutdown); } @@ -266,7 +268,7 @@ sm_save_yourself_request (SmsConn sms_conn, xfsm_verbose ("\n"); } - xfsm_manager_save_yourself (client, save_type, shutdown, interact_style, fast, global); + xfsm_manager_save_yourself (client->manager, client, save_type, shutdown, interact_style, fast, global); } @@ -278,7 +280,7 @@ sm_save_yourself_phase2_request (SmsConn sms_conn, xfsm_verbose ("Client Id = %s, received SAVE YOURSELF PHASE2 REQUEST\n\n", client->id); - xfsm_manager_save_yourself_phase2 (client); + xfsm_manager_save_yourself_phase2 (client->manager, client); } @@ -292,7 +294,7 @@ sm_save_yourself_done (SmsConn sms_conn, xfsm_verbose ("Client Id = %s, received SAVE YOURSELF DONE [Success = %s]\n\n", client->id, success ? "True" : "False"); - xfsm_manager_save_yourself_done (client, success); + xfsm_manager_save_yourself_done (client->manager, client, success); } @@ -314,7 +316,7 @@ sm_close_connection (SmsConn sms_conn, xfsm_verbose ("\n"); } - xfsm_manager_close_connection (client, TRUE); + xfsm_manager_close_connection (client->manager, client, TRUE); if (num_reasons > 0) SmFreeReasons (num_reasons, reasons); diff --git a/xfce4-session/sm-layer.h b/xfce4-session/sm-layer.h index d67d2e71..acfa8e8b 100644 --- a/xfce4-session/sm-layer.h +++ b/xfce4-session/sm-layer.h @@ -24,6 +24,10 @@ #include <libxfce4util/libxfce4util.h> -void sm_init (XfceRc *rc, gboolean disable_tcp); +#include "xfsm-manager.h" + +void sm_init (XfceRc *rc, + gboolean disable_tcp, + XfsmManager *manager); #endif /* !__SM_LAYER_H__ */ diff --git a/xfce4-session/xfsm-client.h b/xfce4-session/xfsm-client.h index dc71a79d..a06387d9 100644 --- a/xfce4-session/xfsm-client.h +++ b/xfce4-session/xfsm-client.h @@ -46,6 +46,7 @@ struct _XfsmClient XfsmProperties *properties; SmsConn sms_conn; guint save_timeout_id; + gpointer manager; /* (XfsmManager *) */ }; diff --git a/xfce4-session/xfsm-compat-gnome.c b/xfce4-session/xfsm-compat-gnome.c index aa8c34d7..a8f0c435 100644 --- a/xfce4-session/xfsm-compat-gnome.c +++ b/xfce4-session/xfsm-compat-gnome.c @@ -67,6 +67,7 @@ static GConfClient *gnome_conf_client = NULL; #endif +static gboolean gnome_compat_started = FALSE; static pid_t gnome_keyring_daemon_pid = 0; static Window gnome_smproxy_window = None; @@ -237,6 +238,9 @@ xfsm_compat_gnome_smproxy_shutdown (void) void xfsm_compat_gnome_startup (XfsmSplashScreen *splash) { + if (G_UNLIKELY (gnome_compat_started)) + return; + xfsm_compat_gnome_smproxy_startup (); /* fire up the keyring daemon */ @@ -260,6 +264,8 @@ xfsm_compat_gnome_startup (XfsmSplashScreen *splash) } } #endif + + gnome_compat_started = TRUE; } @@ -269,6 +275,9 @@ xfsm_compat_gnome_shutdown (void) GError *error = NULL; gint status; + if (G_UNLIKELY (!gnome_compat_started)) + return; + /* shutdown the keyring daemon */ gnome_keyring_daemon_shutdown (); @@ -295,5 +304,7 @@ xfsm_compat_gnome_shutdown (void) } xfsm_compat_gnome_smproxy_shutdown (); + + gnome_compat_started = FALSE; } diff --git a/xfce4-session/xfsm-compat-kde.c b/xfce4-session/xfsm-compat-kde.c index 438a5689..f7dab1de 100644 --- a/xfce4-session/xfsm-compat-kde.c +++ b/xfce4-session/xfsm-compat-kde.c @@ -48,6 +48,9 @@ #include <xfce4-session/xfsm-compat-kde.h> +static gboolean kde_compat_started = FALSE; + + static gboolean run_timeout (gpointer user_data) { @@ -114,6 +117,9 @@ xfsm_compat_kde_startup (XfsmSplashScreen *splash) { gchar command[256]; + if (G_UNLIKELY (kde_compat_started)) + return; + if (G_LIKELY (splash != NULL)) xfsm_splash_screen_next (splash, _("Starting KDE services")); @@ -132,15 +138,22 @@ xfsm_compat_kde_startup (XfsmSplashScreen *splash) "KDE_MULTIHEAD \"true\""); run (command); } + + kde_compat_started = TRUE; } void xfsm_compat_kde_shutdown (void) { + if (G_UNLIKELY (!kde_compat_started)) + return; + /* shutdown KDE services */ run ("kdeinit_shutdown"); run ("dcopserver_shutdown"); run ("artsshell -q terminate"); + + kde_compat_started = FALSE; } diff --git a/xfce4-session/xfsm-global.c b/xfce4-session/xfsm-global.c index 5d3b0286..8951bbb2 100644 --- a/xfce4-session/xfsm-global.c +++ b/xfce4-session/xfsm-global.c @@ -36,20 +36,18 @@ /* global variables */ gboolean verbose = FALSE; -gboolean compat_kde = FALSE; -gboolean compat_gnome = FALSE; -GList *starting_properties = NULL; -GList *pending_properties = NULL; -GList *restart_properties = NULL; -GList *running_clients = NULL; -gchar *session_name = NULL; -gchar *session_file = NULL; -GList *failsafe_clients = NULL; -gboolean failsafe_mode = TRUE; -gint shutdown_type = SHUTDOWN_LOGOUT; XfsmSplashScreen *splash_screen = NULL; void +xfsm_failsafe_client_free (FailsafeClient *fclient) +{ + if (fclient->command) + g_strfreev (fclient->command); + g_free (fclient); +} + + +void xfsm_enable_verbose (void) { if (!verbose) diff --git a/xfce4-session/xfsm-global.h b/xfce4-session/xfsm-global.h index 25b523ad..f6102963 100644 --- a/xfce4-session/xfsm-global.h +++ b/xfce4-session/xfsm-global.h @@ -31,23 +31,14 @@ struct _FailsafeClient gchar **command; GdkScreen *screen; }; + +void xfsm_failsafe_client_free (FailsafeClient *fclient); #define DEFAULT_SESSION_NAME "Default" extern gboolean verbose; -extern gboolean compat_kde; -extern gboolean compat_gnome; -extern GList *starting_properties; -extern GList *pending_properties; -extern GList *restart_properties; -extern GList *running_clients; -extern gchar *session_name; -extern gchar *session_file; -extern GList *failsafe_clients; -extern gboolean failsafe_mode; -extern gint shutdown_type; extern XfsmSplashScreen *splash_screen; diff --git a/xfce4-session/xfsm-manager.c b/xfce4-session/xfsm-manager.c index eeadaaa1..b271d8fc 100644 --- a/xfce4-session/xfsm-manager.c +++ b/xfce4-session/xfsm-manager.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2003-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2008 Brian Tarricone <bjt23@cornell.edu> * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -67,36 +68,130 @@ #define DEFAULT_SESSION_NAME "Default" +struct _XfsmManager +{ + GObject parent; + + XfsmManagerState state; + gint shutdown_type; + + gboolean session_chooser; + gchar *session_name; + gchar *session_file; + + gboolean compat_gnome; + gboolean compat_kde; + + GQueue *starting_properties; + GQueue *pending_properties; + GQueue *restart_properties; + GQueue *running_clients; + + gboolean failsafe_mode; + GQueue *failsafe_clients; + + guint die_timeout_id; +}; + +typedef struct _XfsmManagerClass +{ + GObjectClass parent; +} XfsmManagerClass; + + /* Prototypes */ -static gboolean xfsm_manager_startup (void); -static void xfsm_manager_load_settings (XfceRc *rc); -static gboolean xfsm_manager_load_session (void); +static void xfsm_manager_class_init (XfsmManagerClass *klass); +static void xfsm_manager_init (XfsmManager *manager); +static void xfsm_manager_finalize (GObject *obj); + +static gboolean xfsm_manager_startup (XfsmManager *manager); +static gboolean xfsm_manager_save_timeout (gpointer client_data); +static void xfsm_manager_load_settings (XfsmManager *manager, + XfceRc *rc); +static gboolean xfsm_manager_load_session (XfsmManager *manager); static GdkPixbuf *xfsm_manager_load_session_preview (const gchar *name); -/* - Static data - */ -static XfsmManagerState state = XFSM_MANAGER_STARTUP; -static gboolean session_chooser = FALSE; -static guint die_timeout_id = 0; +G_DEFINE_TYPE(XfsmManager, xfsm_manager, G_TYPE_OBJECT) + + +static void +xfsm_manager_class_init (XfsmManagerClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *)klass; + + gobject_class->finalize = xfsm_manager_finalize; +} + + +static void +xfsm_manager_init (XfsmManager *manager) +{ + manager->state = XFSM_MANAGER_STARTUP; + manager->session_chooser = FALSE; + manager->failsafe_mode = TRUE; + manager->shutdown_type = SHUTDOWN_LOGOUT; + + manager->pending_properties = g_queue_new (); + manager->starting_properties = g_queue_new (); + manager->restart_properties = g_queue_new (); + manager->running_clients = g_queue_new (); + manager->failsafe_clients = g_queue_new (); +} + + +static void +xfsm_manager_finalize (GObject *obj) +{ + XfsmManager *manager = XFSM_MANAGER(obj); + + if (manager->die_timeout_id != 0) + g_source_remove (manager->die_timeout_id); + + g_queue_foreach (manager->pending_properties, (GFunc) xfsm_properties_free, NULL); + g_queue_free (manager->pending_properties); + + g_queue_foreach (manager->starting_properties, (GFunc) xfsm_properties_free, NULL); + g_queue_free (manager->starting_properties); + + g_queue_foreach (manager->restart_properties, (GFunc) xfsm_properties_free, NULL); + g_queue_free (manager->restart_properties); + + g_queue_foreach (manager->running_clients, (GFunc) xfsm_client_free, NULL); + g_queue_free (manager->running_clients); + + g_queue_foreach (manager->failsafe_clients, (GFunc) xfsm_failsafe_client_free, NULL); + g_queue_free (manager->failsafe_clients); + + g_free (manager->session_name); + g_free (manager->session_file); + + G_OBJECT_CLASS (xfsm_manager_parent_class)->finalize (obj); +} + + +XfsmManager * +xfsm_manager_new (void) +{ + return g_object_new (XFSM_TYPE_MANAGER, NULL); +} static gboolean -xfsm_manager_startup (void) +xfsm_manager_startup (XfsmManager *manager) { - xfsm_startup_foreign (); - pending_properties = g_list_sort (pending_properties, - (GCompareFunc) xfsm_properties_compare); - xfsm_startup_begin (); + xfsm_startup_foreign (manager); + g_queue_sort (manager->pending_properties, (GCompareDataFunc) xfsm_properties_compare, NULL); + xfsm_startup_begin (manager); return FALSE; } static void -xfsm_manager_restore_active_workspace (XfceRc *rc) +xfsm_manager_restore_active_workspace (XfsmManager *manager, + XfceRc *rc) { WnckWorkspace *workspace; GdkDisplay *display; @@ -125,7 +220,8 @@ xfsm_manager_restore_active_workspace (XfceRc *rc) void -xfsm_manager_handle_failed_client (XfsmProperties *properties) +xfsm_manager_handle_failed_client (XfsmManager *manager, + XfsmProperties *properties) { /* Handle apps that failed to start here */ @@ -143,13 +239,14 @@ xfsm_manager_handle_failed_client (XfsmProperties *properties) NULL, NULL); } - if (starting_properties == NULL) - xfsm_startup_session_continue (); + if (g_queue_peek_head (manager->starting_properties) == NULL) + xfsm_startup_session_continue (manager); } static gboolean -xfsm_manager_choose_session (XfceRc *rc) +xfsm_manager_choose_session (XfsmManager *manager, + XfceRc *rc) { XfsmSessionInfo *session; GdkPixbuf *preview_default = NULL; @@ -193,7 +290,7 @@ xfsm_manager_choose_session (XfceRc *rc) if (sessions != NULL) { result = xfsm_splash_screen_choose (splash_screen, sessions, - session_name, &name); + manager->session_name, &name); if (result == XFSM_CHOOSE_LOGOUT) { @@ -205,9 +302,9 @@ xfsm_manager_choose_session (XfceRc *rc) load = TRUE; } - if (session_name != NULL) - g_free (session_name); - session_name = name; + if (manager->session_name != NULL) + g_free (manager->session_name); + manager->session_name = name; for (lp = sessions; lp != NULL; lp = lp->next) { @@ -226,27 +323,27 @@ xfsm_manager_choose_session (XfceRc *rc) static gboolean -xfsm_manager_load_session (void) +xfsm_manager_load_session (XfsmManager *manager) { XfsmProperties *properties; gchar buffer[1024]; XfceRc *rc; gint count; - if (!g_file_test (session_file, G_FILE_TEST_IS_REGULAR)) + if (!g_file_test (manager->session_file, G_FILE_TEST_IS_REGULAR)) return FALSE; - rc = xfce_rc_simple_open (session_file, FALSE); + rc = xfce_rc_simple_open (manager->session_file, FALSE); if (G_UNLIKELY (rc == NULL)) return FALSE; - if (session_chooser && !xfsm_manager_choose_session (rc)) + if (manager->session_chooser && !xfsm_manager_choose_session (manager, rc)) { xfce_rc_close (rc); return FALSE; } - g_snprintf (buffer, 1024, "Session: %s", session_name); + g_snprintf (buffer, 1024, "Session: %s", manager->session_name); xfce_rc_set_group (rc, buffer); count = xfce_rc_read_int_entry (rc, "Count", 0); @@ -263,7 +360,7 @@ xfsm_manager_load_session (void) if (G_UNLIKELY (properties == NULL)) continue; if (xfsm_properties_check (properties)) - pending_properties = g_list_append (pending_properties, properties); + g_queue_push_tail (manager->pending_properties, properties); else xfsm_properties_free (properties); } @@ -273,12 +370,13 @@ xfsm_manager_load_session (void) xfce_rc_close (rc); - return pending_properties != NULL; + return g_queue_peek_head (manager->pending_properties) != NULL; } static gboolean -xfsm_manager_load_failsafe (XfceRc *rc) +xfsm_manager_load_failsafe (XfsmManager *manager, + XfceRc *rc) { FailsafeClient *fclient; const gchar *old_group; @@ -314,7 +412,7 @@ xfsm_manager_load_failsafe (XfceRc *rc) fclient = g_new0 (FailsafeClient, 1); fclient->command = xfce_rc_read_list_entry (rc, command_entry, NULL); fclient->screen = gdk_display_get_screen (display, n_screen); - failsafe_clients = g_list_append (failsafe_clients, fclient); + g_queue_push_tail (manager->failsafe_clients, fclient); } } else @@ -322,41 +420,42 @@ xfsm_manager_load_failsafe (XfceRc *rc) fclient = g_new0 (FailsafeClient, 1); fclient->command = command; fclient->screen = gdk_screen_get_default (); - failsafe_clients = g_list_append (failsafe_clients, fclient); + g_queue_push_tail (manager->failsafe_clients, fclient); } } xfce_rc_set_group (rc, old_group); - return failsafe_clients != NULL; + return g_queue_peek_head (manager->failsafe_clients) != NULL; } static void -xfsm_manager_load_settings (XfceRc *rc) +xfsm_manager_load_settings (XfsmManager *manager, + XfceRc *rc) { gboolean session_loaded = FALSE; const gchar *name; name = xfce_rc_read_entry (rc, "SessionName", NULL); if (name != NULL && *name != '\0') - session_name = g_strdup (name); + manager->session_name = g_strdup (name); else - session_name = g_strdup (DEFAULT_SESSION_NAME); + manager->session_name = g_strdup (DEFAULT_SESSION_NAME); xfce_rc_set_group (rc, "Chooser"); - session_chooser = xfce_rc_read_bool_entry (rc, "AlwaysDisplay", FALSE); + manager->session_chooser = xfce_rc_read_bool_entry (rc, "AlwaysDisplay", FALSE); - session_loaded = xfsm_manager_load_session (); + session_loaded = xfsm_manager_load_session (manager); if (session_loaded) { - xfsm_verbose ("Session \"%s\" loaded successfully.\n\n", session_name); - failsafe_mode = FALSE; + xfsm_verbose ("Session \"%s\" loaded successfully.\n\n", manager->session_name); + manager->failsafe_mode = FALSE; } else { - if (!xfsm_manager_load_failsafe (rc)) + if (!xfsm_manager_load_failsafe (manager, rc)) { fprintf (stderr, "xfce4-session: Unable to load failsafe session, exiting. Please check\n" " the value of the environment variable XDG_CONFIG_DIRS\n" @@ -365,13 +464,14 @@ xfsm_manager_load_settings (XfceRc *rc) xfce_rc_close (rc); exit (EXIT_FAILURE); } - failsafe_mode = TRUE; + manager->failsafe_mode = TRUE; } } void -xfsm_manager_init (XfceRc *rc) +xfsm_manager_load (XfsmManager *manager, + XfceRc *rc) { gchar *display_name; gchar *resource_name; @@ -379,6 +479,10 @@ xfsm_manager_init (XfceRc *rc) gchar *s; #endif + xfce_rc_set_group (rc, "Compatibility"); + manager->compat_gnome = xfce_rc_read_bool_entry (rc, "LaunchGnome", FALSE); + manager->compat_kde = xfce_rc_read_bool_entry (rc, "LaunchKDE", FALSE); + xfce_rc_set_group (rc, "General"); display_name = xfce_gdk_display_get_fullname (gdk_display_get_default ()); @@ -391,57 +495,57 @@ xfsm_manager_init (XfceRc *rc) #endif resource_name = g_strconcat ("sessions/xfce4-session-", display_name, NULL); - session_file = xfce_resource_save_location (XFCE_RESOURCE_CACHE, resource_name, TRUE); + manager->session_file = xfce_resource_save_location (XFCE_RESOURCE_CACHE, resource_name, TRUE); g_free (resource_name); g_free (display_name); - xfsm_manager_load_settings (rc); + xfsm_manager_load_settings (manager, rc); } gboolean -xfsm_manager_restart (void) +xfsm_manager_restart (XfsmManager *manager) { GdkPixbuf *preview; unsigned steps; - g_assert (session_name != NULL); + g_assert (manager->session_name != NULL); /* setup legacy application handling */ xfsm_legacy_init (); /* tell splash screen that the session is starting now */ - preview = xfsm_manager_load_session_preview (session_name); + preview = xfsm_manager_load_session_preview (manager->session_name); if (preview == NULL) preview = gdk_pixbuf_from_pixdata (&chooser_icon_data, FALSE, NULL); - steps = g_list_length (failsafe_mode ? failsafe_clients : pending_properties); - xfsm_splash_screen_start (splash_screen, session_name, preview, steps); + steps = g_queue_get_length (manager->failsafe_mode ? manager->failsafe_clients : manager->pending_properties); + xfsm_splash_screen_start (splash_screen, manager->session_name, preview, steps); g_object_unref (preview); - g_idle_add ((GSourceFunc) xfsm_manager_startup, NULL); + g_idle_add ((GSourceFunc) xfsm_manager_startup, manager); return TRUE; } void -xfsm_manager_signal_startup_done (void) +xfsm_manager_signal_startup_done (XfsmManager *manager) { gchar buffer[1024]; XfceRc *rc; xfsm_verbose ("Manager finished startup, entering IDLE mode now\n\n"); - state = XFSM_MANAGER_IDLE; + manager->state = XFSM_MANAGER_IDLE; - if (!failsafe_mode) + if (!manager->failsafe_mode) { /* restore active workspace, this has to be done after the * window manager is up, so we do it last. */ - g_snprintf (buffer, 1024, "Session: %s", session_name); - rc = xfce_rc_simple_open (session_file, TRUE); + g_snprintf (buffer, 1024, "Session: %s", manager->session_name); + rc = xfce_rc_simple_open (manager->session_file, TRUE); xfce_rc_set_group (rc, buffer); - xfsm_manager_restore_active_workspace (rc); + xfsm_manager_restore_active_workspace (manager, rc); xfce_rc_close (rc); /* start legacy applications now */ @@ -491,53 +595,67 @@ xfsm_manager_generate_client_id (SmsConn sms_conn) XfsmClient* -xfsm_manager_new_client (SmsConn sms_conn, - gchar **error) +xfsm_manager_new_client (XfsmManager *manager, + SmsConn sms_conn, + gchar **error) { - if (G_UNLIKELY (state != XFSM_MANAGER_IDLE) - && G_UNLIKELY (state != XFSM_MANAGER_STARTUP)) + XfsmClient *client = NULL; + + if (G_UNLIKELY (manager->state != XFSM_MANAGER_IDLE) + && G_UNLIKELY (manager->state != XFSM_MANAGER_STARTUP)) { if (error != NULL) *error = "We don't accept clients while in CheckPoint/Shutdown state!"; return NULL; } - return xfsm_client_new (sms_conn); + client = xfsm_client_new (sms_conn); + client->manager = manager; /* dirty hack until client is a GObject */ + return client; +} + + +static gint +xfsm_properties_queue_find (gconstpointer a, + gconstpointer b) +{ + XfsmProperties *properties = XFSM_PROPERTIES (a); + const gchar *previous_id = (const gchar *) b; + + if (strcmp (properties->client_id, previous_id) == 0) + return 0; + return 1; } gboolean -xfsm_manager_register_client (XfsmClient *client, +xfsm_manager_register_client (XfsmManager *manager, + XfsmClient *client, const gchar *previous_id) { XfsmProperties *properties = NULL; gchar *client_id; GList *lp; - + if (previous_id != NULL) { - for (lp = starting_properties; lp != NULL; lp = lp->next) + lp = g_queue_find_custom (manager->starting_properties, + previous_id, + xfsm_properties_queue_find); + if (lp != NULL) { - if (strcmp (XFSM_PROPERTIES (lp->data)->client_id, previous_id) == 0) - { - properties = XFSM_PROPERTIES (lp->data); - starting_properties = g_list_remove (starting_properties, - properties); - break; - } + properties = XFSM_PROPERTIES (lp->data); + g_queue_delete_link (manager->starting_properties, lp); } - - if (properties == NULL) + else { - for (lp = pending_properties; lp != NULL; lp = lp->next) + lp = g_queue_find_custom (manager->pending_properties, + previous_id, + xfsm_properties_queue_find); + if (lp != NULL) { - if (!strcmp (XFSM_PROPERTIES (lp->data)->client_id, previous_id)) - { - properties = XFSM_PROPERTIES (lp->data); - pending_properties = g_list_remove (pending_properties, - properties); - break; - } + properties = XFSM_PROPERTIES (lp->data); + g_queue_delete_link (manager->pending_properties, lp); } } @@ -565,7 +683,7 @@ xfsm_manager_register_client (XfsmClient *client, g_free (client_id); } - running_clients = g_list_append (running_clients, client); + g_queue_push_tail (manager->running_clients, client); SmsRegisterClientReply (client->sms_conn, (char *) client->id); @@ -578,7 +696,8 @@ xfsm_manager_register_client (XfsmClient *client, client); } - if ((failsafe_mode || previous_id != NULL) && state == XFSM_MANAGER_STARTUP) + if ((manager->failsafe_mode || previous_id != NULL) + && manager->state == XFSM_MANAGER_STARTUP) { /* Only continue the startup if we are either in Failsafe mode (which * means that we don't have any previous_id at all) or the previous_id @@ -586,8 +705,8 @@ xfsm_manager_register_client (XfsmClient *client, * above, previous_id will be NULL here. * See http://bugs.xfce.org/view_bug_page.php?f_id=212 for details. */ - if (starting_properties == NULL) - xfsm_startup_session_continue (); + if (g_queue_peek_head (manager->starting_properties) == NULL) + xfsm_startup_session_continue (manager); } return TRUE; @@ -595,7 +714,8 @@ xfsm_manager_register_client (XfsmClient *client, void -xfsm_manager_start_interact (XfsmClient *client) +xfsm_manager_start_interact (XfsmManager *manager, + XfsmClient *client) { /* notify client of interact */ SmsInteract (client->sms_conn); @@ -608,61 +728,68 @@ xfsm_manager_start_interact (XfsmClient *client) void -xfsm_manager_interact (XfsmClient *client, - int dialog_type) +xfsm_manager_interact (XfsmManager *manager, + XfsmClient *client, + int dialog_type) { GList *lp; - + if (G_UNLIKELY (client->state != XFSM_CLIENT_SAVING)) { xfsm_verbose ("Client Id = %s, requested INTERACT, but client is not in SAVING mode\n" " Client will be disconnected now.\n\n", client->id); - xfsm_manager_close_connection (client, TRUE); + xfsm_manager_close_connection (manager, client, TRUE); } - else if (G_UNLIKELY (state != XFSM_MANAGER_CHECKPOINT) - && G_UNLIKELY (state != XFSM_MANAGER_SHUTDOWN)) + else if (G_UNLIKELY (manager->state != XFSM_MANAGER_CHECKPOINT) + && G_UNLIKELY (manager->state != XFSM_MANAGER_SHUTDOWN)) { xfsm_verbose ("Client Id = %s, requested INTERACT, but manager is not in CheckPoint/Shutdown mode\n" - " Clinet will be disconnected now.\n\n", + " Client will be disconnected now.\n\n", client->id); - xfsm_manager_close_connection (client, TRUE); + xfsm_manager_close_connection (manager, client, TRUE); } else { - for (lp = running_clients; lp != NULL; lp = lp->next) - if (XFSM_CLIENT (lp->data)->state == XFSM_CLIENT_INTERACTING) - { - client->state = XFSM_CLIENT_WAITFORINTERACT; - return; - } + for (lp = g_queue_peek_nth_link (manager->running_clients, 0); + lp; + lp = lp->next) + { + XfsmClient *client = lp->data; + if (client->state == XFSM_CLIENT_INTERACTING) + { + client->state = XFSM_CLIENT_WAITFORINTERACT; + return; + } + } - xfsm_manager_start_interact (client); + xfsm_manager_start_interact (manager, client); } } void -xfsm_manager_interact_done (XfsmClient *client, - gboolean cancel_shutdown) +xfsm_manager_interact_done (XfsmManager *manager, + XfsmClient *client, + gboolean cancel_shutdown) { GList *lp; - + if (G_UNLIKELY (client->state != XFSM_CLIENT_INTERACTING)) { xfsm_verbose ("Client Id = %s, send INTERACT DONE, but client is not in INTERACTING state\n" " Client will be disconnected now.\n\n", client->id); - xfsm_manager_close_connection (client, TRUE); + xfsm_manager_close_connection (manager, client, TRUE); return; } - else if (G_UNLIKELY (state != XFSM_MANAGER_CHECKPOINT) - && G_UNLIKELY (state != XFSM_MANAGER_SHUTDOWN)) + else if (G_UNLIKELY (manager->state != XFSM_MANAGER_CHECKPOINT) + && G_UNLIKELY (manager->state != XFSM_MANAGER_SHUTDOWN)) { xfsm_verbose ("Client Id = %s, send INTERACT DONE, but manager is not in CheckPoint/Shutdown state\n" " Client will be disconnected now.\n\n", client->id); - xfsm_manager_close_connection (client, TRUE); + xfsm_manager_close_connection (manager, client, TRUE); return; } @@ -675,10 +802,10 @@ xfsm_manager_interact_done (XfsmClient *client, * for the interact-style field. Otherwise, cancel-shutdown must be * False. */ - if (cancel_shutdown && state == XFSM_MANAGER_SHUTDOWN) + if (cancel_shutdown && manager->state == XFSM_MANAGER_SHUTDOWN) { /* we go into checkpoint state from here... */ - state = XFSM_MANAGER_CHECKPOINT; + manager->state = XFSM_MANAGER_CHECKPOINT; /* If a shutdown is in progress, the user may have the option * of cancelling the shutdown. If the shutdown is cancelled @@ -686,25 +813,33 @@ xfsm_manager_interact_done (XfsmClient *client, * manager should send a "Shutdown Cancelled" message to each * client that requested to interact. */ - for (lp = running_clients; lp != NULL; lp = lp->next) + for (lp = g_queue_peek_nth_link (manager->running_clients, 0); + lp; + lp = lp->next) { - if (XFSM_CLIENT (lp->data)->state != XFSM_CLIENT_WAITFORINTERACT) + XfsmClient *client = lp->data; + if (client->state != XFSM_CLIENT_WAITFORINTERACT) continue; /* reset all clients that are waiting for interact */ client->state = XFSM_CLIENT_SAVING; - SmsShutdownCancelled (XFSM_CLIENT (lp->data)->sms_conn); + SmsShutdownCancelled (client->sms_conn); } } else { /* let next client interact */ - for (lp = running_clients; lp != NULL; lp = lp->next) - if (XFSM_CLIENT (lp->data)->state == XFSM_CLIENT_WAITFORINTERACT) - { - xfsm_manager_start_interact (XFSM_CLIENT (lp->data)); - break; - } + for (lp = g_queue_peek_nth_link (manager->running_clients, 0); + lp; + lp = lp->next) + { + XfsmClient *client = lp->data; + if (client->state == XFSM_CLIENT_WAITFORINTERACT) + { + xfsm_manager_start_interact (manager, client); + break; + } + } } /* restart save yourself timeout for client */ @@ -715,30 +850,31 @@ xfsm_manager_interact_done (XfsmClient *client, void -xfsm_manager_save_yourself (XfsmClient *client, - gint save_type, - gboolean shutdown, - gint interact_style, - gboolean fast, - gboolean global) +xfsm_manager_save_yourself (XfsmManager *manager, + XfsmClient *client, + gint save_type, + gboolean shutdown, + gint interact_style, + gboolean fast, + gboolean global) { gboolean shutdown_save = TRUE; - GList *lp; + GList *lp; if (G_UNLIKELY (client->state != XFSM_CLIENT_IDLE)) { xfsm_verbose ("Client Id = %s, requested SAVE YOURSELF, but client is not in IDLE mode.\n" " Client will be nuked now.\n\n", client->id); - xfsm_manager_close_connection (client, TRUE); + xfsm_manager_close_connection (manager, client, TRUE); return; } - else if (G_UNLIKELY (state != XFSM_MANAGER_IDLE)) + else if (G_UNLIKELY (manager->state != XFSM_MANAGER_IDLE)) { xfsm_verbose ("Client Id = %s, requested SAVE YOURSELF, but manager is not in IDLE mode.\n" " Client will be nuked now.\n\n", client->id); - xfsm_manager_close_connection (client, TRUE); + xfsm_manager_close_connection (manager, client, TRUE); return; } @@ -756,19 +892,26 @@ xfsm_manager_save_yourself (XfsmClient *client, } else { - if (!fast && shutdown && !shutdownDialog (&shutdown_type, &shutdown_save)) + if (!fast && shutdown && !shutdownDialog (manager->session_name, &manager->shutdown_type, &shutdown_save)) return; if (!shutdown || shutdown_save) { - state = shutdown ? XFSM_MANAGER_SHUTDOWN : XFSM_MANAGER_CHECKPOINT; + manager->state = shutdown ? XFSM_MANAGER_SHUTDOWN : XFSM_MANAGER_CHECKPOINT; /* handle legacy applications first! */ xfsm_legacy_perform_session_save (); - for (lp = running_clients; lp != NULL; lp = lp->next) + if (client->state == XFSM_CLIENT_INTERACTING) + { + client->state = XFSM_CLIENT_WAITFORINTERACT; + return; + } + for (lp = g_queue_peek_nth_link (manager->running_clients, 0); + lp; + lp = lp->next) { - XfsmClient *client = XFSM_CLIENT (lp->data); + XfsmClient *client = lp->data; /* xterm's session management is broken, so we won't * send a SAVE YOURSELF to xterms */ @@ -793,16 +936,17 @@ xfsm_manager_save_yourself (XfsmClient *client, else { /* shutdown session without saving */ - xfsm_manager_perform_shutdown (); + xfsm_manager_perform_shutdown (manager); } } } void -xfsm_manager_save_yourself_phase2 (XfsmClient *client) +xfsm_manager_save_yourself_phase2 (XfsmManager *manager, + XfsmClient *client) { - if (state != XFSM_MANAGER_CHECKPOINT && state != XFSM_MANAGER_SHUTDOWN) + if (manager->state != XFSM_MANAGER_CHECKPOINT && manager->state != XFSM_MANAGER_SHUTDOWN) { SmsSaveYourselfPhase2 (client->sms_conn); client->state = XFSM_CLIENT_SAVINGLOCAL; @@ -817,15 +961,16 @@ xfsm_manager_save_yourself_phase2 (XfsmClient *client) g_source_remove (client->save_timeout_id); client->save_timeout_id = 0; - if (!xfsm_manager_check_clients_saving ()) - xfsm_manager_maybe_enter_phase2 (); + if (!xfsm_manager_check_clients_saving (manager)) + xfsm_manager_maybe_enter_phase2 (manager); } } void -xfsm_manager_save_yourself_done (XfsmClient *client, - gboolean success) +xfsm_manager_save_yourself_done (XfsmManager *manager, + XfsmClient *client, + gboolean success) { if (client->state != XFSM_CLIENT_SAVING && client->state != XFSM_CLIENT_SAVINGLOCAL) { @@ -833,7 +978,7 @@ xfsm_manager_save_yourself_done (XfsmClient *client, "in save mode. Prepare to be nuked!\n", client->id); - xfsm_manager_close_connection (client, TRUE); + xfsm_manager_close_connection (manager, client, TRUE); } /* remove client save timeout, as client responded in time */ @@ -846,27 +991,28 @@ xfsm_manager_save_yourself_done (XfsmClient *client, client->state = XFSM_CLIENT_IDLE; SmsSaveComplete (client->sms_conn); } - else if (state != XFSM_MANAGER_CHECKPOINT && state != XFSM_MANAGER_SHUTDOWN) + else if (manager->state != XFSM_MANAGER_CHECKPOINT && manager->state != XFSM_MANAGER_SHUTDOWN) { xfsm_verbose ("Client Id = %s, send SAVE YOURSELF DONE, but manager is not in CheckPoint/Shutdown mode.\n" " Client will be nuked now.\n\n", client->id); - xfsm_manager_close_connection (client, TRUE); + xfsm_manager_close_connection (manager, client, TRUE); } else { client->state = XFSM_CLIENT_SAVEDONE; - xfsm_manager_complete_saveyourself (); + xfsm_manager_complete_saveyourself (manager); } } void -xfsm_manager_close_connection (XfsmClient *client, - gboolean cleanup) +xfsm_manager_close_connection (XfsmManager *manager, + XfsmClient *client, + gboolean cleanup) { IceConn ice_conn; - GList *lp; + GList *lp; client->state = XFSM_CLIENT_DISCONNECTED; if (client->save_timeout_id > 0) @@ -883,26 +1029,35 @@ xfsm_manager_close_connection (XfsmClient *client, IceCloseConnection (ice_conn); } - if (state == XFSM_MANAGER_SHUTDOWNPHASE2) + if (manager->state == XFSM_MANAGER_SHUTDOWNPHASE2) { - for (lp = running_clients; lp != NULL; lp = lp->next) - if (XFSM_CLIENT (lp->data)->state != XFSM_CLIENT_DISCONNECTED) - return; + for (lp = g_queue_peek_nth_link (manager->running_clients, 0); + lp; + lp = lp->next) + { + XfsmClient *client = lp->data; + if (client->state != XFSM_CLIENT_DISCONNECTED) + return; + } /* all clients finished the DIE phase in time */ - g_source_remove (die_timeout_id); + if (manager->die_timeout_id) + { + g_source_remove (manager->die_timeout_id); + manager->die_timeout_id = 0; + } gtk_main_quit (); } - else if (state == XFSM_MANAGER_SHUTDOWN || state == XFSM_MANAGER_CHECKPOINT) + else if (manager->state == XFSM_MANAGER_SHUTDOWN || manager->state == XFSM_MANAGER_CHECKPOINT) { xfsm_verbose ("Client Id = %s, closed connection in checkpoint state\n" " Session manager will show NO MERCY\n\n", client->id); /* stupid client disconnected in CheckPoint state, prepare to be nuked! */ - running_clients = g_list_remove (running_clients, client); + g_queue_remove (manager->running_clients, client); xfsm_client_free (client); - xfsm_manager_complete_saveyourself (); + xfsm_manager_complete_saveyourself (manager); } else { @@ -912,7 +1067,7 @@ xfsm_manager_close_connection (XfsmClient *client, { if (properties->restart_style_hint == SmRestartAnyway) { - restart_properties = g_list_append (restart_properties, properties); + g_queue_push_tail (manager->restart_properties, properties); client->properties = NULL; } else if (properties->restart_style_hint == SmRestartImmediately) @@ -923,14 +1078,14 @@ xfsm_manager_close_connection (XfsmClient *client, " Will be re-scheduled for run on next startup\n", properties->client_id, properties->restart_attempts); - restart_properties = g_list_append (restart_properties, properties); + g_queue_push_tail (manager->restart_properties, properties); client->properties = NULL; } #if 0 else if (xfsm_manager_run_prop_command (properties, SmRestartCommand)) { /* XXX - add a timeout here, in case the application does not come up */ - pending_properties = g_list_append (pending_properties, properties); + g_queue_push_tail (manager->pending_properties, properties); client->properties = NULL; } #endif @@ -945,7 +1100,7 @@ xfsm_manager_close_connection (XfsmClient *client, * But for now, this work-around fixes the problem of the evergrowing * number of xfwm4 session files when restarting xfwm4 within a session. */ - if (state == XFSM_MANAGER_IDLE && properties->discard_command != NULL) + if (manager->state == XFSM_MANAGER_IDLE && properties->discard_command != NULL) { xfsm_verbose ("Client Id = %s exited while in IDLE state, running " "discard command now.\n\n", properties->client_id); @@ -960,23 +1115,29 @@ xfsm_manager_close_connection (XfsmClient *client, } } - running_clients = g_list_remove (running_clients, client); + g_queue_remove (manager->running_clients, client); xfsm_client_free (client); } } void -xfsm_manager_close_connection_by_ice_conn (IceConn ice_conn) +xfsm_manager_close_connection_by_ice_conn (XfsmManager *manager, + IceConn ice_conn) { GList *lp; - - for (lp = running_clients; lp != NULL; lp = lp->next) - if (SmsGetIceConnection (XFSM_CLIENT (lp->data)->sms_conn) == ice_conn) - { - xfsm_manager_close_connection (XFSM_CLIENT (lp->data), FALSE); - break; - } + + for (lp = g_queue_peek_nth_link (manager->running_clients, 0); + lp; + lp = lp->next) + { + XfsmClient *client = lp->data; + if (SmsGetIceConnection (client->sms_conn) == ice_conn) + { + xfsm_manager_close_connection (manager, client, FALSE); + break; + } + } /* be sure to close the Ice connection in any case */ IceSetShutdownNegotiation (ice_conn, False); @@ -985,44 +1146,56 @@ xfsm_manager_close_connection_by_ice_conn (IceConn ice_conn) void -xfsm_manager_perform_shutdown (void) -{ +xfsm_manager_perform_shutdown (XfsmManager *manager) +{ GList *lp; - + /* send SmDie message to all clients */ - state = XFSM_MANAGER_SHUTDOWNPHASE2; - for (lp = running_clients; lp != NULL; lp = lp->next) - SmsDie (XFSM_CLIENT (lp->data)->sms_conn); + manager->state = XFSM_MANAGER_SHUTDOWNPHASE2; + for (lp = g_queue_peek_nth_link (manager->running_clients, 0); + lp; + lp = lp->next) + { + XfsmClient *client = lp->data; + SmsDie (client->sms_conn); + } /* give all clients the chance to close the connection */ - die_timeout_id = g_timeout_add (DIE_TIMEOUT, - (GSourceFunc) gtk_main_quit, - NULL); + manager->die_timeout_id = g_timeout_add (DIE_TIMEOUT, + (GSourceFunc) gtk_main_quit, + NULL); } gboolean -xfsm_manager_check_clients_saving (void) +xfsm_manager_check_clients_saving (XfsmManager *manager) { GList *lp; - - for (lp = running_clients; lp != NULL; lp = lp->next) - if (XFSM_CLIENT (lp->data)->state == XFSM_CLIENT_SAVING) - return TRUE; + + for (lp = g_queue_peek_nth_link (manager->running_clients, 0); + lp; + lp = lp->next) + { + XfsmClient *client = lp->data; + if (client->state == XFSM_CLIENT_SAVING) + return TRUE; + } return FALSE; } gboolean -xfsm_manager_maybe_enter_phase2 (void) +xfsm_manager_maybe_enter_phase2 (XfsmManager *manager) { gboolean entered_phase2 = FALSE; - GList *lp; + GList *lp; - for (lp = running_clients; lp != NULL; lp = lp->next) + for (lp = g_queue_peek_nth_link (manager->running_clients, 0); + lp; + lp = lp->next) { - XfsmClient *client = XFSM_CLIENT (lp->data); + XfsmClient *client = lp->data; if (client->state == XFSM_CLIENT_WAITFORPHASE2) { @@ -1043,40 +1216,43 @@ xfsm_manager_maybe_enter_phase2 (void) void -xfsm_manager_complete_saveyourself (void) +xfsm_manager_complete_saveyourself (XfsmManager *manager) { GList *lp; - + /* Check if still clients in SAVING state or if we have to enter PHASE2 * now. In either case, SaveYourself cannot be completed in this run. */ - if (xfsm_manager_check_clients_saving () || xfsm_manager_maybe_enter_phase2 ()) + if (xfsm_manager_check_clients_saving (manager) || xfsm_manager_maybe_enter_phase2 (manager)) return; xfsm_verbose ("Manager finished SAVE YOURSELF, session data will be stored now.\n\n"); /* all clients done, store session data */ - xfsm_manager_store_session (); + xfsm_manager_store_session (manager); - if (state == XFSM_MANAGER_CHECKPOINT) + if (manager->state == XFSM_MANAGER_CHECKPOINT) { /* reset all clients to idle state */ - state = XFSM_MANAGER_IDLE; - for (lp = running_clients; lp != NULL; lp = lp->next) + manager->state = XFSM_MANAGER_IDLE; + for (lp = g_queue_peek_nth_link (manager->running_clients, 0); + lp; + lp = lp->next) { - XFSM_CLIENT (lp->data)->state = XFSM_CLIENT_IDLE; - SmsSaveComplete (XFSM_CLIENT (lp->data)->sms_conn); + XfsmClient *client = lp->data; + client->state = XFSM_CLIENT_IDLE; + SmsSaveComplete (client->sms_conn); } } else { /* shutdown the session */ - xfsm_manager_perform_shutdown (); + xfsm_manager_perform_shutdown (manager); } } -gboolean +static gboolean xfsm_manager_save_timeout (gpointer client_data) { XfsmClient *client = XFSM_CLIENT (client_data); @@ -1085,14 +1261,14 @@ xfsm_manager_save_timeout (gpointer client_data) " Client will be disconnected now.\n\n", client->id); - xfsm_manager_close_connection (client, TRUE); + xfsm_manager_close_connection (client->manager, client, TRUE); return FALSE; } void -xfsm_manager_store_session (void) +xfsm_manager_store_session (XfsmManager *manager) { WnckWorkspace *workspace; GdkDisplay *display; @@ -1105,46 +1281,52 @@ xfsm_manager_store_session (void) gint count = 0; gint n, m; - rc = xfce_rc_simple_open (session_file, FALSE); + rc = xfce_rc_simple_open (manager->session_file, FALSE); if (G_UNLIKELY (rc == NULL)) { fprintf (stderr, "xfce4-session: Unable to open session file %s for " "writing. Session data will not be stored. Please check " "your installation.\n", - session_file); + manager->session_file); return; } /* backup the old session file first */ - if (g_file_test (session_file, G_FILE_TEST_IS_REGULAR)) + if (g_file_test (manager->session_file, G_FILE_TEST_IS_REGULAR)) { - backup = g_strconcat (session_file, ".bak", NULL); + backup = g_strconcat (manager->session_file, ".bak", NULL); unlink (backup); - link (session_file, backup); + link (manager->session_file, backup); g_free (backup); } - group = g_strconcat ("Session: ", session_name, NULL); + group = g_strconcat ("Session: ", manager->session_name, NULL); xfce_rc_delete_group (rc, group, TRUE); xfce_rc_set_group (rc, group); g_free (group); - for (lp = restart_properties; lp != NULL; lp = lp->next) + for (lp = g_queue_peek_nth_link (manager->restart_properties, 0); + lp; + lp = lp->next) { + XfsmProperties *properties = lp->data; g_snprintf (prefix, 64, "Client%d_", count); - xfsm_properties_store (XFSM_PROPERTIES (lp->data), rc, prefix); + xfsm_properties_store (properties, rc, prefix); ++count; } - for (lp = running_clients; lp != NULL; lp = lp->next) + for (lp = g_queue_peek_nth_link (manager->running_clients, 0); + lp; + lp = lp->next) { - if (XFSM_CLIENT (lp->data)->properties == NULL - || !xfsm_properties_check (XFSM_CLIENT (lp->data)->properties)) + XfsmClient *client = lp->data; + if (client->properties == NULL + || !xfsm_properties_check (client->properties)) continue; g_snprintf (prefix, 64, "Client%d_", count); - xfsm_properties_store (XFSM_CLIENT (lp->data)->properties, rc, prefix); + xfsm_properties_store (client->properties, rc, prefix); ++count; } @@ -1174,6 +1356,60 @@ xfsm_manager_store_session (void) } +gint +xfsm_manager_get_shutdown_type (XfsmManager *manager) +{ + return manager->shutdown_type; +} + + +GQueue * +xfsm_manager_get_queue (XfsmManager *manager, + XfsmManagerQueueType q_type) +{ + switch(q_type) + { + case XFSM_MANAGER_QUEUE_PENDING_PROPS: + return manager->pending_properties; + case XFSM_MANAGER_QUEUE_STARTING_PROPS: + return manager->starting_properties; + case XFSM_MANAGER_QUEUE_RESTART_PROPS: + return manager->restart_properties; + case XFSM_MANAGER_QUEUE_RUNNING_CLIENTS: + return manager->running_clients; + case XFSM_MANAGER_QUEUE_FAILSAFE_CLIENTS: + return manager->failsafe_clients; + default: + g_warning ("Requested invalid queue type %d", (gint)q_type); + return NULL; + } +} + + +gboolean +xfsm_manager_get_use_failsafe_mode (XfsmManager *manager) +{ + return manager->failsafe_mode; +} + + +gboolean +xfsm_manager_get_compat_startup (XfsmManager *manager, + XfsmManagerCompatType type) +{ + switch (type) + { + case XFSM_MANAGER_COMPAT_GNOME: + return manager->compat_gnome; + case XFSM_MANAGER_COMPAT_KDE: + return manager->compat_kde; + default: + g_warning ("Invalid compat startup type %d", type); + return FALSE; + } +} + + static GdkPixbuf* xfsm_manager_load_session_preview (const gchar *name) { diff --git a/xfce4-session/xfsm-manager.h b/xfce4-session/xfsm-manager.h index fa6d0d93..d86210a8 100644 --- a/xfce4-session/xfsm-manager.h +++ b/xfce4-session/xfsm-manager.h @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2003-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2008 Brian Tarricone <bjt23@cornell.edu> * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -22,10 +23,17 @@ #ifndef __XFSM_MANAGER_H__ #define __XFSM_MANAGER_H__ +#include <glib-object.h> + +G_BEGIN_DECLS + #include <libxfce4util/libxfce4util.h> #include <xfce4-session/xfsm-client.h> +#define XFSM_TYPE_MANAGER (xfsm_manager_get_type()) +#define XFSM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XFSM_TYPE_MANAGER, XfsmManager)) +#define XFSM_IS_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XFSM_TYPE_MANAGER)) #define DIE_TIMEOUT ( 7 * 1000) #define SAVE_TIMEOUT (60 * 1000) @@ -40,49 +48,104 @@ typedef enum XFSM_MANAGER_SHUTDOWNPHASE2, } XfsmManagerState; +typedef enum +{ + XFSM_MANAGER_QUEUE_PENDING_PROPS = 0, + XFSM_MANAGER_QUEUE_STARTING_PROPS, + XFSM_MANAGER_QUEUE_RESTART_PROPS, + XFSM_MANAGER_QUEUE_RUNNING_CLIENTS, + XFSM_MANAGER_QUEUE_FAILSAFE_CLIENTS, +} XfsmManagerQueueType; + +typedef enum +{ + XFSM_MANAGER_COMPAT_GNOME = 0, + XFSM_MANAGER_COMPAT_KDE, +} XfsmManagerCompatType; + +typedef struct _XfsmManager XfsmManager; -void xfsm_manager_init (XfceRc *rc); +GType xfsm_manager_get_type (void) G_GNUC_CONST; -gboolean xfsm_manager_restart (void); +XfsmManager *xfsm_manager_new (void); + +void xfsm_manager_load (XfsmManager *manager, + XfceRc *rc); + +gboolean xfsm_manager_restart (XfsmManager *manager); /* call when startup is finished */ -void xfsm_manager_signal_startup_done (void); +void xfsm_manager_signal_startup_done (XfsmManager *manager); /* call for each client that fails */ -void xfsm_manager_handle_failed_client (XfsmProperties *properties); +void xfsm_manager_handle_failed_client (XfsmManager *manager, + XfsmProperties *properties); gchar* xfsm_manager_generate_client_id (SmsConn sms_conn) G_GNUC_PURE; -XfsmClient* xfsm_manager_new_client (SmsConn sms_conn, - gchar **error); -gboolean xfsm_manager_register_client (XfsmClient *client, - const gchar *previous_id); -void xfsm_manager_start_interact (XfsmClient *client); -void xfsm_manager_interact (XfsmClient *client, - gint dialog_type); -void xfsm_manager_interact_done (XfsmClient *client, - gboolean cancel_shutdown); -void xfsm_manager_save_yourself (XfsmClient *client, - gint save_type, - gboolean shutdown, - gint interact_style, - gboolean fast, - gboolean global); -void xfsm_manager_save_yourself_phase2 (XfsmClient *client); -void xfsm_manager_save_yourself_done (XfsmClient *client, - gboolean success); -void xfsm_manager_close_connection (XfsmClient *client, - gboolean cleanup); -void xfsm_manager_close_connection_by_ice_conn (IceConn ice_conn); - -gboolean xfsm_manager_check_clients_saving (void); -gboolean xfsm_manager_maybe_enter_phase2 (void); -gboolean xfsm_manager_save_timeout (gpointer client_data); -void xfsm_manager_perform_shutdown (void); -gboolean xfsm_manager_run_command (const XfsmProperties *properties, +XfsmClient* xfsm_manager_new_client (XfsmManager *manager, + SmsConn sms_conn, + gchar **error); + +gboolean xfsm_manager_register_client (XfsmManager *manager, + XfsmClient *client, + const gchar *previous_id); + +void xfsm_manager_start_interact (XfsmManager *manager, + XfsmClient *client); + +void xfsm_manager_interact (XfsmManager *manager, + XfsmClient *client, + gint dialog_type); + +void xfsm_manager_interact_done (XfsmManager *manager, + XfsmClient *client, + gboolean cancel_shutdown); + +void xfsm_manager_save_yourself (XfsmManager *manager, + XfsmClient *client, + gint save_type, + gboolean shutdown, + gint interact_style, + gboolean fast, + gboolean global); + +void xfsm_manager_save_yourself_phase2 (XfsmManager *manager, + XfsmClient *client); + +void xfsm_manager_save_yourself_done (XfsmManager *manager, + XfsmClient *client, + gboolean success); + +void xfsm_manager_close_connection (XfsmManager *manager, + XfsmClient *client, + gboolean cleanup); + +void xfsm_manager_close_connection_by_ice_conn (XfsmManager *manager, + IceConn ice_conn); + +gboolean xfsm_manager_check_clients_saving (XfsmManager *manager); + +gboolean xfsm_manager_maybe_enter_phase2 (XfsmManager *manager); + +void xfsm_manager_perform_shutdown (XfsmManager *manager); + +gboolean xfsm_manager_run_command (XfsmManager *manager, + const XfsmProperties *properties, const gchar *command); -void xfsm_manager_store_session (void); -void xfsm_manager_complete_saveyourself (void); -#endif /* !__XFSM_MANAGER_H__ */ +void xfsm_manager_store_session (XfsmManager *manager); + +void xfsm_manager_complete_saveyourself (XfsmManager *manager); + +gint xfsm_manager_get_shutdown_type (XfsmManager *manager); + +GQueue *xfsm_manager_get_queue (XfsmManager *manager, + XfsmManagerQueueType q_type); +gboolean xfsm_manager_get_use_failsafe_mode (XfsmManager *manager); + +gboolean xfsm_manager_get_compat_startup (XfsmManager *manager, + XfsmManagerCompatType type); + +#endif /* !__XFSM_MANAGER_H__ */ diff --git a/xfce4-session/xfsm-properties.c b/xfce4-session/xfsm-properties.c index a9bf92aa..a888e73e 100644 --- a/xfce4-session/xfsm-properties.c +++ b/xfce4-session/xfsm-properties.c @@ -658,6 +658,8 @@ xfsm_properties_free (XfsmProperties *properties) { g_return_if_fail (properties != NULL); + if (properties->startup_timeout_id != 0) + g_source_remove (properties->startup_timeout_id); if (properties->client_id != NULL) g_free (properties->client_id); if (properties->hostname != NULL) diff --git a/xfce4-session/xfsm-startup.c b/xfce4-session/xfsm-startup.c index 4033cc70..a449fe2d 100644 --- a/xfce4-session/xfsm-startup.c +++ b/xfce4-session/xfsm-startup.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2003-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2008 Brian Tarricone <bjt23@cornell.edu> * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -58,17 +59,36 @@ #include "xfsm-startup.h" +typedef struct +{ + XfsmManager *manager; + XfsmProperties *properties; +} XfsmStartupTimeoutData; + +typedef struct +{ + XfsmManager *manager; + gchar *client_id; +} XfsmStartupChildWatchData; + /* Prototypes */ -static void xfsm_startup_failsafe (void); -static gboolean xfsm_startup_session_next_prio_group (void); +static void xfsm_startup_failsafe (XfsmManager *manager); + +static gboolean xfsm_startup_session_next_prio_group (XfsmManager *manager); + static void xfsm_startup_child_watch (GPid pid, gint status, gpointer user_data); static void xfsm_startup_child_watch_destroy (gpointer user_data); -static gboolean xfsm_startup_handle_failed_client (gpointer data); + +static gboolean xfsm_startup_timeout (gpointer data); +static void xfsm_startup_timeout_destroy (gpointer data); + +static void xfsm_startup_handle_failed_client (XfsmProperties *properties, + XfsmManager *manager); void xfsm_startup_init (XfceRc *rc) @@ -421,40 +441,39 @@ xfsm_startup_autostart (void) void -xfsm_startup_foreign (void) +xfsm_startup_foreign (XfsmManager *manager) { - if (compat_kde) + if (xfsm_manager_get_compat_startup(manager, XFSM_MANAGER_COMPAT_KDE)) xfsm_compat_kde_startup (splash_screen); - if (compat_gnome) + if (xfsm_manager_get_compat_startup(manager, XFSM_MANAGER_COMPAT_GNOME)) xfsm_compat_gnome_startup (splash_screen); } void -xfsm_startup_begin (void) +xfsm_startup_begin (XfsmManager *manager) { - if (failsafe_mode) + if (xfsm_manager_get_use_failsafe_mode (manager)) { - xfsm_startup_failsafe (); + xfsm_startup_failsafe (manager); xfsm_startup_autostart (); } else { - xfsm_startup_session_continue (); + xfsm_startup_session_continue (manager); } } static void -xfsm_startup_failsafe (void) +xfsm_startup_failsafe (XfsmManager *manager) { - GList *lp; + GQueue *failsafe_clients = xfsm_manager_get_queue (manager, XFSM_MANAGER_QUEUE_FAILSAFE_CLIENTS); + FailsafeClient *fclient; - for (lp = failsafe_clients; lp; lp = lp->next) + while ((fclient = g_queue_pop_head (failsafe_clients))) { - FailsafeClient *fclient = (FailsafeClient *) lp->data; - /* FIXME: splash */ /* let the user know whats going on */ if (G_LIKELY (splash_screen != NULL)) @@ -466,16 +485,12 @@ xfsm_startup_failsafe (void) /* start the application */ xfsm_start_application (fclient->command, NULL, fclient->screen, NULL, NULL, NULL); - g_strfreev (fclient->command); - g_free (fclient); + xfsm_failsafe_client_free (fclient); } - - g_list_free (failsafe_clients); - failsafe_clients = NULL; } -static gboolean +static GPid xfsm_startup_session_client (XfsmProperties *properties) { gchar **argv; @@ -513,75 +528,64 @@ xfsm_startup_session_client (XfsmProperties *properties) { /* tell the user that we failed to fork */ perror ("Failed to fork new process"); - return FALSE; + return -1; } - /* watch the child process */ - g_child_watch_add_full (G_PRIORITY_LOW, pid, xfsm_startup_child_watch, g_strdup (properties->client_id), xfsm_startup_child_watch_destroy); - properties->startup_timeout_id = g_timeout_add (STARTUP_TIMEOUT, - xfsm_startup_handle_failed_client, - properties); - return TRUE; + return pid; } void -xfsm_startup_session_continue () +xfsm_startup_session_continue (XfsmManager *manager) { + GQueue *pending_properties = xfsm_manager_get_queue (manager, XFSM_MANAGER_QUEUE_PENDING_PROPS); gboolean client_started = FALSE; /* try to start some clients. if we fail to start anything in the current * priority group, move right to the next one. if we *did* start something, * the failed/registered handlers will take care of moving us on to the * next priority group */ - while (client_started == FALSE && pending_properties != NULL) - client_started = xfsm_startup_session_next_prio_group (); + while (client_started == FALSE && g_queue_peek_head (pending_properties) != NULL) + client_started = xfsm_startup_session_next_prio_group (manager); - if (G_UNLIKELY (client_started == FALSE && pending_properties == NULL)) + if (G_UNLIKELY (client_started == FALSE && g_queue_peek_head (pending_properties) == NULL)) { /* we failed to start anything, and we don't have anything else, * to start, so just move on to the autostart items and signal * the manager that we're finished */ xfsm_startup_autostart (); - xfsm_manager_signal_startup_done (); + xfsm_manager_signal_startup_done (manager); } } /* returns TRUE if we started anything, FALSE if we didn't */ static gboolean -xfsm_startup_session_next_prio_group (void) +xfsm_startup_session_next_prio_group (XfsmManager *manager) { + GQueue *pending_properties = xfsm_manager_get_queue (manager, XFSM_MANAGER_QUEUE_PENDING_PROPS); + GQueue *starting_properties = xfsm_manager_get_queue (manager, XFSM_MANAGER_QUEUE_STARTING_PROPS); XfsmProperties *properties; gint cur_prio_group; gboolean client_started = FALSE; + GPid pid; - /* can this ever happen? */ - while (G_UNLIKELY (pending_properties && pending_properties->data == NULL)) - pending_properties = g_list_delete_link (pending_properties, pending_properties); - - if (pending_properties == NULL) + properties = (XfsmProperties *) g_queue_peek_head (pending_properties); + if (properties == NULL) return FALSE; - /* determine prio group for this run */ - properties = (XfsmProperties *) pending_properties->data; cur_prio_group = properties->priority; xfsm_verbose ("Starting apps in prio group %d\n", cur_prio_group); - while (pending_properties) + while ((properties = g_queue_pop_head (pending_properties))) { - XfsmProperties *properties = (XfsmProperties *) pending_properties->data; - - if (G_UNLIKELY (properties == NULL)) - { - pending_properties = g_list_delete_link (pending_properties, pending_properties); - continue; - } - /* quit if we've hit all the clients in the current prio group */ if (properties->priority != cur_prio_group) - break; + { + g_queue_push_head (pending_properties, properties); + break; + } /* FIXME: splash */ if (G_LIKELY (splash_screen != NULL)) @@ -590,18 +594,34 @@ xfsm_startup_session_next_prio_group (void) figure_app_name (properties->program)); } - /* it's not pending anymore... */ - pending_properties = g_list_remove (pending_properties, properties); - - if (G_LIKELY (xfsm_startup_session_client (properties))) + if (G_LIKELY ((pid = xfsm_startup_session_client (properties)) != -1)) { - starting_properties = g_list_append (starting_properties, properties); + XfsmStartupChildWatchData *cwdata; + XfsmStartupTimeoutData *stdata; + + cwdata = g_new(XfsmStartupChildWatchData, 1); + cwdata->manager = g_object_ref (manager); + cwdata->client_id = g_strdup (properties->client_id); + g_child_watch_add_full (G_PRIORITY_LOW, pid, + xfsm_startup_child_watch, cwdata, + xfsm_startup_child_watch_destroy); + + stdata = g_new(XfsmStartupTimeoutData, 1); + stdata->manager = manager; + stdata->properties = properties; + properties->startup_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT, + STARTUP_TIMEOUT, + xfsm_startup_timeout, + stdata, + xfsm_startup_timeout_destroy); + + g_queue_push_tail (starting_properties, properties); client_started = TRUE; } else { /* if starting the app failed, just ditch it */ - xfsm_manager_handle_failed_client (properties); + xfsm_manager_handle_failed_client (manager, properties); xfsm_properties_free (properties); } } @@ -615,25 +635,23 @@ xfsm_startup_child_watch (GPid pid, gint status, gpointer user_data) { - XfsmProperties *properties; - const gchar *client_id = user_data; - GList *lp; + XfsmProperties *properties; + XfsmStartupChildWatchData *cwdata = user_data; + GQueue *starting_properties; + gint i, n_items; + + starting_properties = xfsm_manager_get_queue (cwdata->manager, XFSM_MANAGER_QUEUE_STARTING_PROPS); + n_items = g_queue_get_length (starting_properties); /* check if we have a starting process with the given client_id */ - for (lp = starting_properties; lp != NULL; lp = lp->next) + for (i = 0; i < n_items; ++i) { /* check if this properties matches */ - properties = (XfsmProperties *) lp->data; - if (strcmp (properties->client_id, client_id) == 0) + properties = (XfsmProperties *) g_queue_peek_nth (starting_properties, i); + if (strcmp (properties->client_id, cwdata->client_id) == 0) { - if (properties->startup_timeout_id) - { - g_source_remove (properties->startup_timeout_id); - properties->startup_timeout_id = 0; - } - /* continue startup, this client failed most probably */ - xfsm_startup_handle_failed_client (properties); + xfsm_startup_handle_failed_client (properties, cwdata->manager); break; } } @@ -643,30 +661,49 @@ xfsm_startup_child_watch (GPid pid, static void xfsm_startup_child_watch_destroy (gpointer user_data) { - /* release the client_id */ - g_free (user_data); + XfsmStartupChildWatchData *cwdata = user_data; + + g_object_unref (cwdata->manager); + g_free (cwdata->client_id); + g_free (cwdata); } static gboolean -xfsm_startup_handle_failed_client (gpointer data) +xfsm_startup_timeout (gpointer data) +{ + XfsmStartupTimeoutData *stdata = data; + + stdata->properties->startup_timeout_id = 0; + xfsm_startup_handle_failed_client(stdata->properties, stdata->manager); + + return FALSE; +} + + +static void +xfsm_startup_timeout_destroy (gpointer data) { - XfsmProperties *properties = (XfsmProperties *) data; + g_free (data); +} - properties->startup_timeout_id = 0; - xfsm_manager_handle_failed_client (properties); +static void +xfsm_startup_handle_failed_client (XfsmProperties *properties, + XfsmManager *manager) +{ + GQueue *starting_properties = xfsm_manager_get_queue (manager, XFSM_MANAGER_QUEUE_STARTING_PROPS); + + xfsm_manager_handle_failed_client (manager, properties); - starting_properties = g_list_remove (starting_properties, properties); + g_queue_remove (starting_properties, properties); xfsm_properties_free (properties); - if (starting_properties == NULL) + if (g_queue_peek_head (starting_properties) == NULL) { /* everything has finished starting or failed; continue startup */ - xfsm_startup_session_continue (); + xfsm_startup_session_continue (manager); } - - return FALSE; } diff --git a/xfce4-session/xfsm-startup.h b/xfce4-session/xfsm-startup.h index 5aa8f330..3593b495 100644 --- a/xfce4-session/xfsm-startup.h +++ b/xfce4-session/xfsm-startup.h @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2003-2004 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2008 Brian Tarricone <bjt23@cornell.edu> * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -25,9 +26,9 @@ #include <libxfce4util/libxfce4util.h> void xfsm_startup_init (XfceRc *rc); -void xfsm_startup_foreign (void); -void xfsm_startup_begin (void); -void xfsm_startup_session_continue (void); +void xfsm_startup_foreign (XfsmManager *manager); +void xfsm_startup_begin (XfsmManager *manager); +void xfsm_startup_session_continue (XfsmManager *manager); #endif /* !__XFSM_STARTUP_H__ */ |